Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Changes-API.md b/Changes-API.md
index 4bbede7..bd2b239 100644
--- a/Changes-API.md
+++ b/Changes-API.md
@@ -1,113 +1,121 @@
# Changelog for HEJ API
This log lists only changes on the HEJ API. These are primarily code changes
relevant for calling HEJ as an API. This file should only be read as an addition
to [`Changes.md`](Changes.md), where the main features are documented.
+## Version 2.2
+
+### 2.2.0
+
+* Renamed `no_2_jets` error flag to `not_enough_jets`.
+* Added helper functions `is_backward_g_to_h`, `is_forward_g_to_h` to
+ detect incoming gluon to outgoing Higgs transitions.
+
## Version 2.1
### 2.1.0
#### Changes to Event class
* Restructured `Event` class
- `Event` can now only be build from a (new) `Event::EventData` class
- Removed default constructor for `Event`
- `Event::EventData` replaces the old `UnclusteredEvent` struct.
- `UnclusteredEvent` is now **deprecated**, and will be removed in version
2.2.0
- Removed `Event.unclustered()` function
- Added new member function `Events.parameters()`, to directly access
(underlying) `Parameters<EventParameters>`
- New member functions `begin_partons`, `end_partons` (`rbegin_partons`,
`rend_partons`) with aliases `cbegin_partons`, `cend_partons`
(`crbegin_partons`, `crend_partons`) for constant (reversed) iterators over
outgoing partons.
* New function `Event::EventData.reconstruct_intermediate()` to reconstruct
bosons from decays, e.g. `positron + nu_e => Wp`
* Added optional Colour charges to particles (`Particle.colour`)
- Colour connection in the HEJ limit can be generated via
`Event.generate_colours` (automatically done in the resummation)
- Colour configuration of input events can be checked with
`Event.is_leading_colour`
* Added function `Event.valid_hej_state` to check if event _could have_ been
produced by `HEJ` according to the `soft pt regulator` cut on the jets
#### New and updated functions
* Renamed `EventType::nonHEJ` to `EventType::non_resummable` and `is_HEJ()`
to `is_resummable()` such that run card is consistent with internal workings
* Made `MatrixElement.tree_kin(...)` and `MatrixElement.tree_param(...)` public
* New `EventReweighter` member function `treatment` to query the
treatment with respect to resummation for the various event types.
* Added auxiliary functions to obtain a `std::string` from `EventDescription`
(`to_string` for human readable, and `to_simple_string` for easy parsable
string)
* New `get_analyses` function to read in multiple `HEJ::Analysis` at once,
similar to `get_analysis`
* New `get_ew_parameters` function to extract electroweak parameters from
YAML configuration.
#### New classes
* New class `Unweighter` to do unweighting
* New class `CrossSectionAccumulator` to keep track of Cross Section of the
different subprocess
* New template struct `Parameters` similar to old `Weights`
- `Weights` are now an alias for `Parameters<double>`. Calling `Weights` did
not change
- `Weights.hh` was replaced by `Parameters.hh`. The old `Weights.hh` header
will be removed in version 2.2.0
* Function to multiplication and division of `EventParameters.weight` by double
- This can be combined with `Parameters`, e.g.
`Parameters<EventParameters>*Weights`, see also `Events.parameters()`
- Moved `EventParameters` to `Parameters.hh` header
* new class `EWConstants` replaces previously hard coded `vev`
- `EWConstants` have to be set in the general `Config` and the
`MatrixElementConfig`
#### Input/Output
* New abstract `EventReader` class, as base for reading events from files
- Moved LHE file reader to `HEJ::LesHouchesReader`
* New (optional) function `finish()` in abstract class `EventWriter`. `finish()`
is called _after_ all events are written.
* Support reading (`HDF5Reader`) and writing (`HDF5Writer`) `hdf5` files
* New `BufferedEventReader` class that allows to put events back into
the reader.
* New `SherpaLHEReader` to read Sherpa LHE files with correct weights
* `get_analysis` now requires `YAML::Node` and `LHEF::HEPRUP` as arguments
* Replaced `HepMCInterface` and `HepMCWriter` by `HepMCInterfaceX` and
`HepMCWriterX` respectively, with `X` being the major version of HepMC (2 or
3)
- Renamed `HepMCInterfaceX::init_kinematics` to `HepMCInterfaceX::init_event`
and protected it, use `HepMCInterfaceX::operator()` instead
- Removed redundant `HepMCInterfaceX::add_variation` function
#### Linking
* Export cmake target `HEJ::HEJ` to link directly against `libHEJ`
* Preprocessor flags (`HEJ_BUILD_WITH_XYZ`) for enabled/disabled dependencies
are now written to `ConfigFlags.hh`
* Provide links to version specific object files, e.g. `libHEJ.so ->
libHEJ.so.2.1 (soname) -> libHEJ.so.2.1.0`
* Removed `LHAPDF` from public interface
#### Miscellaneous
* Capitalisation of `Config.hh` now matches class `Config` (was `config.hh`)
* Renamed `Config::max_ext_soft_pt_fraction` to `Config::soft_pt_regulator`.
The new `Config::soft_pt_regulator` parameter is optional and the old
`Config::max_ext_soft_pt_fraction` is **deprecated**.
* Replaced redundant member `EventReweighterConfig::jet_param` with getter
function `EventReweighter.jet_param()` (`JetParameters` are already in
`PhaseSpacePointConfig`)
* Avoid storing reference to the Random Number Generator inside classes
- Constructors of `EventReweighter` now expect `std::shared_ptr<HEJ::RNG>`
(was reference)
- Moved reference to `HEJ::RNG` from constructor of `JetSplitter` to
`JetSplitter.split`
## Version 2.0
### 2.0.4
* Fixed wrong path of `HEJ_INCLUDE_DIR` in `hej-config.cmake`
### 2.0.0
* First release
diff --git a/Changes.md b/Changes.md
index 4cd4d0e..04ace7d 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,145 +1,153 @@
# Changelog
This is the log for changes to the HEJ program. Further changes to the HEJ API
are documented in [`Changes-API.md`](Changes-API.md). If you are using HEJ as a
library, please also read the changes there.
+## Version 2.2
+
+* Significantly improved description of Higgs boson plus jet production:
+ - Processes with extremal Higgs boson emission are now treated as
+ leading-log.
+ - Resummation is now enabled for Higgs boson production with a
+ single jet.
+
## Version 2.1
This release adds support for two new processes:
* W boson with jets.
* Jets with a charged lepton-antilepton pair via a virtual Z boson or photon.
In addition, the complete set of first subleading processes (unordered
gluon, central and extremal quark-antiquark pair) is implemented for
pure jets and W + jets, see
[arXiv:TODO](https://arxiv.org/abs/TODO). Unordered gluon emission is
also supported for Higgs boson + jets and Z boson/photon + jets.
This release include many changes to the code, which affect users of
HEJ as a library (see [`Changes-API.md`](Changes-API.md)).
### 2.1.0
#### New Processes
* Resummation for W bosons with jets
- New subleading processes `extremal qqbar` & `central qqbar` for a quark and
anti-quark in the final state, e.g. `g g => u d_bar Wm g` (the other
subleading processes also work with W's)
- `HEJFOG` can generate multiple jets together with a (off-shell) W bosons
decaying into lepton & neutrino
* Resummation for jets with a charged lepton-antilepton pair via a
virtual Z boson or photon. Includes the `unordered` subleading process.
* Resummation can now be performed on all subleading processes within pure
jets also. This includes `unordered`, `extremal qqbar` and `central
qqbar` processes.
#### More Physics implementation
* Partons now have a Colour charge
- Colours are read from and written to LHE files
- For reweighted events the colours are created according to leading colour in
the FKL limit
* Use relative fraction for soft transverse momentum in tagging jets (`soft pt
regulator`) as new (optional) parameter.
- This supersedes `min extparton pt`, which is marked **deprecated** and will
be removed in version 2.2.0
- This is a direct replacement for the old `max ext soft pt fraction`, which
is also **deprecated**.
* Changed the redistribution of the momenta of soft emissions. Now also bosons
can take part of the recoil (previously only jets).
#### Updates to Runcard
* Allow multiplication and division of multiple scale functions e.g.
`H_T/2*m_j1j2`
* Grouped `event treatment` for subleading channels together in runcard
- Rename `non-HEJ` processes to `non-resummable`
* Read electro-weak constants from input
- new mandatory setting `vev` to change vacuum expectation value
- new mandatory settings `particle properties` to specify mass & width of
bosons
- `HEJFOG`: decays are now specified in `decays` setting (previously under
`particle properties`)
* Allow loading multiple analyses with `analyses`. The old `analysis` (with "i")
is marked **deprecated**.
* Optional setting to specify maximal number of Fixed Order events (`max
events`, default is all)
* Allow changing the regulator lambda in input (`regulator parameter`, only for
advanced users)
#### Changes to Input/Output
* Added support to read & write `hdf5` event files suggested in
[arXiv:1905.05120](https://arxiv.org/abs/1905.05120) (needs
[HighFive](https://github.com/BlueBrain/HighFive))
* Support input with average weight equal to the cross section (`IDWTUP=1 or 4`)
* Support unmodified Les Houches Event Files written by Sherpa with
`cross section = sum(weights)/sum(trials)`
* Analyses now get general run information (`LHEF::HEPRUP`) in the
constructor. **This might break previously written, external analyses!**
- external analyses should now be created with
`make_analysis(YAML::Node const & config, LHEF::HEPRUP const & heprup)`
* Support `rivet` version 3 with both `HepMC` version 2 and 3
- Multiple weights with `rivet 3` will only create one `.yoda` file (instead
of one per weight/scale)
* Added option to unweight only resummation events
(`unweight: {type: resummation}`)
* Added option for partially unweighting resummation events, similar to
the fixed-order generator.
* Improved unweighting algorithm.
* Follow HepMC convention for particle Status codes: incoming = 11,
decaying = 2, outgoing = 1 (unchanged)
#### Miscellaneous
* Print cross sections at end of run
* Added example analysis & scale to `examples/`. Everything in `examples/` will
be build when the flag `-DBUILD_EXAMPLES=TRUE` is set in `cmake`.
* Dropped support for HepMC 3.0.0, either HepMC version 2 or >3.1 is required
- It is now possible to write out both HepMC 2 and HepMC 3 events at the same
time
* Require LHADPF version 6. Dropped support for all other versions.
* Use `git-lfs` for raw data in test (`make test` now requires `git-lfs`)
* Currents are now generated with [`FORM`](https://github.com/vermaseren/form)
- `FORM` is included as a `git submodule`, use `git submodule update --init`
to download `FORM`
* Create [Sphinx](http://sphinx-doc.org/) and [Doxygen](http://doxygen.org/)
documentation by `make sphinx` or `make doxygen` in your `build/` folder
## Version 2.0
First release of HEJ 2. Complete code rewrite compared to HEJ 1. Improved
matching to Fixed Order ([arXiv:1805.04446](https://arxiv.org/abs/1805.04446)).
Implemented processes: Higgs boson with jets (FKL and unordered gluon emission,
with finite quark mass loop,
[arXiv:1812.08072](https://arxiv.org/abs/1812.08072)), and pure jets (only FKL).
See [arXiv:1902.08430](https://arxiv.org/abs/1902.08430)
### 2.0.6
* Fixed compiling rivet when YODA headers are _outside_ of rivet directory
### 2.0.5
* Fixed event classification for input not ordered in rapidity
### 2.0.4
* Fixed wrong path of `HEJ_INCLUDE_DIR` in `hej-config.cmake`
### 2.0.3
* Fixed parsing of (numerical factor) * (base scale) in configuration
* Don't change scale names, but sanitise Rivet output file names instead
### 2.0.2
* Changed scale names to `"_over_"` and `"_times_"` for proper file names (was
`"/"` and `"*"` before)
### 2.0.1
* Fixed name of fixed-order generator in error message.
### 2.0.0
* First release
diff --git a/FixedOrderGen/t/CMakeLists.txt b/FixedOrderGen/t/CMakeLists.txt
index b2f0fef..354b0be 100644
--- a/FixedOrderGen/t/CMakeLists.txt
+++ b/FixedOrderGen/t/CMakeLists.txt
@@ -1,213 +1,213 @@
set(tst_dir "${CMAKE_CURRENT_SOURCE_DIR}")
set(runcard_dir ${tst_dir}/runcards)
function(add_long_test)
set(options NONE)
set(oneValueArgs NAME)
set(multiValueArgs COMMAND)
cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
add_test(
NAME ${TEST_NAME}_short
COMMAND ${TEST_COMMAND} short
)
if(TEST_ALL)
add_test(
NAME ${TEST_NAME}
COMMAND ${TEST_COMMAND}
)
endif()
endfunction()
foreach(tst W_reconstruct_enu W_2j_classify W_nj_classify)
add_executable(test_${tst} ${tst_dir}/${tst}.cc)
target_link_libraries(test_${tst} hejfog_lib)
add_test(NAME ${tst}
COMMAND test_${tst}
WORKING_DIRECTORY ${runcard_dir}
)
endforeach()
# this only tests if the runcard actually works, not if the result is correct
add_test(
NAME main_example
COMMAND HEJFOG ${PROJECT_SOURCE_DIR}/configFO.yml
)
add_test(
NAME main_2j
COMMAND HEJFOG ${runcard_dir}/2j.yml
)
add_test(
NAME main_h2j
COMMAND HEJFOG ${runcard_dir}/h2j.yml
)
add_test(
NAME main_h2j_decay
COMMAND HEJFOG ${runcard_dir}/h2j_decay.yml
)
add_test(
NAME peakpt
COMMAND HEJFOG ${runcard_dir}/2j_peak.yml
)
# special case where coupling not trivial
add_test(
NAME main_W4j_uno+eqqbar
COMMAND HEJFOG ${runcard_dir}/Wp4j_uno+eqqbar.yml
)
# check that uno emission doesn't change FKL xs
add_executable(FKL_uno FKL_uno.cc)
target_link_libraries(FKL_uno hejfog_lib)
add_test(
NAME FKL_uno
# calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
COMMAND FKL_uno ${runcard_dir}/h3j_uno.yml 0.0243548 0.000119862
)
# xs tests
add_executable(xs_gen xs_gen.cc)
target_link_libraries(xs_gen hejfog_lib)
## Higgs
add_test(
NAME xs_hqQ
# calculated with Sherpa see #132
COMMAND xs_gen ${runcard_dir}/hqQ.yml 1.612e-02 1.26303e-04
)
add_test(
NAME xs_h2j
# calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
- COMMAND xs_gen ${runcard_dir}/h2j.yml 2.04928 0.00956022
+ COMMAND xs_gen ${runcard_dir}/h2j.yml 2.07698 0.0096357
)
add_test(
NAME xs_h3j
# calculated with HEJ revision bd4388fe55cbc3f5a7b6139096456c551294aa31
- COMMAND xs_gen ${runcard_dir}/h3j.yml 1.07807 0.0132409
+ COMMAND xs_gen ${runcard_dir}/h3j.yml 0.93163 0.0078376
)
add_long_test(
NAME xs_h3j_uno
# calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
COMMAND xs_gen ${runcard_dir}/h3j_uno.yml 0.00347538 3.85875e-05
)
add_test(
NAME xs_h5j
# calculated with HEJ revision dbde2ffbb3b383ae6709b2424d8f0f9d5658270b
- COMMAND xs_gen ${runcard_dir}/h5j.yml 0.0112504 0.000199633
+ COMMAND xs_gen ${runcard_dir}/h5j.yml 0.0104322 1.848913e-04
)
add_test(
NAME xs_h2j_decay
# calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
- COMMAND xs_gen ${runcard_dir}/h2j_decay.yml 0.00466994 2.20995e-05
+ COMMAND xs_gen ${runcard_dir}/h2j_decay.yml 4.760767e-03 2.242386e-05
)
## pure jets
add_test(
NAME xs_qQ
# calculated with Sherpa see #132
COMMAND xs_gen ${runcard_dir}/qQ.yml 7.354e+05 1.905e+03
)
add_test(
NAME xs_2j
# calculated with "combined" HEJ svn r3480
COMMAND xs_gen ${runcard_dir}/2j.yml 86.42031848e06 590570
)
add_test(
NAME xs_3j_uno
# calculated with HEJ revision 59b8452accfe1462796406fa8e008c8b16b9657b
COMMAND xs_gen ${runcard_dir}/3j_uno.yml 1.449280e+05 2.318716e+03
)
add_test(
NAME xs_3j_qqbar
# calculated with HEJ revision 9401196fba75b5d16bc33f2a309175fecaca00f1
COMMAND xs_gen ${runcard_dir}/3j_qqbar.yml 62040 1005
)
add_long_test(
NAME xs_4j_qqbar
# calculated with HEJ revision 9401196fba75b5d16bc33f2a309175fecaca00f1
COMMAND xs_gen ${runcard_dir}/4j_qqbar.yml 28936 550
)
add_test(
NAME xs_4j
# calculated with HEJ revision 59b8452accfe1462796406fa8e008c8b16b9657b
COMMAND xs_gen ${runcard_dir}/4j.yml 1.042808e+06 2.137257e+04
)
## W
add_test(
NAME xs_WqQ
# calculated with Sherpa see #132
COMMAND xs_gen ${runcard_dir}/WpqQ.yml 3.086e+00 4.511e-02
)
add_test(
NAME xs_W2j
# calculated with HEJ revision 449f2f6b597020e9c9e35699568edc05c827fc11+1
COMMAND xs_gen ${runcard_dir}/Wm2j.yml 4.177443e+02 7.446928e+00
)
add_long_test(
NAME xs_W3j_eqqbar
# calculated with HEJ revision 667eb768fbefa99148bf6fe9ffb6fcd16c0f976e
COMMAND xs_gen ${runcard_dir}/Wp3j_qqbar.yml 2.267785e+01 3.707774e-01
)
add_long_test(
NAME xs_W3j_uno
# calculated with HEJ revision 449f2f6b597020e9c9e35699568edc05c827fc11+1
COMMAND xs_gen ${runcard_dir}/Wp3j_uno.yml 3.000955e-01 5.831799e-03
)
add_long_test(
NAME xs_W4j_qqbar
# calculated with HEJ revision 667eb768fbefa99148bf6fe9ffb6fcd16c0f976e
COMMAND xs_gen ${runcard_dir}/Wp4j_qqbar.yml 1.159881e-01 3.633528e-03
)
# Test that sum of partons == proton
add_executable(PSP_channel PSP_channel.cc)
target_link_libraries(PSP_channel hejfog_lib)
# pure jets
add_long_test(
NAME channel_2j
COMMAND PSP_channel ${runcard_dir}/2j.yml
)
add_test(
NAME channel_3j_qqbar
COMMAND PSP_channel ${runcard_dir}/3j_qqbar.yml
)
add_long_test(
NAME channel_3j_uno
COMMAND PSP_channel ${runcard_dir}/3j_uno.yml
)
add_long_test(
NAME channel_4j_qqbar
COMMAND PSP_channel ${runcard_dir}/4j_qqbar.yml
)
# W+jets
# pure jets
add_long_test(
NAME channel_W2j
COMMAND PSP_channel ${runcard_dir}/Wm2j.yml
)
add_long_test(
NAME channel_W3j_uno
COMMAND PSP_channel ${runcard_dir}/Wp3j_uno.yml
)
add_long_test(
NAME channel_W3j_eqqbar
COMMAND PSP_channel ${runcard_dir}/Wp3j_qqbar.yml
)
add_long_test(
NAME channel_W4j_qqbar
COMMAND PSP_channel ${runcard_dir}/Wp4j_qqbar.yml
)
# Test that each subleading channel is generated consistently
add_executable(PSP_subl PSP_subl.cc)
target_link_libraries(PSP_subl hejfog_lib)
add_long_test(
NAME subl_5j
COMMAND PSP_subl ${runcard_dir}/5j.yml
)
add_long_test(
NAME subl_h5j
COMMAND PSP_subl ${runcard_dir}/h5j.yml
)
add_long_test(
NAME subl_W3j
COMMAND PSP_subl ${runcard_dir}/Wp3j_qqbar.yml
)
add_long_test(
NAME subl_W5j
COMMAND PSP_subl ${runcard_dir}/Wm5j.yml
)
diff --git a/current_generator/include/currents.frm b/current_generator/include/currents.frm
index 9f9a68d..c2cfd6c 100644
--- a/current_generator/include/currents.frm
+++ b/current_generator/include/currents.frm
@@ -1,134 +1,66 @@
*/**
* \brief Predefined current functions and polarisation vectors
*
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2020
* \copyright GPLv2 or later
*/
#ifndef `$HEJCurrentsIncluded'
#$HEJCurrentsIncluded = 1;
-* Extremal Higgs boson emission vertex
-cfunction JH;
* FKL current for vector boson
cfunction JV;
* Polarisation vectors
cfunction Eps;
* Polarisation vectors contracted with Higgs emission vertex
cfunction EPSH;
* Higgs emission vertex
cfunction VH;
cfunction m2,plus,minus,perphat,sqrt,conj,dot;
-cf T1,T2;
-cf <H1DD>,...,<H12DD>;
+s T1,T2;
* internal symbols are all uppercase
symbols H, H1, HL, M;
indices MU1,...,MU50;
vectors PA,P1,PH,PLBAR,PL,PG,PR,Q1,Q2;
#procedure InsSpecialCurrents
#call InsJV
- #call InsJH
#call InsEps
#call InsVH
#endprocedure
* Replace vector boson FKL current
#procedure InsJV()
* we use a loop here to introduce a new dummy index for each occurence
repeat;
once JV(H1?, HL?, MU1?, PA?, P1?, PLBAR?, PL?) = Current(HL, PL, MU2, PLBAR)*(
+ Current(H1, P1, MU2, P1+PLBAR+PL, MU1, PA)/m2(P1+PLBAR+PL)
+ Current(H1, P1, MU1, PA-PLBAR-PL, MU2, PA)/m2(PA-PLBAR-PL)
);
sum MU2;
endrepeat;
#endprocedure
* Replace polarisation vectors by currents
#procedure InsEps()
id Conjugate(Eps(H1?, MU1?, PG?, PR?)) = - Eps(-H1, MU1, PG, PR);
id Eps(-1, MU1?, PG?, PR?) = sqrt(2)/2*SpinorChain(PR, MU1, PG)/AngleChain(PG,PR);
id Eps(+1, MU1?, PG?, PR?) = sqrt(2)/2*SpinorChain(PG, MU1, PR)/SquareChain(PG,PR);
#endprocedure
* Higgs emission vertex
* see eq:VH in developer manual, but without overall prefactor
#procedure InsVH()
id VH(MU1?, MU2?, Q1?, Q2?) = d_(MU1, MU2)*T1 - Q2(MU1)*Q1(MU2)*T2;
#endprocedure
-* Higgs currents
-* see eq:jH_same_helicity and jH_helicity_flip in developer manual
-* the overall prefactor is omitted
-#procedure InsJH()
-
- id JH(+1, +1, MU1?, P1?, PA?, PH?, M?) =
- conj(perphat(P1))*m2(PA - P1 - PH)*(
- - sqrt(2*minus(P1)/minus(PA))/square(PA, P1)*Conjugate(EPSH(+1, MU1, P1, PH, PA, M))
- + sqrt(2*minus(PA)/minus(P1))/angle(P1, PA)*EPSH(+1, MU1, PA, PH, P1, M)
- )
- + sqrt(2)*Current(+1, P1, PH, PA)*(
- + EPSH(+1, MU1, PA, PH, P1, M)/angle(P1, PA)
- + Conjugate(EPSH(+1, MU1, P1, PH, PA, M))/square(PA, P1)
- - angle(P1, PA)/(2*m2(PA - PH))*T2(PA, PA-PH, M)*Conjugate(Eps(+1, MU1, P1, PA))
- - square(PA, P1)/(2*m2(P1 + PH))*T2(P1+PH, P1, M)*Eps(+1, MU1, PA, P1)
- - 4*pi_^2*i_*H4DD(P1, -PA, PH, M)/square(PA, P1)*Conjugate(Eps(+1, MU1, P1, PA))
- + 4*pi_^2*i_*H5DD(P1, -PA, PH, M)/angle(P1, PA)*Eps(+1, MU1, PA, P1)
- )
- - 4*pi_^2*i_*Current(+1, P1, PH, PA)^2/m2(PA-P1)*(
- PA(MU1)*H10DD(P1, -PA, PH, M) - P1(MU1)*H12DD(P1, -PA, PH, M)
- )
- ;
-
-* TODO:
-* signs of negative-helicity polarisation vectors
-* and of the terms proportional to H10, H12
-* differ from developer manual and arXiv:1812.08072
- id JH(+1, -1, MU1?, P1?, PA?, PH?, M?) =
- m2(PA - P1 - PH)/square(PA, P1)*(
- + sqrt(2*minus(P1)/minus(PA))*conj(perphat(P1))*Conjugate(EPSH(-1, MU1, P1, PH, PA, M))
- + sqrt(2*minus(PA)/minus(P1))*perphat(P1)*EPSH(+1, MU1, PA, PH, P1, M)
- )
- + sqrt(2)*Current(+1, P1, PH, PA)*(
- - Conjugate(EPSH(-1, MU1, P1, PH, PA, M))/square(PA, P1)
- + angle(P1, PA)/(2*m2(PA - PH))*T2(PA, PA-PH, M)*Conjugate(Eps(-1, MU1, P1, PA))
- + 4*pi_^2*i_*H4DD(P1, -PA, PH, M)/square(PA, P1)*Conjugate(Eps(-1, MU1, P1, PA))
- )
- + sqrt(2)*Current(+1, PA, PH, P1)*(
- + EPSH(+1, MU1, PA, PH, P1, M)/square(PA, P1)
- - angle(P1, PA)/(2*m2(P1 + PH))*T2(P1+PH, P1, M)*Eps(+1, MU1, PA, P1)
- + 4*pi_^2*i_*H5DD(P1, -PA, PH, M)/square(PA, P1)*Eps(+1, MU1, PA, P1)
- )
- + 4*pi_^2*i_*Current(+1, P1, PH, PA)*Current(+1, PA, PH, P1)/square(PA, P1)^2*(
- PA(MU1)*H10DD(P1, -PA, PH, M) - P1(MU1)*H12DD(P1, -PA, PH, M)
- )
- + angle(P1, PA)/square(PA, P1)*(
- + 8*pi_^2*i_*H1DD(P1, -PA, PH, M)*P1(MU1)
- - 8*pi_^2*i_*H2DD(P1, -PA, PH, M)*PA(MU1)
- + 2*dot(P1, PH)*T2(P1+PH, P1, M)/m2(P1+PH)*PA(MU1)
- - 2*dot(PA, PH)*T2(PA, PA-PH, M)/m2(PA-PH)*P1(MU1)
- + T1(PA-P1, PA-P1-PH, M)/m2(PA-P1)*(P1(MU1) + PA(MU1))
- - dot(P1+PA, PH)/m2(PA-P1)*T2(PA-P1, PA-P1-PH, M)*(P1(MU1) - PA(MU1))
- );
-
-* eq:eps_H in developer manual
- id EPSH(H1?, MU1?, PA?, PH?, P1?, M?) = T2(PA, PA-PH, M)/m2(PA - PH)*(
- dot(PA,PH)*Eps(H1, MU1, PA, P1) - Eps(H1, PH, PA, P1)*PA(MU1)
- );
- id Conjugate(EPSH(H1?, MU1?, P1?, PH?, PA?, M?)) = -T2(P1+PH, P1, M)/m2(P1 + PH)*(
- dot(P1,PH)*Conjugate(Eps(H1, MU1, P1, PA)) - Conjugate(Eps(H1, PH, P1, PA))*P1(MU1)
- );
-
-#endprocedure
-
#endif
diff --git a/current_generator/jgh_j.frm b/current_generator/jgh_j.frm
new file mode 100644
index 0000000..71ffddf
--- /dev/null
+++ b/current_generator/jgh_j.frm
@@ -0,0 +1,41 @@
+*/**
+* \brief Contraction of g -> H current with FKL current
+*
+* \authors The HEJ collaboration (see AUTHORS for details)
+* \date 2020
+* \copyright GPLv2 or later
+*
+* The Higgs boson momentum is decomposed as pH = pH1 + pH2
+* such that pH1, pH2 are both lightlike with positive energy
+*
+* See eq:S_gf_Hf in developer manual.
+*/
+#include- include/helspin.frm
+#include- include/write.frm
+
+v pa,pb,pn,pH,pH1,pH2,pr;
+i mu,nu;
+
+#do h1={+,-}
+ #do h2={+,-}
+ l [jgh_j `h1'`h2'] = (
+ Eps(`h1'1, mu, pa, pr)
+ *VH(mu, nu, pa, pa-pH)
+ *Current(`h2'1, pn, nu, pb)
+ );
+ #enddo
+#enddo
+
+multiply replace_(
+ pH, pH1 + pH2,
+ pr, pb
+);
+
+#call ContractCurrents
+.sort
+format O4;
+format c;
+#call WriteHeader(`OUTPUT')
+#call WriteOptimised(`OUTPUT',jgh_j,2,pa,pb,pn,pH1,pH2,COMPLEX:,T1,T2)
+#call WriteFooter(`OUTPUT')
+.end
diff --git a/current_generator/jh_j.frm b/current_generator/jh_j.frm
deleted file mode 100644
index caf2252..0000000
--- a/current_generator/jh_j.frm
+++ /dev/null
@@ -1,77 +0,0 @@
-*/**
-* \brief Contraction of extremal Higgs boson emission current with FKL current
-*
-* \authors The HEJ collaboration (see AUTHORS for details)
-* \date 2020
-* \copyright GPLv2 or later
-*
-*/
-#include- include/helspin.frm
-#include- include/write.frm
-
-v pb,p2,pa,p1,ph,ph1,ph2;
-i mu;
-s mq;
-
-* backward (p1.z < 0)
-* the first helicity corresponds to the outgoing gluon,
-* where - corresponds to a helicity flip
-* h2 is the helicity of the current without Higgs emission
-#do h2={+,-}
- l [jh_j_backward +`h2'] = (
- JH(+1, +1, mu, p1, pa, ph, mq)
- *Current(`h2'1, p2, mu, pb)
- );
- l [jh_j_backward -`h2'] = (
- JH(+1, -1, mu, p1, pa, ph, mq)
- *Current(`h2'1, p2, mu, pb)
- );
-#enddo
-
-multiply replace_(
- ph, ph1 + ph2
-);
-
-#call ContractCurrents
-.sort
-skip;
-
-* forward (p1.z > 0)
-#do hout={+,-}
- #do h2={+,-}
- l [jh_j_forward `hout'`h2'] = [jh_j_backward `hout'`h2'];
- #enddo
-#enddo
-
-multiply replace_(minus,plus);
-id perphat(p1) = -1;
-id conj(perphat(p1)) = -1;
-.sort
-
-format O4;
-format c;
-#call WriteHeader(`OUTPUT')
-#write <`OUTPUT'> " namespace currents {"
-#write <`OUTPUT'> " namespace {"
-#do i=1,2
- #write <`OUTPUT'> " std::complex<double> T`i'("
- #write <`OUTPUT'> " CLHEP::HepLorentzVector const & q1,"
- #write <`OUTPUT'> " CLHEP::HepLorentzVector const & q2,"
- #write <`OUTPUT'> " double m"
- #write <`OUTPUT'> " );"
-#enddo
-#do i={1,2,4,5,10,12}
- #write <`OUTPUT'> " std::complex<double> H`i'DD("
- #write <`OUTPUT'> " CLHEP::HepLorentzVector const & k1,"
- #write <`OUTPUT'> " CLHEP::HepLorentzVector const & k2,"
- #write <`OUTPUT'> " CLHEP::HepLorentzVector const & kh,"
- #write <`OUTPUT'> " double mq"
- #write <`OUTPUT'> " );"
-#enddo
-#write <`OUTPUT'> " }"
-#write <`OUTPUT'> " }"
-#do DIR={backward,forward}
- #call WriteOptimised(`OUTPUT',jh_j_`DIR',2,pa,p1,pb,p2,ph1,ph2,DOUBLE:,mq)
-#enddo
-#call WriteFooter(`OUTPUT')
-.end
diff --git a/current_generator/juno_jgh.frm b/current_generator/juno_jgh.frm
new file mode 100644
index 0000000..80d46ba
--- /dev/null
+++ b/current_generator/juno_jgh.frm
@@ -0,0 +1,74 @@
+*/**
+* \brief Contraction of unordered current with g -> h current
+*
+* \authors The HEJ collaboration (see AUTHORS for details)
+* \date 2020
+* \copyright GPLv2 or later
+*/
+#include- include/helspin.frm
+#include- include/write.frm
+
+v pb,pa,p1,pg,q2,q3,p,pr,pr2,pH,pH1,pH2;
+i mu,nu,sigma;
+s h,foo,bar;
+
+#do h1={+,-}
+* eq:juno in developer manual with p1 -> pg, p2 -> p1
+ l [U1_jgh `h1'] = (
+ + Current(`h1'1, p1, nu, pg)*Current(`h1'1, pg, mu, pa)
+ + 2*p1(nu)*Current(`h1'1, p1, mu, pa)
+ )/m2(p1 + pg);
+ l [U2_jgh `h1'] = (
+ + 2*Current(`h1'1, p1, mu, pa)*pa(nu)
+ - Current(`h1'1, p1, mu, pg)*Current(`h1'1, pg, nu, pa)
+ )/m2(pa - pg);
+ l [L_jgh `h1'] = (
+ - (q2(nu) + q3(nu))*Current(`h1'1, p1, mu, pa)
+ - 2*pg(mu)*Current(`h1'1, p1, nu, pa)
+ + 2*Current(`h1'1, p1, pg, pa)*d_(mu, nu)
+ + 2*m2(q2)*Current(`h1'1, p1, mu, pa)*pb(nu)/m2(pb+pg)
+ )/m2(q3);
+#enddo
+multiply replace_(
+ q2,p1+pg-pa,
+ q3,p1-pa
+);
+.sort
+drop;
+
+* multiply with polarisation vector and other current
+#do h1={+,-}
+ #do h2={+,-}
+ #do hg={+,-}
+ #do TENSOR={U1_jgh,U2_jgh,L_jgh}
+ l [`TENSOR' `h1'`h2'`hg'] = (
+ [`TENSOR' `h1']
+ *Eps(`hg'1, nu, pg, pr)
+ *VH(sigma, mu, pb, pb-pH)
+ *Eps(`h2'1, sigma, pb, pr2)
+ );
+ #enddo
+ #enddo
+ #enddo
+#enddo
+
+* choice of auxiliary vectors
+multiply replace_(
+ pr,p1,
+ pr2,p1
+);
+
+multiply replace_(pH, pH1+pH2);
+.sort
+#call ContractCurrents
+id sqrt(2)*sqrt(2) = 2;
+id pa?.pb? = dot(pa, pb);
+.sort
+format O4;
+format c;
+#call WriteHeader(`OUTPUT')
+#do UNOTENSOR={U1,U2,L}
+ #call WriteOptimised(`OUTPUT',`UNOTENSOR'_jgh,3,pg,p1,pa,pH1,pH2,pb,COMPLEX:,T1,T2)
+#enddo
+#call WriteFooter(`OUTPUT')
+.end
diff --git a/doc/developer_manual/currents.tex b/doc/developer_manual/currents.tex
index e142aff..0116a24 100644
--- a/doc/developer_manual/currents.tex
+++ b/doc/developer_manual/currents.tex
@@ -1,717 +1,594 @@
\section{Currents}
\label{sec:currents_impl}
The following section contains a list of all the currents implemented
in \HEJ. Clean up of the code structure is ongoing. All $W$+Jet
currents are located in \texttt{src/Wjets.cc}, all Higgs+Jets currents
are defined in \texttt{src/Hjets.cc}, Z/$\gamma$ + Jet currents are in
\texttt{src/Zjets.cc} and pure jet currents are defined in in
\texttt{src/jets.cc}. All of these have their own separate header
files: \texttt{include/HEJ/Wjets.hh}, \texttt{include/HEJ/Hjets.hh},
\texttt{include/HEJ/Zjets.hh} and \texttt{include/HEJ/jets.hh}
respectively.
The naming convention for the current contraction $\left\|S_{f_1 f_2\to f_1
f_2}\right\|^2$ is \lstinline!ME_[Boson]_[subleading-type]_[incoming]!. For
example \lstinline!ME_W_unob_qq! corresponds to the contraction $j_W^\mu
j_{\text{uno}, \mu}$ ($qQ\to \bar{q}WQg$). For bosons on the same side as the
subleading we drop the connecting underscore, e.g. \lstinline!ME_Wuno_qq!
gives $j_{W,\text{uno}}^\mu j_\mu$ ($qQ\to g\bar{q}WQ$).
\subsection{Pure Jets}
\subsubsection{Quark}
\label{sec:current_quark}
\begin{align}
j_\mu(p_i,p_j)=\bar{u}(p_i)\gamma_\mu u(p_j)
\end{align}
The exact form depends on the helicity and direction (forward/backwards) for the quarks.
\subsubsection{Gluon}
In \HEJ the currents for gluons and quarks are the same, up to a colour factor $K_g/C_F$, where
\begin{align}
K_g(p_1^-, p_a^-) = \frac{1}{2}\left(\frac{p_1^-}{p_a^-} + \frac{p_a^-}{p_1^-}\right)\left(C_A -
\frac{1}{C_A}\right)+\frac{1}{C_A}.
\end{align}
Thus we can just reuse the results from sec.~\ref{sec:current_quark}.
\subsubsection{Single unordered gluon}
Configuration $q(p_a) \to g(p_1) q(p_2) g^*(\tilde{q}_2)$~\cite{Andersen:2017kfc}
\begin{align}
\label{eq:juno}
\begin{split}
&j^{{\rm uno}\; \mu\ cd}(p_2,p_1,p_a) = i \varepsilon_{1\nu} \left( T_{2i}^{c}T_{ia}^d\
\left(U_1^{\mu\nu}-L^{\mu\nu} \right) + T_{2i}^{d}T_{ia}^c\ \left(U_2^{\mu\nu} +
L^{\mu\nu} \right) \right). \\
U_1^{\mu\nu} &= \frac1{s_{21}} \left( j_{21}^\nu j_{1a}^\mu + 2 p_2^\nu
j_{2a}^\mu \right) \qquad \qquad U_2^{\mu\nu} = \frac1{t_{a1}} \left( 2
j_{2a}^\mu p_a^\nu - j_{21}^\mu j_{1a}^\nu \right) \\
L^{\mu\nu} &= \frac1{t_{a2}} \left(-2p_1^\mu j_{2a}^\nu+2p_1.j_{2a}
g^{\mu\nu} + (\tilde{q}_1+\tilde{q}_2)^\nu j_{2a}^\mu + \frac{t_{b2}}{2} j_{2a}^\mu \left(
\frac{p_2^\nu}{p_1.p_2} + \frac{p_b^\nu}{p_1.p_b} \right) \right) ,
\end{split}
\end{align}
$j^{{\rm uno}\; \mu}$ is currently not calculated as a separate current, but always as needed for the ME (i.e. in \lstinline!ME_unob_XX!).
\subsubsection{Extremal \texorpdfstring{$q\bar{q}$}{qqbar}}
In Pure jets we also include the subleading process which arises when
an incoming gluon splits into a $q\bar{q}$ pair. This splitting impact
factor is related to the unordered current by simple means of a
crossing symmetry.
\subsubsection{Central \texorpdfstring{$q\bar{q}$}{qqbar}}
The final subleading process type in the Pure Jets case is Central
$q\bar{q}$. In this process type, we have two currents scattering off
of each other, but this time, via an effective vertex, which connects
together two FKL chains. Each FKL chain t-channel gluon splits into a
$q\bar{q}$ and this results in a quark and anti-quark in between the
most forward and backward jets. One can see an example of such a
process in Figure \ref{fig:qqbarcen_example}.
\begin{figure}[ht]
\centering
\includegraphics[]{Cenqqbar_jx}
\caption{Momentum labeling for a central $q\bar{q}$ process.}
\label{fig:qqbarcen_example}
\end{figure}
As the new central $q\bar{q}$ piece contains the quark propagator, we will treat
this as part of the skeleton process. This means that we do not impose strong ordering
between the $q\bar{q}$-pair taking
\begin{align}
\label{eq:cenqqbarraporder}
y_1 \ll y_q,y_{\bar{q}} \ll y_n.
\end{align}
The HEJ Matrix element for this process can be calculated as:
\begin{align}
\label{eq:Mcentral}
i\mathcal{M} &= g_s^4 T^d_{1a} T^e_{nb}\ \frac{j_{\mu}(p_a,p_1)\ X^{ab\, \mu
\nu}_{{\rm cen}}(p_q,p_{\bar{q}},q_1,q_3)\
j_{\nu}(p_b,p_n)}{t_{a1}t_{bn}}.
\end{align}
where $X^{\mu \nu}_{\rm cen}$ is given by:
\begin{equation}
\label{eq:Xcen}
\begin{split}
X^{\mu \nu}_{\rm cen} ={}&\frac{f^{ced}T^c_{q\bar{q}}}{s_{q\bar{q}}}
\left(\eta^{\mu \nu} X_{sym}^\sigma + V^{\mu \nu \sigma}_{\bar{q}g} \right)
\bar{u}(p_q) \gamma^\sigma u(p_{\bar{q}}) \\ & \qquad + \frac{i
T^d_{qj}T^e_{j\bar{q}}}{(q_1-p_q)^2} X^{\mu\nu}_{\text{qprop}} - \frac{i
T^e_{qj}T^d_{j\bar{q}}}{(q_1-p_{\bar{q}})^2} X^{\mu\nu}_{\text{crossed}}\,,
\end{split}
\end{equation}
with
\begin{align}
\label{eq:Xsym}
X_{sym}^\sigma ={}& q_1^2 \left(
\frac{p_a^\sigma}{s_{aq} + s_{a\bar{q}}} + \frac{p_1^\sigma}{s_{1q} + s_{1\bar{q}}}
\right) - q_3^2 \left(
\frac{p_b^\sigma}{s_{bq} + s_{b\bar{q}}} + \frac{p_n^\sigma}{s_{nq} + s_{n\bar{q}}}
\right)\,,\\
\label{eq:V3g}
V_{3g}^{\mu\nu\sigma} ={}& (q_1 + p_q + p_{\bar{q}})^\nu \eta^{\mu\sigma}
+ (q_3 - p_q - p_{\bar{q}})^\mu \eta^{\nu\sigma}
- (q_1 + q_3)^\sigma \eta^{\mu\nu}\,,\\
\label{eq:Xqprop}
X^{\mu\nu}_{\text{qprop}} ={}& \frac{\langle p_q | \mu (q_1-p_q) \nu | p_{\bar{q}}\rangle}{(q_1-p_q)^2}\,,\\
\label{eq:Xcrossed}
X^{\mu\nu}_{\text{crossed}} ={}& \frac{\langle p_q | \nu (q_1-p_{\bar{q}}) \mu | p_{\bar{q}}\rangle}{(q_1-p_{\bar{q}})^2}\,,
\end{align}
and $q_3 = q_1 - p_q - p_{\bar{q}}$.
\subsection{Higgs}
-Different rapidity orderings \todo{give name of functions}
-\begin{enumerate}
-\item $qQ\to HqQ/qHQ/qQH$ (any rapidity order, full LO ME) $\Rightarrow$ see~\ref{sec:V_H}
-\item $qg\to Hqg$ (Higgs outside quark) $\Rightarrow$ see~\ref{sec:V_H}
-\item $qg\to qHg$ (central Higgs) $\Rightarrow$ see~\ref{sec:V_H}
-\item $qg\to qgH$ (Higgs outside gluon) $\Rightarrow$ see~\ref{sec:jH_mt}
-\item $gg\to gHg$ (central Higgs) $\Rightarrow$ see~\ref{sec:V_H}
-\item $gg\to ggH$ (Higgs outside gluon) $\Rightarrow$ see~\ref{sec:jH_mt}
-\end{enumerate}
\subsubsection{Higgs gluon vertex}
\label{sec:V_H}
The coupling of the Higgs boson to gluons via a virtual quark loop can be written as
\begin{align}
\label{eq:VH}
V^{\mu\nu}_H(q_1, q_2) = \mathgraphics{V_H.pdf} &=
\frac{\alpha_s m^2}{\pi v}\big[
g^{\mu\nu} T_1(q_1, q_2) - q_2^\mu q_1^\nu T_2(q_1, q_2)
\big]\, \\
&\xrightarrow{m \to \infty} \frac{\alpha_s}{3\pi
v} \left(g^{\mu\nu} q_1\cdot q_2 - q_2^\mu q_1^\nu\right).
\end{align}
The outgoing momentum of the Higgs boson is $p_H = q_1 - q_2$.
As a contraction with two currents this by implemented in \lstinline!cHdot! inside \texttt{src/Hjets.cc}.
The form factors $T_1$ and $T_2$ are then given by~\cite{DelDuca:2003ba}
\begin{align}
\label{eq:T_1}
T_1(q_1, q_2) ={}& -C_0(q_1, q_2)\*\left[2\*m^2+\frac{1}{2}\*\left(q_1^2+q_2^2-p_H^2\right)+\frac{2\*q_1^2\*q_2^2\*p_H^2}{\lambda}\right]\notag\\
&-\left[B_0(q_2)-B_0(p_H)\right]\*\frac{q_2^2}{\lambda}\*\left(q_2^2-q_1^2-p_H^2\right)\notag\\
&-\left[B_0(q_1)-B_0(p_H)\right]\*\frac{q_1^2}{\lambda}\*\left(q_1^2-q_2^2-p_H^2\right)-1\,,\displaybreak[0]\\
\label{eq:T_2}
T_2(q_1, q_2) ={}& C_0(q_1,
q_2)\*\left[\frac{4\*m^2}{\lambda}\*\left(p_H^2-q_1^2-q_2^2\right)-1-\frac{4\*q_1^2\*q_2^2}{\lambda}
-
\frac{12\*q_1^2\*q_2^2\*p_H^2}{\lambda^2}\*\left(q_1^2+q_2^2-p_H^2\right)\right]\notag\\
&-\left[B_0(q_2)-B_0(p_H)\right]\*\left[\frac{2\*q_2^2}{\lambda}+\frac{12\*q_1^2\*q_2^2}{\lambda^2}\*\left(q_2^2-q_1^2+p_H^2\right)\right]\notag\\
&-\left[B_0(q_1)-B_0(p_H)\right]\*\left[\frac{2\*q_1^2}{\lambda}+\frac{12\*q_1^2\*q_2^2}{\lambda^2}\*\left(q_1^2-q_2^2+p_H^2\right)\right]\notag\\
&-\frac{2}{\lambda}\*\left(q_1^2+q_2^2-p_H^2\right)\,,
\end{align}
where we have used the scalar bubble and triangle integrals
\begin{align}
\label{eq:B0}
B_0\left(p\right) ={}& \int \frac{d^dl}{i\pi^{\frac{d}{2}}}
\frac{1}{\left(l^2-m^2\right)\left((l+p)^2-m^2\right)}\,,\\
\label{eq:C0}
C_0\left(p,q\right) ={}& \int \frac{d^dl}{i\pi^{\frac{d}{2}}} \frac{1}{\left(l^2-m^2\right)\left((l+p)^2-m^2\right)\left((l+p-q)^2-m^2\right)}\,,
\end{align}
and the K\"{a}ll\'{e}n function
\begin{equation}
\label{eq:lambda}
\lambda = q_1^4 + q_2^4 + p_H^4 - 2\*q_1^2\*q_2^2 - 2\*q_1^2\*p_H^2- 2\*q_2^2\*p_H^2\,.
\end{equation}
The Integrals as such are provided by \QCDloop{} (see wrapper functions \lstinline!B0DD! and \lstinline!C0DD! in \texttt{src/Hjets.cc}).
In the code we are sticking to the convention of~\cite{DelDuca:2003ba}, thus instead of the $T_{1/2}$ we implement (in the functions \lstinline!A1! and \lstinline!A2!)
\begin{align}
\label{eq:A_1}
A_1(q_1, q_2) ={}& \frac{i}{16\pi^2}\*T_2(-q_1, q_2)\,,\\
\label{eq:A_2}
A_2(q_1, q_2) ={}& -\frac{i}{16\pi^2}\*T_1(-q_1, q_2)\,.
\end{align}
-\subsubsection{Peripheral Higgs emission - Finite quark mass}
-\label{sec:jH_mt}
-
-We describe the emission of a peripheral Higgs boson close to a
-scattering gluon with an effective current. In the following we consider
-a lightcone decomposition of the gluon momenta, i.e. $p^\pm = E \pm p_z$
-and $p_\perp = p_x + i p_y$. The incoming gluon momentum $p_a$ defines
-the $-$ direction, so that $p_a^+ = p_{a\perp} = 0$. The outgoing
-momenta are $p_1$ for the gluon and $p_H$ for the Higgs boson. We choose
-the following polarisation vectors
-\begin{equation}
- \label{eq:pol_vectors}
- \epsilon_\mu^\pm(p_a) = \epsilon_\mu^\pm(p_a, p_1),\qquad \epsilon_\mu^\pm(p_1) = \epsilon_\mu^\pm(p_1, p_a)\,.
-\end{equation} The polarisation vectors with two momentum arguments
-are defined in equation~(\ref{eq:pol_vector}).
-
-Following~\cite{DelDuca:2001fn}, we introduce effective polarisation
-vectors to describe the contraction with the Higgs-boson production
-vertex eq.~\eqref{eq:VH}:
-\begin{align}
- \label{eq:eps_H}
- \epsilon_{H,\mu}(p_a) = \frac{T_2(p_a, p_a-p_H)}{(p_a-p_H)^2}\big[p_a\cdot
- p_H\epsilon_\mu(p_a) - p_H\cdot\epsilon(p_a) p_{a,\mu}\big]\,,\\
- \epsilon_{H,\mu}^*(p_1) = -\frac{T_2(p_1+p_H, p_1)}{(p_1+p_H)^2}\big[p_1\cdot
- p_H\epsilon_\mu^*(p_1) - p_H\cdot\epsilon^*(p_1) p_{1,\mu}\big]\,,
-\end{align}
-with $T_1$ from equation~\eqref{eq:T_1} and $T_2$ from equation~\eqref{eq:T_2}.
-
-Without loss of generality, we consider only the case where the incoming
-gluon has positive helicity. The remaining helicity configurations can
-be obtained through parity transformation.
-
-Labelling the effective current by the helicities of the gluons we obtain
-for the same-helicity case
-\begin{equation}
- \label{eq:jH_same_helicity}
- \begin{split}
- j_{H,\mu}^{++}{}&(p_1,p_a,p_H) =
- \frac{m^2}{\pi v}\bigg[\\
- &-\sqrt{\frac{2p_1^-}{p_a^-}}\frac{p_{1\perp}^*}{|p_{1\perp}|}\frac{t_2}{\spb a.1}\epsilon^{+,*}_{H,\mu}(p_1)
- +\sqrt{\frac{2p_a^-}{p_1^-}}\frac{p_{1\perp}^*}{|p_{1\perp}|}\frac{t_2}{\spa 1.a}\epsilon^{+}_{H,\mu}(p_a)\\
- &+ [1|H|a\rangle \bigg(
- \frac{\sqrt{2}}{\spa 1.a}\epsilon^{+}_{H,\mu}(p_a)
- + \frac{\sqrt{2}}{\spb a.1}\epsilon^{+,*}_{H,\mu}(p_1)-\frac{\spa 1.a T_2(p_a, p_a-p_H)}{\sqrt{2}(p_a-p_H)^2}\epsilon^{+,*}_{\mu}(p_1)\\
- &
- \qquad
- -\frac{\spb a.1 T_2(p_1+p_H,
- p_1)}{\sqrt{2}(p_1+p_H)^2}\epsilon^{+}_{\mu}(p_a)-\frac{RH_4}{\sqrt{2}\spb a.1}\epsilon^{+,*}_{\mu}(p_1)+\frac{RH_5}{\sqrt{2}\spa 1.a}\epsilon^{+}_{\mu}(p_a)
- \bigg)\\
- &
- - \frac{[1|H|a\rangle^2}{2 t_1}(p_{a,\mu} RH_{10} - p_{1,\mu} RH_{12})\bigg]
- \end{split}
-\end{equation}
-with $t_1 = (p_a-p_1)^2$, $t_2 = (p_a-p_1-p_H)^2$ and $R = 8 \pi^2$\todo{Code has $R=8\pi^2 i$}. Like other special currents, eq.~\eqref{eq:jH_same_helicity}
-is implemented in \texttt{current\_generator/include/currents.frm}.
-
-The currents with a helicity flip is given through
-\begin{equation}
- \label{eq:jH_helicity_flip}
- \begin{split}
- j_{H,\mu}^{+-}{}&(p_1,p_a,p_H) =
- \frac{m^2}{\pi v}\bigg[\\
- &-\sqrt{\frac{2p_1^-}{p_a^-}}\frac{p_{1\perp}^*}{|p_{1\perp}|}\frac{t_2}{\spb
- a.1}\epsilon^{-,*}_{H,\mu}(p_1)
- +\sqrt{\frac{2p_a^-}{p_1^-}}\frac{p_{1\perp}}{|p_{1\perp}|}\frac{t_2}{\spb a.1}\epsilon^{+}_{H,\mu}(p_a)\\
- &+ [1|H|a\rangle \left(
- \frac{\sqrt{2}}{\spb a.1} \epsilon^{-,*}_{H,\mu}(p_1)
- -\frac{\spa 1.a T_2(p_a, p_a-p_H)}{\sqrt{2}(p_a-p_H)^2}\epsilon^{-,*}_{\mu}(p_1)
- - \frac{RH_4}{\sqrt{2}\spb a.1}\epsilon^{-,*}_{\mu}(p_1)\right)
- \\
- &+ [a|H|1\rangle \left(
- \frac{\sqrt{2}}{\spb a.1}\epsilon^{+}_{H,\mu}(p_a)
- -\frac{\spa 1.a
- T_2(p_1+p_H,p_1)}{\sqrt{2}(p_1+p_H)^2}\epsilon^{+}_{\mu}(p_a)
- +\frac{RH_5}{\sqrt{2}\spb a.1}\epsilon^{+}_{\mu}(p_a)
- \right)\\
- & - \frac{[1|H|a\rangle [a|H|1\rangle}{2 \spb a.1 ^2}(p_{a,\mu} RH_{10} - p_{1,\mu}
- RH_{12})\\
- &+ \frac{\spa 1.a}{\spb a.1}\bigg(RH_1p_{1,\mu}-RH_2p_{a,\mu}+2
- p_1\cdot p_H \frac{T_2(p_1+p_H, p_1)}{(p_1+p_H)^2} p_{a,\mu}
- \\
- &
- \qquad- 2p_a \cdot p_H \frac{T_2(p_a, p_a-p_H)}{(p_a-p_H)^2} p_{1,\mu}+ T_1(p_a-p_1, p_a-p_1-p_H)\frac{(p_1 + p_a)_\mu}{t_1}\\
- &\qquad-\frac{(p_1+p_a)\cdot p_H}{t_1} T_2(p_a-p_1, p_a-p_1-p_H)(p_1 - p_a)_\mu
- \bigg)
- \bigg]\,,
- \end{split}
-\end{equation}
-and implemented again in \texttt{current\_generator/include/currents.frm}.\todo{sign mismatch in line 5 and negative-helicity polarisation vectors}
-If we instead choose the gluon momentum in the $+$ direction, so that
-$p_a^- = p_{a\perp} = 0$, the corresponding currents are obtained by
-replacing $p_1^- \to p_1^+, p_a^- \to p_a^+,
-\frac{p_{1\perp}}{|p_{1\perp}|} \to -1$ in the second line of
-eq.~\eqref{eq:jH_same_helicity} and eq.~\eqref{eq:jH_helicity_flip}..
-
- The form factors $H_1,H_2,H_4,H_5, H_{10}, H_{12}$ are given in~\cite{DelDuca:2003ba}, and are implemented as \lstinline!H1DD,H2DD! etc. in \texttt{src/Hjets.cc}. They reduce down to fundamental QCD integrals, which are again provided by \QCDloop.
-
-\subsubsection{Peripheral Higgs emission - Infinite top mass}
-\label{sec:jH_eff}
-
-To get the result with infinite top mass we could either take the limit $m_t\to \infty$ in~\eqref{eq:jH_helicity_flip} and~\eqref{eq:jH_same_helicity}, or use the \textit{impact factors} as given in~\cite{DelDuca:2003ba}. Both methods are equivalent, and lead to the same result. For the first one would find
-\begin{align}
-\lim_{m_t\to\infty} m_t^2 H_1 &= i \frac{1}{24 \pi^2}\\
-\lim_{m_t\to\infty} m_t^2 H_2 &=-i \frac{1}{24 \pi^2}\\
-\lim_{m_t\to\infty} m_t^2 H_4 &= i \frac{1}{24 \pi^2}\\
-\lim_{m_t\to\infty} m_t^2 H_5 &=-i \frac{1}{24 \pi^2}\\
-\lim_{m_t\to\infty} m_t^2 H_{10} &= 0 \\
-\lim_{m_t\to\infty} m_t^2 H_{12} &= 0.
-\end{align}
-\todo{double check this, see James thesis eq. 4.33}
-However only the second method is implemented in the code through \lstinline!C2gHgp!
-and \lstinline!C2gHgm! inside \texttt{src/Hjets.cc}, each function
-calculates the square of eq. (4.23) and (4.22) from~\cite{DelDuca:2003ba} respectively.
-
\subsection{Vector Boson + Jets}
\label{sec:currents_W}
\subsubsection{Quark+ Vector Boson}
\begin{figure}
\centering
\begin{minipage}[b]{0.2\textwidth}
\includegraphics[width=\textwidth]{Wbits.pdf}
\end{minipage}
\begin{minipage}[b]{0.1\textwidth}
\centering{=}
\vspace{0.7cm}
\end{minipage}
\begin{minipage}[b]{0.2\textwidth}
\includegraphics[width=\textwidth]{Wbits2.pdf}
\end{minipage}
\begin{minipage}[b]{0.1\textwidth}
\centering{+}
\vspace{0.7cm}
\end{minipage}
\begin{minipage}[b]{0.2\textwidth}
\includegraphics[width=\textwidth]{Wbits3.pdf}
\end{minipage}
\caption{The $j_V$ current is constructed from the two diagrams which
contribute to the emission of a vector boson from a given quark line.}
\label{fig:jV}
\end{figure}
For a $W, Z$, or photon emission we require a fermion. The current is actually a sum of
two separate contributions, see figure~\ref{fig:jV}, one with a vector boson emission
from the initial state, and one with the vector boson emission from the final state.
This can be seen as the following two
terms, given for the example of a $W$ emission~\cite{Andersen:2012gk}\todo{cite W subleading paper}:
\begin{align}
\label{eq:Weffcur1}
j_W^\mu(p_a,p_{\ell},p_{\bar{\ell}}, p_1) =&\ \frac{g_W^2}{2}\
\frac1{p_W^2-M_W^2+i\ \Gamma_W M_W}\ \bar{u}^-(p_\ell) \gamma_\alpha
v^-(p_{\bar\ell})\nonumber \\
& \cdot \left( \frac{ \bar{u}^-(p_1) \gamma^\alpha (\slashed{p}_W +
\slashed{p}_1)\gamma^\mu u^-(p_a)}{(p_W+p_1)^2} +
\frac{ \bar{u}^-(p_1)\gamma^\mu (\slashed{p}_a - \slashed{p}_W)\gamma^\alpha u^-(p_a)}{(p_a-p_W)^2} \right).
\end{align}
There are a couple of subtleties here. There is a minus sign
distinction between the quark-anti-quark cases due to the fermion flow
of the propagator in the current. Note that the type of $W$ emission
(+ or -) will depend on the quark flavour, and that the handedness of
the quark-line is given by whether its a quark or anti-quark.
The coupling and propagator factor in eq.~(\ref{eq:Weffcur1}) have to
be adapted depending on the emitted boson. The remaining product of
currents
\begin{equation}
\label{eq:J_V}
J_{\text{V}}^\mu(p_2,p_l,p_{\bar{l}},p_3)=\left( \frac{ \bar{u}_2 \gamma^\nu (\slashed{p}_2 +
\slashed{p}_l +
\slashed{p}_{\bar{l}}) \gamma^\mu u_3}{s_{2l\bar{l}}} - \frac{\bar u_2
\gamma^\mu(\slashed{p}_3 + \slashed{p}_l + \slashed{p}_{\bar{l}}) \gamma^\nu
u_3}{s_{3l\bar{l}}} \right) [\bar{u}_l \gamma_\nu u_{\bar{l}}]
\end{equation}
with $s_{il\bar{l}} = (p_i + p_l +p_{\bar{l}})^2$ is universal. The
implementation is in \texttt{include/currents.frm} inside the
\texttt{current\_generator} (see section~\ref{sec:cur_gen}). To use it
inside \FORM use the place-holder
\lstinline!JV(h1, hl, mu, pa, p1, plbar, pl)!, where \lstinline!h1! is
the helicity of the quark line and \lstinline!hl! the helicity of the
lepton line.
\subsubsection{Vector boson with unordered emission}
\begin{figure}
\centering
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{vuno1}
\caption{}
\label{fig:U1diags}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{vuno2}
\caption{}
\label{fig:U2diags}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{vuno3}
\caption{}
\label{fig:Cdiags}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{vuno4}
\caption{}
\label{fig:Ddiags}
\end{subfigure}
\vspace{0.4cm}
\caption{Examples of each of the four categories of Feynman diagram which
contribute to at leading-order; there are twelve in total. (a) is an example where the gluon and vector
boson are emitted from the same quark line and the gluon comes after the
$t$-channel propagator. In (b), the gluon and vector boson are emitted from
the same quark line and the gluon comes before the $t$-channel proagator.
In (c) the gluon is emitted from the $t$-channel gluon and in (d) the gluon
is emitted from the $b$--$3$ quark line.}
\label{fig:Vunodiags}
\end{figure}
It is necessary to include subleading processes in vector boson + jets
also. Similarly to the pure jet case, the unordered currents are not
calculated separately, and only in the ME functions when required in
the \texttt{src/Wjets.cc} or \texttt{src/Zjets.cc} file. The following shows the derivation of the calculation of
this ME within HEJ. We start with a contraction of two currents:
\begin{equation}
\label{eq:SabsVuno}
S_{qQ\to Vgq^\prime Q} =
j_{V{\rm uno}\,\mu}^d(p_a,p_1,p_2,p_\ell,p_{\bar\ell})\ g^{\mu
\nu}\ T^d_{3b}\ j^{h_b,h_3}_{\nu}(p_b,p_{3}),
\end{equation}
where $j_{V,{\rm uno}}$ is our new unordered current which is is
only non-zero for $h_a=h_1=-$ and hence we have suppressed its
helicity indices. It is derived from the 12 leading-order Feynman
diagrams in the QMRK limit (see figure~\ref{fig:Vunodiags}). Using
$T^m_{ij}$ represent fundamental colour matrices between quark state
$i$ and $j$ with adjoint index $m$ we find
\begin{align}\label{eq:wunocurrent}
\begin{split}
j^{d\,\mu}_{\rm V,uno}(p_a,p_1,p_2,p_\ell,p_{\bar{\ell}}) =& \ i \varepsilon_{\nu}(p_1)\
\bar{u}^-(p_\ell) \gamma_\rho v^-(p_{\bar \ell}) \\ & \quad \times\
\left(T^1_{2i} T^d_{ia} (\tilde U_1^{\nu\mu\rho}-\tilde L^{\nu\mu\rho}) +
T^d_{2i} T^1_{ia} (\tilde U_2^{\nu\mu\rho}+\tilde L^{\nu\mu\rho}) \right),
\end{split}
\end{align}
where expressions for $\tilde U_{1,2}^{\nu\mu\rho}$ and $\tilde L^{\nu\mu\rho}$
are given as:
\begin{align}
\label{eq:U1tensor}
\begin{split}
\tilde U_1^{\nu\mu\rho} ={}&\frac{\langle 2|\nu (\slashed{p}_2+ \slashed{p}_1)\mu (\slashed{p}_a - \slashed{p}_V)\rho P_L |a\rangle }{s_{12}t_{aV}} + \frac{\langle 2|\nu (\slashed{p}_2+ \slashed{p}_1)\rho P_L (\slashed{p}_2+\slashed{p}_1 + \slashed{p}_V)\mu |a\rangle }{s_{12}s_{12V}} \\
&+ \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_V) \nu
(\slashed{p}_1 + \slashed{p}_2+\slashed{p}_V)\mu |a\rangle}{s_{2V}s_{12V}}\,,
\end{split}\\
\label{eq:U2tensor}
\begin{split}
\tilde U_2^{\nu\mu\rho} ={}&\frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_V-\slashed{p}_1)\nu (\slashed{p}_a - \slashed{p}_V)\rho P_L |a\rangle }{t_{aV1}t_{aV}} + \frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_V- \slashed{p}_1)\rho P_L (\slashed{p}_a-\slashed{p}_1) \nu |a\rangle }{t_{a1V}t_{a1}} \\
&+ \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_V) \mu
(\slashed{p}_a-\slashed{p}_1)\nu |a\rangle}{s_{2V}t_{a1}}\,,
\end{split}\\
\label{eq:Ltensor}
\begin{split}
\tilde L^{\nu\mu\rho} ={}& \frac{1}{t_{aV2}}\left[
\frac{\langle 2 | \sigma (\slashed{p}_a-\slashed{p}_V)\rho|a\rangle}{t_{aV}}
+\frac{\langle 2 | \rho (\slashed{p}_2+\slashed{p}_V)\sigma|a\rangle}{s_{2V}}
\right]\\
&\times \left\{\left(\frac{p_b^\nu}{s_{1b}} + \frac{p_3^\nu}{s_{13}}\right)(q_1-p_1)^2g^{\mu\sigma}+(2q_1-p_1)^\nu g^{\mu\sigma} - 2p_1^\mu g^{\nu\sigma} + (2p_1-q_1)^\sigma g^{\mu\nu} \right\}\,,
\end{split}
\end{align}
where $s_{ij\dots} = (p_i + p_j + \dots)^2, t_{ij\dots} = (p_i - p_j -
\dots)^2$ and $q_1 = p_a-p_2-p_V$. This is actually calculated and
used in the code in a much cleaner way as follows:
\begin{align}\label{eq:spinorstringVuno}
S_{qQ\to Vgq^\prime Q} = i\varepsilon_\nu (p_g) \bar{u}^-(p_2)&\gamma_\rho\nu(p_{\bar{q}})\times T^d_{3b} \bar{u}^{h_3}(p_3)\gamma_\mu u^{h_b}(p_b) \times \nonumber \\
&\left( T^1_{2i}T^d_{ia} \left( \tilde{U}_1^{\nu\mu\rho}-\tilde{L}^{\nu\mu\rho}\right)+T^d_{2i}T^1_{ia}\left(\tilde{U}_2^{\nu\mu\rho}+\tilde{L}^{\nu\mu\rho}\right) \right)
\end{align}
If we define the objects:
\begin{align}\label{eq:VunoX}
X &= \varepsilon_\nu(p_g) \left[ \bar{u}^-(p_2)\gamma_\rho\nu(p_{\bar{q}})\right] \left[ \bar{u}^{h_3}(p_3)\gamma_\mu u^{h_b}(p_b)\right] \left( \tilde{U}_1^{\nu\mu\rho}-\tilde{L}^{\nu\mu\rho}\right)\\
Y &= \varepsilon_\nu(p_g) \left[ \bar{u}^-(p_2)\gamma_\rho\nu(p_{\bar{q}})\right] \left[ \bar{u}^{h_3}(p_3)\gamma_\mu u^{h_b}(p_b)\right] \left( \tilde{U}_2^{\nu\mu\rho}+\tilde{L}^{\nu\mu\rho}\right)
\label{eq:WunoY}
\end{align}
then we can rewrite Equation \eqref{eq:spinorstringVuno} in the much simpler form:
\begin{equation}
S_{qQ\to Vgq^\prime Q} = iT^d_{3b} \left( T^{1}_{2i}T^d_{ia} X + T^d_{2i}T^1_{ia} Y \right)
\end{equation}
then, by using:
\begin{align}
\sum_{\text{all indices}}& T^d_{3b}T^e_{b3}T^1_{2i}T^d_{ia}T^e_{ai}T^1_{i2} = \frac{1}{2}C_F^2C_A \\
\sum_{\text{all indices}}& T^d_{3b}T^e_{b3}T^1_{2i}T^d_{ia}T^1_{ai}T^e_{i2} = \frac{1}{2}C_F^2C_A - \frac{1}{4}C_A^2C_F = -\frac{1}{4}C_F
\end{align}
giving then, the spin summed and helicity averaged spinor string as:
\begin{equation}\label{eq:VunoSumAveS}
||\;\bar{S}_{qQ\to Vgq^\prime Q}\;|| = \frac{1}{4N_C^2} \left( \frac{1}{2}C_F^2C_A\left(|X|^2+|Y|^2\right)-\frac{1}{4}C_F\times2\mathrm{Re}\left(XY^*\right)\right)
\end{equation}
\subsubsection{\texorpdfstring{$W$}{W}+Extremal \texorpdfstring{$\mathbf{q\bar{q}}$}{qqbar}}
\todo{Update when included in $Z$ + jets}
The $W$+Jet sub-leading processes containing an extremal $q\bar{q}$ are
related by crossing symmetry to the $W$+Jet unordered processes. This
means that one can simply perform a crossing symmetry argument on
eq.~\ref{eq:wunocurrent} to arrive at the extremal $q\bar{q}$ current
required.We show the basic structure of the extremal $q\bar{q}$
current in figure~\ref{fig:qgimp}, neglecting the $W$-emission for
simplicity.
\begin{figure}
\centering
\includegraphics[width=0.3\textwidth]{{qqbarex_schem}}
\caption{Schematic structure of the $gq \to \bar{Q}Qq$ amplitude in the limit
$y_1 \sim y_2 \ll y_3$}
\label{fig:qgimp}
\end{figure}
\begin{figure}
\centering
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex1}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex2}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex4}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex5}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex3}
\end{subfigure}
\caption{The five tree-level graphs which contribute to the process $gq \to \bar{Q}Qq$.}
\label{fig:qg_qQQ_graphs}
\end{figure}
We can obtain the current for $g\rightarrow W q \bar{q}$ by evaluating
the current for $W$ plus unordered emissions with the normal arguments
$p_a \leftrightarrow -p_1 $ interchanged. This is a non-trivial
statement: due to the minimality of the approximations made, the
crossing symmetry normally present in the full amplitude may be
extended to the factorised current.
We must again note that swapping $p_a \leftrightarrow -p_1$ will lead
to $u$-spinors with momenta with negative energy. These are identical
to $v$-spinors with momenta with positive energy, up to an overall
phase which is common to all terms, and can therefore be neglected.
Mathematically, this is given by:
\begin{align}\label{eq:crossedJ}
j^\mu_{\rm W,g\to Q\bar{Q}}(p_a,p_1,p_2,p_\ell,p_{\bar{\ell}}) =i \varepsilon_{g\nu}
\langle \ell | \rho | \bar \ell \rangle_L
\left(T^1_{2i} T^d_{ia} (\tilde U_{1,X}^{\nu\mu\rho}-\tilde L^{\nu\mu\rho}_X) + T^d_{2i} T^1_{ia} (\tilde U_{2,X}^{\nu\mu\rho}+\tilde L_X^{\nu\mu\rho}) \right),
\end{align}
where the components are now given by
\begin{align}
\label{eq:U1tensorX}
\begin{split}
\tilde U_{1,X}^{\nu\mu\rho} =&\frac{\langle 2|\nu (\slashed{p}_a- \slashed{p}_2)\mu (\slashed{p}_1 + \slashed{p}_W)\rho P_L |1\rangle }{t_{a2}s_{1W}} + \frac{\langle 2|\nu (\slashed{p}_a- \slashed{p}_2)\rho P_L (\slashed{p}_a-\slashed{p}_2 - \slashed{p}_W)\mu |1\rangle }{t_{a2}t_{a2W}} \\
&- \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_W) \nu
(\slashed{p}_a - \slashed{p}_2-\slashed{p}_W)\mu
|1\rangle}{s_{2W}t_{a2W}}\,,
\end{split}\\
\label{eq:U2tensorX}
\begin{split}
\tilde U_{2,X}^{\nu\mu\rho} =&-\frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_W-\slashed{p}_1)\nu (\slashed{p}_1 + \slashed{p}_W)\rho P_L |1\rangle }{t_{aW1}s_{1W}} + \frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_W- \slashed{p}_1)\rho P_L (\slashed{p}_a-\slashed{p}_1) \nu |1\rangle }{t_{a1W}t_{a1}} \\
&+ \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_W) \mu
(\slashed{p}_a-\slashed{p}_1)\nu |1\rangle}{s_{2W}t_{a1}}\,,
\end{split}\\
\label{eq:LtensorX}
\begin{split}
\tilde L^{\nu\mu\rho}_X &= \frac{1}{s_{W12}}\left[-\frac{\langle 2 |\sigma (\slashed{p}_1 + \slashed{p}_W) \rho P_L | 1\rangle}{s_{1W}} + \frac{\langle 2 |\rho P_L (\slashed{p}_2 + \slashed{p}_W) \sigma | 1\rangle }{s_{2W}} \right] \\
&\vphantom{+\frac{1}{t_{aW2}}}\quad\cdot \left( -\left(
\frac{p_b^\nu}{s_{ab}} + \frac{p_n^\nu}{s_{an}} \right) (q_1+p_a)^2 g^{\sigma\mu}+ g^{\sigma \mu} (2q_1 +p_a)^\nu - g^{\mu \nu}(2p_a+q_1)^\sigma+ 2g^{\nu \sigma}p_a^\mu \right)\,,
\end{split}
\end{align}
where $q_1=-(p_1+p_2+p_W)$. Notice in particular the similarity to the $W$+uno scenario (from which
this has been derived).
\subsubsection{Central \texorpdfstring{$\mathbf{q\bar{q}}$}{qqbar} Vertex}
The final subleading process in the $W$+Jet case is the Central
$q\bar{q}$ vertex. This subleading process does not require an altered
current, but an effective vertex which is contracted with two regular
\HEJ currents. This complexity is dealt with nicely by the \FORM inside the
\texttt{current\_generator/j\_Wqqbar\_j.frm}, which is detailed in
section~\ref{sec:contr_calc}.
The $W$-emission can be from the central effective vertex (scenario
dealt with by the function \lstinline!ME_WCenqqbar_qq! in the file
\texttt{src/Wjets.cc}); or from either of the external quark legs
(scenario dealt with by \lstinline!ME_W_Cenqqbar_qq! in same file). In
the pure jets case, there are 7 separate diagrams which contribute to
this, which can be seen in figure~\ref{fig:qq_qQQq_graphs}. In the $W$+Jets
case, there are then 45 separate contributions.
\begin{figure}
\centering
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarcen1}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarcen2}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarcen3}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarcen4}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarcen5}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarcen6}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarcen7}
\end{subfigure}
\caption{All Feynman diagrams which contribute to $qq' \to qQ\bar{Q}q'$ at
leading order.}
\label{fig:qq_qQQq_graphs}
\end{figure}
The end result is of the effective vertex, after derivation, is:
\begin{align}
\label{eq:EffectiveVertexqqbar}
\begin{split}
V^{\mu\nu}_{\text{Eff}}=&
- i \frac{C_1}{s_{23AB}}\left(X^{\mu\nu\sigma}_{1a}\hat{t_1} + X^{\mu\nu\sigma}_{4b}\hat{t_3} +V^{\mu\nu\sigma}_{3g}\right)J_{\text{V} \sigma}(p_2,p_A,p_B,p_3)
\\
&\quad +iC_2X^{\mu\nu}_{Unc}+iC_3X^{\mu\nu}_{Cro},
\end{split}
\end{align}
where:
\begin{align}
\begin{split}
C_1=&T^e_{1q}T^g_{qa}T^e_{23}T^g_{4b} -
T^g_{1q}T^e_{qa}T^e_{23}T^g_{4b} = f^{egc}T^c_{1a}T^e_{23}T^g_{4b},
\\
C_2=&T^g_{1a}T^g_{2q}T^{g'}_{q3}T^{g'}_{4b}
\\
C_3=&T^g_{1a}T^{g'}_{2q}T^g_{q3}T^{g'}_{4b}
\end{split}
\end{align}
are the colour factors of different contributions and $J_\text{V}$ is
given in equation~(\ref{eq:J_V}).
The following tensor structures correspond to groupings of diagrams in
figure~\ref{fig:qq_qQQq_graphs}.
\begin{eqnarray}
\label{eq:X_1a}
X_{1a}^{\mu\nu\sigma} &=
\frac{-g^{\mu\nu}}{s_{23AB}\hat{t_3}}\left(\frac{p^\sigma_a}{s_{a2} + s_{a3} + s_{aA} + s_{aB}} +
\frac{p^\sigma_1}{s_{12} + s_{13} + s_{1A} + s_{1B}}\right)
\\
\label{eq:X_4b}
X_{4b}^{\mu\nu\sigma}
&=\frac{g^{\mu\nu}}{s_{23AB}\hat{t_1}}\left(\frac{p^\sigma_b}{s_{b2} + s_{b3} + s_{bA} + s_{bB}}+
\frac{p^\sigma_4}{s_{42} + s_{43} + s_{4A} + s_{4B}}\right)
\end{eqnarray}
correspond to the first and second row of diagrams in figure~\ref{fig:qq_qQQq_graphs}.
\begin{align}
\label{eq:3GluonWEmit}
\begin{split}
V^{\mu\nu\sigma}_{3g}=\frac{1}{
\hat{t}_1s_{23AB}\,\hat{t}_3}
\bigg[&\left(q_1+p_2+p_3+p_A+p_B\right)^\nu
g^{\mu\sigma}+
\\
&\quad\left(q_3-p_2-p_3-p_A-p_B\right)^\mu g^{\sigma\nu}-
\\
& \qquad\left(q_1+q_3\right)^\sigma g^{\mu\nu}\bigg]J_{\text{V} \sigma}(p_2,p_A,p_B,p_3)
\end{split}
\end{align}
corresponds to the left diagram on the third row in
figure~\ref{fig:qq_qQQq_graphs}. One notes that all of these
contributions have the same colour factor, and as such we can group
them together nicely before summing over helicities etc. As such, the function
\lstinline!M_sym_W! returns a contraction of the above tensor containing the
information from these 5 groupings of contributions (30 diagrams in total). It
is available through the generated header \texttt{j\_Wqqbar\_j.hh} (see
section~\ref{sec:cur_gen}).
\begin{align}
\label{eq:X_Unc}
\begin{split}
X^{\mu\nu}_{Unc}=\frac{\langle A|\sigma P_L|B\rangle}{\hat{t_1}\hat{t_3}} \bar{u}_2&\left[-\frac{
\gamma^\sigma P_L(\slashed{p}_2+\slashed{p}_A+\slashed{p}_B)\gamma^\mu
(\slashed{q}_3+ \slashed{p}_3)\gamma^\nu}{(s_{2AB})(t_{unc_{2}})}\right.+
\\
&\qquad\left. \frac{\gamma^\mu(\slashed{q}_1-\slashed{p}_2)\gamma^\sigma
P_L(\slashed{q}_3+\slashed{p}_3)\gamma^\nu}{(t_{unc_{1}})(t_{unc_{2}})}\right. +
\\
&\qquad\qquad\left. \frac{\gamma^\mu(\slashed{q}_1-\slashed{p}_2)\gamma^\nu(\slashed{p}_3+\slashed{p}_A+\slashed{p}_B)\gamma^\sigma P_L
}{(t_{unc_1})(s_{3AB})}\right]v_3
\end{split}
\end{align}
corresponds to the diagram on the right of row three in
figure~\ref{fig:qq_qQQq_graphs}. This contribution to the current
contraction can be obtained in the code with the function
\lstinline!M_uncross_W!.
\begin{align}
\begin{split}
\label{eq:X_Cro}
X^{\mu\nu}_{Cro}=\frac{\langle
A|\sigma P_L|B\rangle}{\hat{t_1}\hat{t_3}} \bar{u}_2&\left[-\frac{
\gamma^\nu(\slashed{q}_3+\slashed{p}_2)\gamma^\mu
(\slashed{p}_3+\slashed{p}_A+\slashed{p}_B)\gamma^\sigma P_L}{(t_{cro_1})(s_{3AB})}\right.+
\\
&\qquad\left. \frac{\gamma^\nu(\slashed{q}_3+\slashed{p}_2)\gamma^\sigma
P_L(\slashed{q}_1-\slashed{p}_3)\gamma^\mu}{(t_{cro_{1}})(t_{cro_{2}})}\right.+
\\ &\qquad\qquad\left
. \frac{\gamma^\sigma P_L(\slashed{p}_2+\slashed{p}_A+\slashed{p}_B)\gamma^\nu(\slashed{q}_1-\slashed{p}_3)\gamma^\mu
}{(s_{2AB})(t_{cro_2})}\right]v_3
\end{split}
\end{align}
corresponds to the last diagram in
figure~\ref{fig:qq_qQQq_graphs}. This contribution to the current
contraction can be obtained in the code with the function
\lstinline!M_cross_W!.
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "developer_manual"
%%% End:
diff --git a/doc/developer_manual/developer_manual.tex b/doc/developer_manual/developer_manual.tex
index a6ddcbd..be7d726 100644
--- a/doc/developer_manual/developer_manual.tex
+++ b/doc/developer_manual/developer_manual.tex
@@ -1,2042 +1,2035 @@
\documentclass[a4paper,11pt]{article}
\usepackage{fourier}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\usepackage{geometry}
\usepackage{enumitem}
\setlist[description]{leftmargin=\parindent,labelindent=\parindent}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage[utf8x]{inputenc}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{todonotes}
\usepackage{listings}
\usepackage{xspace}
\usepackage{tikz}
\usepackage{slashed}
\usepackage{subcaption}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{shapes}
\usetikzlibrary{calc}
\usepackage[colorlinks,linkcolor={blue!50!black}]{hyperref}
\graphicspath{{build/figures/}{figures/}}
\usepackage[left]{showlabels}
\renewcommand{\showlabelfont}{\footnotesize\color{darkgreen}}
\emergencystretch \hsize
\setlength{\marginparwidth}{2cm}
\newcommand{\HEJ}{{\tt HEJ}\xspace}
\newcommand{\HIGHEJ}{\emph{High Energy Jets}\xspace}
\newcommand{\cmake}{\href{https://cmake.org/}{cmake}\xspace}
\newcommand{\html}{\href{https://www.w3.org/html/}{html}\xspace}
\newcommand{\YAML}{\href{http://yaml.org/}{YAML}\xspace}
\newcommand{\QCDloop}{\href{https://github.com/scarrazza/qcdloop}{QCDloop}\xspace}
\newcommand{\FORM}{{\tt FORM}\xspace}
\newcommand\matel[4][]{\mathinner{\langle#2\vert#3\vert#4\rangle}_{#1}}
\newcommand{\as}{\alpha_s}
\DeclareRobustCommand{\mathgraphics}[1]{\vcenter{\hbox{\includegraphics{#1}}}}
\def\spa#1.#2{\left\langle#1\,#2\right\rangle}
\def\spb#1.#2{\left[#1\,#2\right]} \def\spaa#1.#2.#3{\langle\mskip-1mu{#1} |
#2 | {#3}\mskip-1mu\rangle} \def\spbb#1.#2.#3{[\mskip-1mu{#1} | #2 |
{#3}\mskip-1mu]} \def\spab#1.#2.#3{\langle\mskip-1mu{#1} | #2 |
{#3}\mskip-1mu\rangle} \def\spba#1.#2.#3{\langle\mskip-1mu{#1}^+ | #2 |
{#3}^+\mskip-1mu\rangle} \def\spav#1.#2.#3{\|\mskip-1mu{#1} | #2 |
{#3}\mskip-1mu\|^2} \def\jc#1.#2.#3{j^{#1}_{#2#3}}
% expectation value
\newcommand{\ev}[1]{\text{E}\left[#1\right]}
\definecolor{darkgreen}{rgb}{0,0.4,0}
\lstset{ %
backgroundcolor=\color{lightgray}, % choose the background color; you must add \usepackage{color} or \usepackage{xcolor}
basicstyle=\footnotesize\usefont{T1}{DejaVuSansMono-TLF}{m}{n}, % the size of the fonts that are used for the code
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
breaklines=false, % sets automatic line breaking
captionpos=t, % sets the caption-position to bottom
commentstyle=\color{red}, % comment style
deletekeywords={...}, % if you want to delete keywords from the given language
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
extendedchars=true, % lets you use non-ASCII characters; for 8-bits encodings only, does not work with UTF-8
frame=false, % adds a frame around the code
keepspaces=true, % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible)
keywordstyle=\color{blue}, % keyword style
otherkeywords={}, % if you want to add more keywords to the set
numbers=none, % where to put the line-numbers; possible values are (none, left, right)
numbersep=5pt, % how far the line-numbers are from the code
rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here))
showspaces=false, % show spaces everywhere adding particular underscores; it overrides 'showstringspaces'
showstringspaces=false, % underline spaces within strings only
showtabs=false, % show tabs within strings adding particular underscores
stepnumber=2, % the step between two line-numbers. If it's 1, each line will be numbered
stringstyle=\color{gray}, % string literal style
tabsize=2, % sets default tabsize to 2 spaces
title=\lstname,
emph={},
emphstyle=\color{darkgreen}
}
\begin{document}
\tikzstyle{mynode}=[rectangle split,rectangle split parts=2, draw,rectangle split part fill={lightgray, none}]
\title{\HEJ 2 developer manual}
\author{}
\maketitle
\tableofcontents
\newpage
\section{Overview}
\label{sec:overview}
\HEJ 2 is a C++ program and library implementing an algorithm to
apply \HIGHEJ resummation~\cite{Andersen:2008ue,Andersen:2008gc} to
pre-generated fixed-order events. This document is intended to give an
overview over the concepts and structure of this implementation.
\subsection{Project structure}
\label{sec:project}
\HEJ 2 is developed under the \href{https://git-scm.com/}{git}
version control system. The main repository is on the IPPP
\href{https://gitlab.com/}{gitlab} server under
\url{https://gitlab.dur.scotgrid.ac.uk/hej/hej}. To get a local
copy, get an account on the gitlab server and use
\begin{lstlisting}[language=sh,caption={}]
git clone git@gitlab.dur.scotgrid.ac.uk:hej/hej.git
\end{lstlisting}
This should create a directory \texttt{hej} with the following
contents:
\begin{description}
\item[README.md:] Basic information concerning \HEJ.
\item[doc:] Contains additional documentation, see section~\ref{sec:doc}.
\item[include:] Contains the C++ header files.
\item[src:] Contains the C++ source files.
\item[examples:] Example analyses and scale setting code.
\item[t:] Contains the source code for the automated tests.
\item[CMakeLists.txt:] Configuration file for the \cmake build
system. See section~\ref{sec:cmake}.
\item[cmake:] Auxiliary files for \cmake. This includes modules for
finding installed software in \texttt{cmake/Modules} and templates for
code generation during the build process in \texttt{cmake/Templates}.
\item[config.yml:] Sample configuration file for running \HEJ 2.
\item[current\_generator:] Contains the code for the current generator,
see section~\ref{sec:cur_gen}.
\item[FixedOrderGen:] Contains the code for the fixed-order generator,
see section~\ref{sec:HEJFOG}.
\item[COPYING:] License file.
\item[AUTHORS:] List of \HEJ authors.
\item[Changes-API.md:] Change history for the \HEJ API (application programming interface).
\item[Changes.md:] History of changes relevant for \HEJ users.
\end{description}
In the following all paths are given relative to the
\texttt{hej} directory.
\subsection{Documentation}
\label{sec:doc}
The \texttt{doc} directory contains user documentation in
\texttt{doc/sphinx} and the configuration to generate source code
documentation in \texttt{doc/doxygen}.
The user documentation explains how to install and run \HEJ 2. The
format is
\href{http://docutils.sourceforge.net/rst.html}{reStructuredText}, which
is mostly human-readable. Other formats, like \html, can be generated with the
\href{http://www.sphinx-doc.org/en/master/}{sphinx} generator with
\begin{lstlisting}[language=sh,caption={}]
make sphinx
\end{lstlisting}
To document the source code we use
\href{https://www.stack.nl/~dimitri/doxygen/}{doxygen}. To generate
\html documentation, use the command
\begin{lstlisting}[language=sh,caption={}]
make doxygen
\end{lstlisting}
in your \texttt{build/} directory.
\subsection{Build system}
\label{sec:cmake}
For the most part, \HEJ 2 is a library providing classes and
functions that can be used to add resummation to fixed-order events. In
addition, there is a relatively small executable program leveraging this
library to read in events from an input file and produce resummation
events. Both the library and the program are built and installed with
the help of \cmake.
Debug information can be turned on by using
\begin{lstlisting}[language=sh,caption={}]
cmake base/directory -DCMAKE_BUILD_TYPE=Debug
make install
\end{lstlisting}
This facilitates the use of debuggers like \href{https://www.gnu.org/software/gdb/}{gdb}.
The main \cmake configuration file is \texttt{CMakeLists.txt}. It defines the
compiler flags, software prerequisites, header and source files used to
build \HEJ 2, and the automated tests.
\texttt{cmake/Modules} contains module files that help with the
detection of the software prerequisites and \texttt{cmake/Templates}
template files for the automatic generation of header and
source files. For example, this allows to only keep the version
information in one central location (\texttt{CMakeLists.txt}) and
automatically generate a header file from the template \texttt{Version.hh.in} to propagate this to the C++ code.
\subsection{General coding guidelines}
\label{sec:notes}
The goal is to make the \HEJ 2 code well-structured and
readable. Here are a number of guidelines to this end.
\begin{description}
\item[Observe the boy scout rule.] Always leave the code cleaner
than how you found it. Ugly hacks can be useful for testing, but
shouldn't make their way into the main branch.
\item[Ask if something is unclear.] Often there is a good reason why
code is written the way it is. Sometimes that reason is only obvious to
the original author (use \lstinline!git blame! to find them), in which
case they should be poked to add a comment. Sometimes there is no good
reason, but nobody has had the time to come up with something better,
yet. In some places the code might just be bad.
\item[Don't break tests.] There are a number of tests in the \texttt{t}
directory, which can be run with \lstinline!make test!. Ideally, all
tests should run successfully in each git revision. If your latest
commit broke a test and you haven't pushed to the central repository
yet, you can fix it with \lstinline!git commit --amend!. If an earlier
local commit broke a test, you can use \lstinline!git rebase -i! if
you feel confident. Additionally each \lstinline!git push! is also
automatically tested via the GitLab CI (see appendix~\ref{sec:CI}).
\item[Test your new code.] When you add some new functionality, also add an
automated test. This can be useful even if you don't know the
``correct'' result because it prevents the code from changing its behaviour
silently in the future. \href{http://www.valgrind.org/}{valgrind} is a
very useful tool to detect potential memory leaks. The code coverage of all
tests can be generated with \href{https://gcovr.com/en/stable/}{gcovr}.
Therefore add the flag \lstinline!-DTEST_COVERAGE=True! to cmake and run
\lstinline!make ctest_coverage!.
\item[Stick to the coding style.] It is somewhat easier to read code
that has a uniform coding and indentation style. We don't have a
strict style, but it helps if your code looks similar to what is
already there.
\end{description}
\section{Program flow}
\label{sec:flow}
A run of the \HEJ 2 program has three stages: initialisation,
event processing, and cleanup. The following sections outline these
stages and their relations to the various classes and functions in the
code. Unless denoted otherwise, all classes and functions are part of
the \lstinline!HEJ! namespace. The code for the \HEJ 2 program is
in \texttt{src/bin/HEJ.cc}, all other code comprises the \HEJ 2
library. Classes and free functions are usually implemented in header
and source files with a corresponding name, i.e. the code for
\lstinline!MyClass! can usually be found in
\texttt{include/HEJ/MyClass.hh} and \texttt{src/MyClass.cc}.
\subsection{Initialisation}
\label{sec:init}
The first step is to load and parse the \YAML configuration file. The
entry point for this is the \lstinline!load_config! function and the
related code can be found in \texttt{include/HEJ/YAMLreader.hh},
\texttt{include/HEJ/config.hh} and the corresponding \texttt{.cc} files
in the \texttt{src} directory. The implementation is based on the
\href{https://github.com/jbeder/yaml-cpp}{yaml-cpp} library.
The \lstinline!load_config! function returns a \lstinline!Config! object
containing all settings. To detect potential mistakes as early as
possible, we throw an exception whenever one of the following errors
occurs:
\begin{itemize}
\item There is an unknown option in the \YAML file.
\item A setting is invalid, for example a string is given where a number
would be expected.
\item An option value is not set.
\end{itemize}
The third rule is sometimes relaxed for ``advanced'' settings with an
obvious default, like for importing custom scales or analyses.
The information stored in the \lstinline!Config! object is then used to
initialise various objects required for the event processing stage described in
section~\ref{sec:processing}. First, the \lstinline!get_analyses! function
creates a number objects that inherits from the \lstinline!Analysis!
interface.\footnote{In the context of C++ the proper technical expression is
``pure abstract class''.} Using an interface allows us to decide the concrete
type of the analysis at run time instead of having to make a compile-time
decision. Depending on the settings, \lstinline!get_analyses! creates a number
of user-defined analyses loaded from one or more external libraries and
\textsc{rivet} analyses (see the user documentation
\url{https://hej.web.cern.ch/HEJ/doc/current/user/})
Together with a number of further objects, whose roles are described in
section~\ref{sec:processing}, we also initialise the global random
number generator. We again use an interface to defer deciding the
concrete type until the program is actually run. Currently, we support the
\href{https://mixmax.hepforge.org/}{MIXMAX}
(\texttt{include/HEJ/Mixmax.hh}) and Ranlux64
(\texttt{include/HEJ/Ranlux64.hh}) random number generators, both are provided
by \href{http://proj-clhep.web.cern.ch/}{CLHEP}.
We also set up a \lstinline!HEJ::EventReader! object for reading events
either in the the Les Houches event file format~\cite{Alwall:2006yp} or
an \href{https://www.hdfgroup.org/}{HDF5}-based
format~\cite{Hoeche:2019rti}. To allow making the decision at run time,
\lstinline!HEJ::EventReader! is an abstract base class defined in
\texttt{include/HEJ/EventReader.hh} and the implementations of the
derived classes are in \texttt{include/HEJ/LesHouchesReader.hh},
\texttt{include/HEJ/HDF5Reader.hh} and the corresponding \texttt{.cc}
source files in the \texttt{src} directory. The
\lstinline!LesHouchesReader! leverages
\href{http://home.thep.lu.se/~leif/LHEF/}{\texttt{include/LHEF/LHEF.h}}. A
small wrapper around the
\href{https://www.boost.org/doc/libs/1_67_0/libs/iostreams/doc/index.html}{boost
iostreams} library allows us to also read event files compressed with
\href{https://www.gnu.org/software/gzip/}{gzip}. The wrapper code is in
\texttt{include/HEJ/stream.hh} and the \texttt{src/stream.cc}.
If unweighting is enabled, we also initialise an unweighter as defined
in \texttt{include/HEJ/Unweighter.hh}. The unweighting strategies are
explained in section~\ref{sec:unweight}.
\subsection{Event processing}
\label{sec:processing}
In the second stage events are continuously read from the event
file. After jet clustering, a number of corresponding resummation events
are generated for each input event and fed into the analyses and a
number of output files. The roles of various classes and functions are
illustrated in the following flow chart:
\begin{center}
\begin{tikzpicture}[node distance=2cm and 5mm]
\node (reader) [mynode]
{\lstinline!EventReader::read_event!\nodepart{second}{read event}};
\node
(data) [mynode,below=of reader]
{\lstinline!Event::EventData! constructor\nodepart{second}{convert to \HEJ object}};
\node
(cluster) [mynode,below=of data]
{\lstinline!Event::EventData::cluster!\nodepart{second}{cluster jets \&
classify \lstinline!EventType!}};
\node
(resum) [mynode,below=of cluster]
{\lstinline!EventReweighter::reweight!\nodepart{second}{perform resummation}};
\node
(cut) [mynode,below=of resum]
{\lstinline!Analysis::pass_cuts!\nodepart{second}{apply cuts}};
\node
(cut) [mynode,below=of resum]
{\lstinline!Analysis::pass_cuts!\nodepart{second}{apply cuts}};
\node
(unweight) [mynode,below=of cut]
{\lstinline!Unweighter::unweight!\nodepart{second}{unweight (optional)}};
\node
(fill) [mynode,below left=of unweight]
{\lstinline!Analysis::fill!\nodepart{second}{analyse event}};
\node
(write) [mynode,below right=of unweight]
{\lstinline!CombinedEventWriter::write!\nodepart{second}{write out event}};
\node
(control) [below=of unweight] {};
\draw[-{Latex[length=3mm, width=1.5mm]}]
(reader.south) -- node[left] {\lstinline!LHEF::HEPEUP!} (data.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(data.south) -- node[left] {\lstinline!Event::EventData!} (cluster.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(cluster.south) -- node[left] {\lstinline!Event!} (resum.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(resum.south) -- (cut.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(resum.south)+(10mm, 0cm)$) -- ($(cut.north)+(10mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(resum.south)+(5mm, 0cm)$) -- ($(cut.north)+(5mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(resum.south)-(5mm, 0cm)$) -- ($(cut.north)-(5mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(resum.south)-(10mm, 0cm)$) -- node[left] {\lstinline!Event!} ($(cut.north)-(10mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(cut.south) -- (unweight.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cut.south)+(7mm, 0cm)$) -- ($(unweight.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cut.south)-(7mm, 0cm)$) -- node[left] {\lstinline!Event!} ($(unweight.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(unweight.south)-(3mm,0mm)$) .. controls ($(control)-(3mm,0mm)$) ..node[left] {\lstinline!Event!} (fill.east);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(unweight.south)-(3mm,0mm)$) .. controls ($(control)-(3mm,0mm)$) .. (write.west);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(unweight.south)+(3mm,0mm)$) .. controls ($(control)+(3mm,0mm)$) .. (fill.east);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(unweight.south)+(3mm,0mm)$) .. controls ($(control)+(3mm,0mm)$) ..node[right] {\lstinline!Event!} (write.west);
\end{tikzpicture}
\end{center}
\lstinline!EventData! is an intermediate container, its members are completely
accessible. In contrast after jet clustering and classification the phase space
inside \lstinline!Event! can not be changed any more
(\href{https://wikipedia.org/wiki/Builder_pattern}{Builder design pattern}). The
resummation is performed by the \lstinline!EventReweighter! class, which is
described in more detail in section~\ref{sec:resum}. The
\lstinline!CombinedEventWriter! writes events to zero or more output files. To
this end, it contains a number of objects implementing the
\lstinline!EventWriter! interface. These event writers typically write the
events to a file in a given format. We currently have the
\lstinline!LesHouchesWriter! for event files in the Les Houches Event File
format, the \lstinline!HDF5Writer! for
\href{https://www.hdfgroup.org/}{HDF5}~\cite{Hoeche:2019rti} and the
\lstinline!HepMC2Writer! or \lstinline!HepMC3Writer! for the
\href{https://hepmc.web.cern.ch/hepmc/}{HepMC} format (Version 2 and
3).
\subsection{Resummation}
\label{sec:resum}
In the \lstinline!EventReweighter::reweight! member function, we first
classify the input fixed-order event (FKL, unordered, non-resummable, \dots)
and decide according to the user settings whether to discard, keep, or
resum the event. If we perform resummation for the given event, we
generate a number of trial \lstinline!PhaseSpacePoint! objects. Phase
space generation is discussed in more detail in
section~\ref{sec:pspgen}. We then perform jet clustering according to
the settings for the resummation jets on each
\lstinline!PhaseSpacePoint!, update the factorisation and
renormalisation scale in the resulting \lstinline!Event! and reweight it
according to the ratio of pdf factors and \HEJ matrix elements between
resummation and original fixed-order event:
\begin{center}
\begin{tikzpicture}[node distance=1.5cm and 5mm]
\node (in) {};
\node (treat) [diamond,draw,below=of in,minimum size=3.5cm,
label={[anchor=west, inner sep=8pt]west:discard},
label={[anchor=east, inner sep=14pt]east:keep},
label={[anchor=south, inner sep=20pt]south:reweight}
] {};
\draw (treat.north west) -- (treat.south east);
\draw (treat.north east) -- (treat.south west);
\node
(psp) [mynode,below=of treat]
{\lstinline!PhaseSpacePoint! constructor};
\node
(cluster) [mynode,below=of psp]
{\lstinline!Event::EventData::cluster!\nodepart{second}{cluster jets}};
\node
(colour) [mynode,below=of cluster]
{\lstinline!Event::generate_colours()!\nodepart{second}{generate particle colour}};
\node
(gen_scales) [mynode,below=of colour]
{\lstinline!ScaleGenerator::operator()!\nodepart{second}{update scales}};
\node
(rescale) [mynode,below=of gen_scales]
{\lstinline!PDF::pdfpt!,
\lstinline!MatrixElement!\nodepart{second}{reweight}};
\node (out) [below of=rescale] {};
\draw[-{Latex[length=3mm, width=1.5mm]}]
(in.south) -- node[left] {\lstinline!Event!} (treat.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(treat.south) -- node[left] {\lstinline!Event!} (psp.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(psp.south) -- (cluster.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(psp.south)+(7mm, 0cm)$) -- ($(cluster.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(psp.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!PhaseSpacePoint!} ($(cluster.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(cluster.south) -- (colour.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cluster.south)+(7mm, 0cm)$) -- ($(colour.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cluster.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(colour.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(colour.south) -- (gen_scales.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(colour.south)+(7mm, 0cm)$) -- ($(gen_scales.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(colour.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(gen_scales.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(gen_scales.south) -- (rescale.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(gen_scales.south)+(7mm, 0cm)$) -- ($(rescale.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(gen_scales.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(rescale.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(rescale.south) -- (out.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(rescale.south)+(7mm, 0cm)$) -- ($(out.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(rescale.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(out.north)-(7mm, 0cm)$);
\node (helper) at ($(treat.east) + (15mm,0cm)$) {};
\draw[-{Latex[length=3mm, width=1.5mm]}]
(treat.east) -- ($(treat.east) + (15mm,0cm)$)
-- node[left] {\lstinline!Event!} (helper |- gen_scales.east) -- (gen_scales.east)
;
\end{tikzpicture}
\end{center}
\subsection{Phase space point generation}
\label{sec:pspgen}
The resummed and matched \HEJ cross section for pure jet production of
FKL configurations is given by (cf. eq. (3) of~\cite{Andersen:2018tnm})
\begin{align}
\label{eq:resumdijetFKLmatched2}
% \begin{split}
\sigma&_{2j}^\mathrm{resum, match}=\sum_{f_1, f_2}\ \sum_m
\prod_{j=1}^m\left(
\int_{p_{j\perp}^B=0}^{p_{j\perp}^B=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{j\perp}^B}{(2\pi)^3}\ \int
\frac{\mathrm{d} y_j^B}{2} \right) \
(2\pi)^4\ \delta^{(2)}\!\!\left(\sum_{k=1}^{m}
\mathbf{p}_{k\perp}^B\right)\nonumber\\
&\times\ x_a^B\ f_{a, f_1}(x_a^B, Q_a^B)\ x_b^B\ f_{b, f_2}(x_b^B, Q_b^B)\
\frac{\overline{\left|\mathcal{M}_\text{LO}^{f_1f_2\to f_1g\cdots
gf_2}\big(\big\{p^B_j\big\}\big)\right|}^2}{(\hat {s}^B)^2}\nonumber\\
& \times (2\pi)^{-4+3m}\ 2^m \nonumber\\
&\times\ \sum_{n=2}^\infty\
\int_{p_{1\perp}=p_{\perp,\mathrm{min}} }^{p_{1\perp}=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{1\perp}}{(2\pi)^3}\
\int_{p_{n\perp}=p_{\perp,\mathrm{min}}}^{p_{n\perp}=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{n\perp}}{(2\pi)^3}\
\prod_{i=2}^{n-1}\int_{p_{i\perp}=\lambda}^{p_{i\perp}=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{i\perp}}{(2\pi)^3}\ (2\pi)^4\ \delta^{(2)}\!\!\left(\sum_{k=1}^n
\mathbf{p}_{k\perp}\right )\\
&\times \ \mathbf{T}_y \prod_{i=1}^n
\left(\int \frac{\mathrm{d} y_i}{2}\right)\
\mathcal{O}_{mj}^e\
\left(\prod_{l=1}^{m-1}\delta^{(2)}(\mathbf{p}_{\mathcal{J}_{l}\perp}^B -
\mathbf{j}_{l\perp})\right)\
\left(\prod_{l=1}^m\delta(y^B_{\mathcal{J}_l}-y_{\mathcal{J}_l})\right)
\ \mathcal{O}_{2j}(\{p_i\})\nonumber\\
&\times \frac{(\hat{s}^B)^2}{\hat{s}^2}\ \frac{x_a f_{a,f_1}(x_a, Q_a)\ x_b f_{b,f_2}(x_b, Q_b)}{x_a^B\ f_{a,f_1}(x_a^B, Q_a^B)\ x_b^B\ f_{b,f_2}(x_b^B, Q_b^B)}\ \frac{\overline{\left|\mathcal{M}_{\mathrm{HEJ}}^{f_1 f_2\to f_1 g\cdots
gf_2}(\{ p_i\})\right|}^2}{\overline{\left|\mathcal{M}_\text{LO, HEJ}^{f_1f_2\to f_1g\cdots
gf_2}\big(\big\{p^B_j\big\}\big)\right|}^{2}} \,.\nonumber
% \end{split}
\end{align}
The first two lines correspond to the generation of the fixed-order
input events with incoming partons $f_1, f_2$ and outgoing momenta
$p_j^B$, where $\mathbf{p}_{j\perp}^B$ and $y_j^B$ denote the respective
transverse momentum and rapidity. Note that, at leading order, these
coincide with the fixed-order jet momenta $p_{\mathcal{J}_j}^B$.
$f_{a,f_1}(x_a, Q_a),f_{b,f_2}(x_b, Q_b)$ are the pdf factors for the incoming partons with
momentum fractions $x_a$ and $x_b$. The square of the partonic
centre-of-mass energy is denoted by $\hat{s}^B$ and
$\mathcal{M}_\text{LO}^{f_1f_2\to f_1g\cdots gf_2}$ is the
leading-order matrix element.
The third line is a factor accounting for the different multiplicities
between fixed-order and resummation events. Lines four and five are
the integration over the resummation phase space described in this
section. $p_i$ are the momenta of the outgoing partons in resummation
phase space. $\mathbf{T}_y$ denotes rapidity
ordering and $\mathcal{O}_{mj}^e$ projects out the exclusive $m$-jet
component. The relation between resummation and fixed-order momenta is
fixed by the $\delta$ functions. The first sets each transverse fixed-order jet
momentum to some function $\mathbf{j_{l\perp}}$ of the resummation
momenta. The exact form is described in section~\ref{sec:ptj_res}. The second
$\delta$ forces the rapidities of resummation and fixed-order jets to be
the same. Finally, the last line is the reweighting of pdf and matrix
element factors already shown in section~\ref{sec:resum}.
There are two kinds of cut-off in the integration over the resummation
partons. $\lambda$ is a technical cut-off connected to the cancellation
of infrared divergencies between real and virtual corrections. Its
numerical value is set in
\texttt{include/HEJ/Constants.h}. $p_{\perp,\mathrm{min}}$ regulates
and \emph{uncancelled} divergence in the extremal parton momenta. Its
size is set by the user configuration \url{https://hej.web.cern.ch/HEJ/doc/current/user/HEJ.html#settings}.
It is straightforward to generalise eq.~(\ref{eq:resumdijetFKLmatched2})
to unordered configurations and processes with additional colourless
emissions, for example a Higgs or electroweak boson. In the latter case only
the fixed-order integration and the matrix elements change.
\subsubsection{Gluon Multiplicity}
\label{sec:psp_ng}
The first step in evaluating the resummation phase space in
eq.~(\ref{eq:resumdijetFKLmatched2}) is to randomly pick terms in the
sum over the number of emissions. This sampling of the gluon
multiplicity is done in the \lstinline!PhaseSpacePoint::sample_ng!
function in \texttt{src/PhaseSpacePoint.cc}.
The typical number of extra emissions depends strongly on the rapidity
span of the underlying fixed-order event. Let us, for example, consider
a fixed-order FKL-type multi-jet configuration with rapidities
$y_{j_f},\,y_{j_b}$ of the most forward and backward jets,
respectively. By eq.~(\ref{eq:resumdijetFKLmatched2}), the jet
multiplicity and the rapidity of each jet are conserved when adding
resummation. This implies that additional hard radiation is restricted
to rapidities $y$ within a region $y_{j_b} \lesssim y \lesssim
y_{j_f}$. Within \HEJ, we require the most forward and most backward
emissions to be hard \todo{specify how hard} in order to avoid divergences, so this constraint
in fact applies to \emph{all} additional radiation.
To simplify the remaining discussion, let us remove the FKL rapidity
ordering
\begin{equation}
\label{eq:remove_y_order}
\mathbf{T}_y \prod_{i=1}^n\int \frac{\mathrm{d}y_i}{2} =
\frac{1}{n!}\prod_{i=1}^n\int
\frac{\mathrm{d}y_i}{2}\,,
\end{equation}
where all rapidity integrals now cover a region which is approximately
bounded by $y_{j_b}$ and $y_{j_f}$. Each of the $m$ jets has to contain at least
one parton; selecting random emissions we can rewrite the phase space
integrals as
\begin{equation}
\label{eq:select_jets}
\frac{1}{n!}\prod_{i=1}^n\int [\mathrm{d}p_i] =
\left(\prod_{i=1}^{m}\int [\mathrm{d}p_i]\ {\cal J}_i(p_i)\right)
\frac{1}{n_g!}\prod_{i=m+1}^{m+n_g}\int [\mathrm{d}p_i]
\end{equation}
with jet selection functions
\begin{equation}
\label{eq:def_jet_selection}
{\cal J}_i(p) =
\begin{cases}
1 &p\text{ clustered into jet }i\\
0 & \text{otherwise}
\end{cases}
\end{equation}
and $n_g \equiv n - m$. Here and in the following we use the short-hand
notation $[\mathrm{d}p_i]$ to denote the phase-space measure for parton
$i$. As is evident from eq.~\eqref{eq:select_jets}, adding an extra emission
$n_g+1$ introduces a suppression factor $\tfrac{1}{n_g+1}$. However, the
additional phase space integral also results in an enhancement proportional
to $\Delta y_{j_f j_b} = y_{j_f} - y_{j_b}$. This is a result of the
rapidity-independence of the MRK limit of the integrand, consisting of the
matrix elements divided by the flux factor. Indeed, we observe that the
typical number of gluon emissions is to a good approximation proportional to
the rapidity separation and the phase space integral is dominated by events
with $n_g \approx \Delta y_{j_f j_b}$.
For the actual phase space sampling, we assume a Poisson distribution
and extract the mean number of gluon emissions in different rapidity
bins and fit the results to a linear function in $\Delta y_{j_f j_b}$,
finding a coefficient of $0.975$ for the inclusive production of a Higgs
boson with two jets. Here are the observed and fitted average gluon
multiplicities as a function of $\Delta y_{j_f j_b}$:
\begin{center}
\includegraphics[width=.75\textwidth]{ng_mean}
\end{center}
As shown for two rapidity slices the assumption of a Poisson
distribution is also a good approximation:
\begin{center}
\includegraphics[width=.49\textwidth]{{ng_1.5}.pdf}\hfill
\includegraphics[width=.49\textwidth]{{ng_5.5}.pdf}
\end{center}
For configurations beyond leading-log, gluon emission is not allowed
everywhere and the rapidity span has to be adjusted. When determining
the most forward and backward jets, we exclude unordered emissions and
the extremal jet in extremal quark-antiquark emissions. In addition,
we subtract the rapidity region between central quark and antiquark
emission. Technically, we could have two or more additional gluons
inside one of the latter jets, in which case there could be gluons
that end up in between the jet centres but still outside the region
spanned by quark and antiquark. However, the phase space for this is
very small and should not affect the average number of emitted gluons
very much.
\subsubsection{Number of Gluons inside Jets}
\label{sec:psp_ng_jet}
For each of the $n_g$ gluon emissions we can split the phase-space
integral into a (disconnected) region inside the jets and a remainder:
\begin{equation}
\label{eq:psp_split}
\int [\mathrm{d}p_i] = \int [\mathrm{d}p_i]\,
\theta\bigg(\sum_{j=1}^{m}{\cal J}_j(p_i)\bigg) + \int [\mathrm{d}p_i]\,
\bigg[1-\theta\bigg(\sum_{j=1}^{m}{\cal J}_j(p_i)\bigg)\bigg]\,.
\end{equation}
The next step is to decide how many of the gluons will form part of a
jet. This is done in the \lstinline!PhaseSpacePoint::sample_ng_jets!
function.
We choose an importance sampling which is flat in the plane
spanned by the azimuthal angle $\phi$ and the rapidity $y$. This is
observed in BFKL and valid in the limit of Multi-Regge-Kinematics
(MRK). Furthermore, we assume anti-$k_t$ jets, which cover an area of
$\pi R^2$.
In principle, the total accessible area in the $y$-$\phi$ plane is given
by $2\pi \Delta y_{fb}$, where $\Delta y_{fb}\geq \Delta y_{j_f j_b}$ is
the a priori unknown rapidity separation between the most forward and
backward partons. In most cases the extremal jets consist of single
partons, so that $\Delta y_{fb} = \Delta y_{j_f j_b}$. For the less common
case of two partons forming a jet we observe a maximum distance of $R$
between the constituents and the jet centre. In rare cases jets have
more than two constituents. Empirically, they are always within a
distance of $\tfrac{5}{3}R$ to the centre of the jet, so
$\Delta y_{fb} \leq \Delta y_{j_f j_b} + \tfrac{10}{3} R$. In practice, the
extremal partons are required to carry a large fraction of the jet
transverse momentum and will therefore be much closer to the jet axis.
In summary, for sufficiently large rapidity separations we can use the
approximation $\Delta y_{fb} \approx \Delta y_{j_f j_b}$. This scenario
is depicted here:
\begin{center}
\includegraphics[width=0.5\linewidth]{ps_large_y}
\end{center}
If there is no overlap between jets, the probability $p_{\cal J, >}$ for
an extra gluon to end up inside a jet is then given by
\begin{equation}
\label{eq:p_J_large}
p_{\cal J, >} = \frac{(m - 1)\*R^2}{2\Delta y_{j_f j_b}}\,.
\end{equation}
For a very small rapidity separation, eq.~\eqref{eq:p_J_large}
obviously overestimates the true probability. The maximum phase space
covered by jets in the limit of a vanishing rapidity distance between
all partons is $2mR \Delta y_{fb}$:
\begin{center}
\includegraphics[width=0.5\linewidth]{ps_small_y}
\end{center}
We therefore estimate the probability for a parton to end up inside a jet as
\begin{equation}
\label{eq:p_J}
p_{\cal J} = \min\bigg(\frac{(m - 1)\*R^2}{2\Delta y_{j_f j_b}}, \frac{mR}{\pi}\bigg)\,.
\end{equation}
Here we compare this estimate with the actually observed
fraction of additional emissions into jets as a function of the rapidity
separation:
\begin{center}
\includegraphics[width=0.75\linewidth]{pJ}
\end{center}
Again, for configurations beyond leading-log the allowed rapidity
range has to be modified as explained in section~\ref{sec:psp_ng}. We
also subtract the areas of unordered jets and the extremal jet
in extremal quark-antiquark emission when we estimate the phase space
area covered by jets. The reason is that in this case any additional
emission inside such a jet would have to beyond the hard parton
dominating the next jet in rapidity, which is possible but rare.
\subsubsection{Gluons outside Jets}
\label{sec:gluons_nonjet}
Using our estimate for the probability of a gluon to be a jet
constituent, we choose a number $n_{g,{\cal J}}$ of gluons inside
jets, which also fixes the number $n_g - n_{g,{\cal J}}$ of gluons
outside jets. As explained later on, we need to generate the momenta of
the gluons outside jets first. This is done in
\lstinline!PhaseSpacePoint::gen_non_jet!.
The azimuthal angle $\phi$ is generated flat within $0\leq \phi \leq 2
\pi$. The allowed rapidity interval is set by the most forward and
backward partons, which are necessarily inside jets. Since these parton
rapidities are not known at this point, we also have to postpone the
rapidity generation for the gluons outside jets. For the scalar
transverse momentum $p_\perp = |\mathbf{p}_\perp|$ of a gluon outside
jets we use the parametrisation
\begin{equation}
\label{eq:p_nonjet}
p_\perp = \lambda + \tilde{p}_\perp\*\tan(\tau\*r)\,, \qquad
\tau = \arctan\bigg(\frac{p_{\perp{\cal J}_\text{min}} - \lambda}{\tilde{p}_\perp}\bigg)\,.
\end{equation}
For $r \in [0,1)$, $p_\perp$ is always less than the minimum momentum
$p_{\perp{\cal J}_\text{min}}$ required for a jet. $\tilde{p}_\perp$ is
a free parameter, a good empirical value is $\tilde{p}_\perp = [1.3 +
0.2\*(n_g - n_{g,\cal J})]\,$GeV
\subsubsection{Resummation jet momenta}
\label{sec:ptj_res}
Since \HEJ generated additional soft emissions, their recoil have to be
compensated through the remaining particles. In the traditional reshuffling this
recoil was only distributed over all jets. However in anticipation of including
more bosons ($WW+2j$), or less jets ($H+1j$) this changed to also include bosons
in the reshuffling. In the following we will still always call the recoilers
\emph{jet} instead of generic \emph{Born particles}, since the bosons are
treated completely equivalent to (massive) jets.
On the one hand, each jet momentum is given by the sum of its
constituent momenta. On the other hand, the resummation jet momenta are
fixed by the constraints in line five of the master
equation~\eqref{eq:resumdijetFKLmatched2}. We therefore have to
calculate the resummation jet momenta from these constraints before
generating the momenta of the gluons inside jets. This is done in
\lstinline!PhaseSpacePoint::reshuffle! and in the free
\lstinline!resummation_jet_momenta! function (declared in \texttt{resummation\_jet.hh}).
The resummation jet momenta are determined by the $\delta$ functions in
line five of eq.~(\ref{eq:resumdijetFKLmatched2}). The rapidities are
fixed to the rapidities of the jets in the input fixed-order events, so
that the FKL ordering is guaranteed to be preserved.
In traditional \HEJ reshuffling the transverse momentum are given through
\begin{equation}
\label{eq:ptreassign_old}
\mathbf{p}^B_{\mathcal{J}_{l\perp}} = \mathbf{j}_{l\perp} \equiv \mathbf{p}_{\mathcal{J}_{l}\perp}
+ \mathbf{q}_\perp \,\frac{|\mathbf{p}_{\mathcal{J}_{l}\perp}|}{P_\perp},
\end{equation}
where $\mathbf{q}_\perp = \sum_{j=1}^n \mathbf{p}_{i\perp}
\bigg[1-\theta\bigg(\sum_{j=1}^{m}{\cal J}_j(p_i)\bigg)\bigg] $ is the
total transverse momentum of all partons \emph{outside} jets and
$P_\perp = \sum_{j=1}^m |\mathbf{p}_{\mathcal{J}_{j}\perp}|$. Since the
total transverse momentum of an event vanishes, we can also use
$\mathbf{q}_\perp = - \sum_{j=1}^m
\mathbf{p}_{\mathcal{J}_{j}\perp}$. Eq.~(\ref{eq:ptreassign}) is a
non-linear system of equations in the resummation jet momenta
$\mathbf{p}_{\mathcal{J}_{l}\perp}$. Hence we would have to solve
\begin{equation}
\label{eq:ptreassign_eq}
\mathbf{p}_{\mathcal{J}_{l}\perp}=\mathbf{j}^B_{l\perp} \equiv\mathbf{j}_{l\perp}^{-1}
\left(\mathbf{p}^B_{\mathcal{J}_{l\perp}}\right)
\end{equation}
numerically.
Since solving such a system is computationally expensive, we instead
change the reshuffling around to be linear in the resummation jet
momenta. Hence~\eqref{eq:ptreassign_eq} gets replaces by
\begin{equation}
\label{eq:ptreassign}
\mathbf{p}_{\mathcal{J}_{l\perp}} = \mathbf{j}^B_{l\perp} \equiv \mathbf{p}^B_{\mathcal{J}_{l}\perp}
- \mathbf{q}_\perp \,\frac{|\mathbf{p}^B_{\mathcal{J}_{l}\perp}|}{P^B_\perp},
\end{equation}
which is linear in the resummation momentum. Consequently the equivalent
of~\eqref{eq:ptreassign_old} is non-linear in the Born momentum. However
the exact form of~\eqref{eq:ptreassign_old} is not relevant for the resummation.
Both methods have been tested for two and three jets with the \textsc{rivet}
standard analysis \texttt{MC\_JETS}. They didn't show any differences even
after $10^9$ events.
The reshuffling relation~\eqref{eq:ptreassign} allows the transverse
momenta $p^B_{\mathcal{J}_{l\perp}}$ of the fixed-order jets to be
somewhat below the minimum transverse momentum of resummation jets. It
is crucial that this difference does not become too large, as the
fixed-order cross section diverges for vanishing transverse momenta. In
the production of a Higgs boson with resummation jets above $30\,$GeV we observe
that the contribution from fixed-order events with jets softer than
about $20\,$GeV can be safely neglected. This is shown in the following
plot of the differential cross section over the transverse momentum of
the softest fixed-order jet:
\begin{center}
\includegraphics[width=.75\textwidth]{ptBMin}
\end{center}
Finally, we have to account for the fact that the reshuffling
relation~\eqref{eq:ptreassign} is non-linear in the Born momenta. To
arrive at the master formula~\eqref{eq:resumdijetFKLmatched2} for the
cross section, we have introduced unity in the form of an integral over
the Born momenta with $\delta$ functions in the integrand, that is
\begin{equation}
\label{eq:delta_intro}
1 = \int_{p_{j\perp}^B=0}^{p_{j\perp}^B=\infty}
\mathrm{d}^2\mathbf{p}_{j\perp}^B\delta^{(2)}(\mathbf{p}_{\mathcal{J}_{j\perp}}^B -
\mathbf{j}_{j\perp})\,.
\end{equation}
If the arguments of the $\delta$ functions are not linear in the Born
momenta, we have to compensate with additional Jacobians as
factors. Explicitly, for the reshuffling relation~\eqref{eq:ptreassign}
we have
\begin{equation}
\label{eq:delta_rewrite}
\prod_{l=1}^m \delta^{(2)}(\mathbf{p}_{\mathcal{J}_{l\perp}}^B -
\mathbf{j}_{l\perp}) = \Delta \prod_{l=1}^m \delta^{(2)}(\mathbf{p}_{\mathcal{J}_{l\perp}} -
\mathbf{j}_{l\perp}^B)\,,
\end{equation}
where $\mathbf{j}_{l\perp}^B$ is given by~\eqref{eq:ptreassign_eq} and only
depends on the Born momenta. We have extended the product to run to $m$
instead of $m-1$ by eliminating the last $\delta$ function
$\delta^{(2)}\!\!\left(\sum_{k=1}^n \mathbf{p}_{k\perp}\right )$.
The Jacobian $\Delta$ is the determinant of a $2m \times 2m$ matrix with $l, l' = 1,\dots,m$
and $X, X' = x,y$.
\begin{equation}
\label{eq:jacobian}
\Delta = \left|\frac{\partial\,\mathbf{j}^B_{l'\perp}}{\partial\, \mathbf{p}^B_{{\cal J}_l \perp}} \right|
= \left| \delta_{l l'} \delta_{X X'} - \frac{q_X\, p^B_{{\cal
J}_{l'}X'}}{\left|\mathbf{p}^B_{{\cal J}_{l'} \perp}\right| P^B_\perp}\left(\delta_{l l'}
- \frac{\left|\mathbf{p}^B_{{\cal J}_l \perp}\right|}{P^B_\perp}\right)\right|\,.
\end{equation}
The determinant is calculated in \lstinline!resummation_jet_weight!,
again coming from the \texttt{resummation\_jet.hh} header.
Having to introduce this Jacobian is not a disadvantage specific to the new
reshuffling. If we instead use the old reshuffling
relation~\eqref{eq:ptreassign_old} we \emph{also} have to introduce a
similar Jacobian since we actually want to integrate over the
resummation phase space and need to transform the argument of the
$\delta$ function to be linear in the resummation momenta for this.
\subsubsection{Gluons inside Jets}
\label{sec:gluons_jet}
After the steps outlined in section~\ref{sec:psp_ng_jet}, we have a
total number of $m + n_{g,{\cal J}}$ constituents. In
\lstinline!PhaseSpacePoint::distribute_jet_partons! we distribute them
randomly among the jets such that each jet has at least one
constituent. We then generate their momenta in
\lstinline!PhaseSpacePoint::split! using the \lstinline!Splitter! class.
The phase space integral for a jet ${\cal J}$ is given by
\begin{equation}
\label{eq:ps_jetparton} \prod_{i\text{ in }{\cal J}} \bigg(\int
\mathrm{d}\mathbf{p}_{i\perp}\ \int \mathrm{d} y_i
\bigg)\delta^{(2)}\Big(\sum_{i\text{ in }{\cal J}} \mathbf{p}_{i\perp} -
\mathbf{j}_{\perp}^B\Big)\delta(y_{\mathcal{J}}-y^B_{\mathcal{J}})\,.
\end{equation}
For jets with a single constituent, the parton momentum is obiously equal to the
jet momentum. In the case of two constituents, we observe that the
partons are always inside the jet cone with radius $R$ and often very
close to the jet centre. The following plots show the typical relative
distance $\Delta R/R$ for this scenario:
\begin{center}
\includegraphics[width=0.45\linewidth]{dR_2}
\includegraphics[width=0.45\linewidth]{dR_2_small}
\end{center}
According to this preference for small values of $\Delta R$, we
parametrise the $\Delta R$ integrals as
\begin{equation}
\label{eq:dR_sampling}
\frac{\Delta R}{R} =
\begin{cases}
0.25\,x_R & x_R < 0.4 \\
1.5\,x_R - 0.5 & x_R \geq 0.4
\end{cases}\,.
\end{equation}
Next, we generate $\Theta_1 \equiv \Theta$ and use the constraint $\Theta_2 = \Theta
\pm \pi$. The transverse momentum of the first parton is then given by
\begin{equation}
\label{eq:delta_constraints}
p_{1\perp} =
\frac{p_{\mathcal{J} y} - \tan(\phi_2) p_{\mathcal{J} x}}{\sin(\phi_1)
- \tan(\phi_2)\cos(\phi_1)}\,.
\end{equation}
We get $p_{2\perp}$ by exchanging $1 \leftrightarrow 2$ in the
indices. To obtain the Jacobian of the transformation, we start from the
single jet phase space eq.~(\ref{eq:ps_jetparton}) with the rapidity
delta function already rewritten to be linear in the rapidity of the
last parton, i.e.
\begin{equation}
\label{eq:jet_2p}
\prod_{i=1,2} \bigg(\int
\mathrm{d}\mathbf{p}_{i\perp}\ \int \mathrm{d} y_i
\bigg)\delta^{(2)}\Big(\mathbf{p}_{1\perp} + \mathbf{p}_{2\perp} -
\mathbf{j}_{\perp}^B\Big)\delta(y_2- \dots)\,.
\end{equation}
The integral over the second parton momentum is now trivial; we can just replace
the integral over $y_2$ with the equivalent constraint
\begin{equation}
\label{eq:R2}
\int \mathrm{d}R_2 \ \delta\bigg(R_2 - \bigg[\phi_{\cal J} - \arctan
\bigg(\frac{p_{{\cal J}y} - p_{1y}}{p_{{\cal J}x} -
p_{1x}}\bigg)\bigg]/\cos \Theta\bigg) \,.
\end{equation}
In order to fix the integral over $p_{1\perp}$ instead, we rewrite this
$\delta$ function. This introduces the Jacobian
\begin{equation}
\label{eq:jac_pt1}
\bigg|\frac{\partial p_{1\perp}}{\partial R_2} \bigg| =
\frac{\cos(\Theta)\mathbf{p}_{2\perp}^2}{p_{{\cal J}\perp}\sin(\phi_{\cal J}-\phi_1)}\,.
\end{equation}
The final form of the integral over the two parton momenta is then
\begin{equation}
\label{eq:ps_jet_2p}
\int \mathrm{d}R_1\ R_1 \int \mathrm{d}R_2 \int \mathrm{d}x_\Theta\ 2\pi \int
\mathrm{d}p_{1\perp}\ p_{1\perp} \int \mathrm{d}p_{2\perp}
\ \bigg|\frac{\partial p_{1\perp}}{\partial R_2} \bigg|\delta(p_{1\perp}
-\dots) \delta(p_{2\perp} - \dots)\,.
\end{equation}
As is evident from section~\ref{sec:psp_ng_jet}, jets with three or more
constituents are rare and an efficient phase-space sampling is less
important. For such jets, we exploit the observation that partons with a
distance larger than $R_{\text{max}} = \tfrac{5}{3} R$ to
the jet centre are never clustered into the jet. Assuming $N$
constituents, we generate all components
for the first $N-1$ partons and fix the remaining parton with the
$\delta$-functional. In order to end up inside the jet, we use the
parametrisation
\begin{align}
\label{eq:ps_jet_param}
\phi_i ={}& \phi_{\cal J} + \Delta \phi_i\,, & \Delta \phi_i ={}& \Delta
R_i
\cos(\Theta_i)\,, \\
y_i ={}& y_{\cal J} + \Delta y_i\,, & \Delta y_i ={}& \Delta
R_i
\sin(\Theta_i)\,,
\end{align}
and generate $\Theta_i$ and $\Delta R_i$ randomly with $\Delta R_i \leq
R_{\text{max}}$ and the empiric value $R_{\text{max}} = 5\*R/3$. We can
then write the phase space integral for a single parton as $(p_\perp = |\mathbf{p}_\perp|)$
\begin{equation}
\label{eq:ps_jetparton_x}
\int \mathrm{d}\mathbf{p}_{\perp}\ \int
\mathrm{d} y \approx \int_{\Box} \mathrm{d}x_{\perp}
\mathrm{d}x_{ R}
\mathrm{d}x_{\theta}\
2\*\pi\,\*R_{\text{max}}^2\,\*x_{R}\,\*p_{\perp}\,\*(p_{\perp,\text{max}}
- p_{\perp,\text{min}})
\end{equation}
with
\begin{align}
\label{eq:ps_jetparton_parameters}
\Delta \phi ={}& R_{\text{max}}\*x_{R}\*\cos(2\*\pi\*x_\theta)\,,&
\Delta y ={}& R_{\text{max}}\*x_{R}\*\sin(2\*\pi\*x_\theta)\,, \\
p_{\perp} ={}& (p_{\perp,\text{max}} - p_{\perp,\text{min}})\*x_\perp +
p_{\perp,\text{min}}\,.
\end{align}
$p_{\perp,\text{max}}$ is determined from the requirement that the total
contribution from the first $n-1$ partons --- i.e. the projection onto the
jet $p_{\perp}$ axis --- must never exceed the jet $p_\perp$. This gives
\todo{This bound is too high}
\begin{equation}
\label{eq:pt_max}
p_{i\perp,\text{max}} = \frac{p_{{\cal J}\perp} - \sum_{j<i} p_{j\perp}
\cos \Delta
\phi_j}{\cos \Delta
\phi_i}\,.
\end{equation}
The $x$ and $y$ components of the last parton follow immediately from
the first $\delta$ function. The last rapidity is fixed by the condition that
the jet rapidity is kept fixed by the reshuffling, i.e.
\begin{equation}
\label{eq:yJ_delta}
y^B_{\cal J} = y_{\cal J} = \frac 1 2 \ln \frac{\sum_{i=1}^n E_i+ p_{iz}}{\sum_{i=1}^n E_i - p_{iz}}\,.
\end{equation}
With $E_n \pm p_{nz} = p_{n\perp}\exp(\pm y_n)$ this can be rewritten to
\begin{equation}
\label{eq:yn_quad_eq}
\exp(2y_{\cal J}) = \frac{\sum_{i=1}^{n-1} E_i+ p_{iz}+p_{n\perp} \exp(y_n)}{\sum_{i=1}^{n-1} E_i - p_{iz}+p_{n\perp} \exp(-y_n)}\,,
\end{equation}
which is a quadratic equation in $\exp(y_n)$. The physical solution is
\begin{align}
\label{eq:yn}
y_n ={}& \log\Big(-b + \sqrt{b^2 + \exp(2y_{\cal J})}\,\Big)\,,\\
b ={}& \bigg(\sum_{i=1}^{n-1} E_i + p_{iz} - \exp(2y_{\cal J})
\sum_{i=1}^{n-1} E_i - p_{iz}\bigg)/(2 p_{n\perp})\,.
\end{align}
\todo{what's wrong with the following?} To eliminate the remaining rapidity
integral, we transform the $\delta$ function to be linear in the
rapidity $y$ of the last parton. The corresponding Jacobian is
\begin{equation}
\label{eq:jacobian_y}
\bigg|\frac{\partial y_{\cal J}}{\partial y_n}\bigg|^{-1} = 2 \bigg( \frac{E_n +
p_{nz}}{E_{\cal J} + p_{{\cal J}z}} + \frac{E_n - p_{nz}}{E_{\cal J} -
p_{{\cal J}z}}\bigg)^{-1}\,.
\end{equation}
Finally, we check that all designated constituents are actually
clustered into the considered jet.
\subsubsection{Final steps}
\label{sec:final}
Knowing the rapidity span covered by the extremal partons, we can now
generate the rapdities for the partons outside jets. We perform jet
clustering on all partons and check in
\lstinline!PhaseSpacePoint::jets_ok! that all the following criteria are
fulfilled:
\begin{itemize}
\item The number of resummation jets must match the number of
fixed-order jets.
\item No partons designated to be outside jets may end up inside jets.
\item All other outgoing partons \emph{must} end up inside jets.
\item The extremal (in rapidity) partons must be inside the extremal
jets. If there is, for example, an unordered forward emission, the
most forward parton must end up inside the most forward jet and the
next parton must end up inside second jet.
\item The rapidities of fixed-order and resummation jets must match.
\end{itemize}
After this, we adjust the phase-space normalisation according to the
third line of eq.~(\ref{eq:resumdijetFKLmatched2}), determine the
flavours of the outgoing partons, and adopt any additional colourless
bosons from the fixed-order input event. Finally, we use momentum
conservation to reconstruct the momenta of the incoming partons.
\subsection{Colour connection}
\label{sec:Colour}
\begin{figure}
\input{src/ColourConnect.tex}
\caption{Left: Non-crossing colour flow dominating in the MRK limit. The
crossing of the colour line connecting to particle 2 can be resolved by
writing particle 2 on the left. Right: A colour flow with a (manifest)
colour-crossing. The crossing can only be resolved if one breaks the
rapidities order, e.g. switching particles 2 and 3. From~\cite{Andersen:2017sht}.}
\label{fig:Colour_crossing}
\end{figure}
After the phase space for the resummation event is generated, we can construct
the colour for each particle. To generate the colour flow one has to call
\lstinline!Event::generate_colours! on any \HEJ configuration. For non-\HEJ
event we do not change the colour, and assume it is provided by the user (e.g.
through the LHE file input). The colour connection is done in the large $N_c$
(infinite number of colour) limit with leading colour in
MRK~\cite{Andersen:2008ue, Andersen:2017sht}. The idea is to allow only
$t$-channel colour exchange, without any crossing colour lines. For example the
colour crossing in the colour connection on the left of
figure~\ref{fig:Colour_crossing} can be resolved by switching \textit{particle
2} to the left.
We can write down the colour connections by following the colour flow from
\textit{gluon a} to \textit{gluon b} and back to \textit{gluon a}, e.g.
figure~\ref{fig:Colour_a123ba} corresponds to $a123ba$. All valid, non-crossing
colour flow will connect all external legs, while respecting the rapidity
ordering. For example the left of figure~\ref{fig:Colour_crossing} is allowed
($a134b2a$), it can be dientangled similar to figure~\ref{fig:Colour_a13b2a}.
However the right of the same figures breaks the rapidity ordering between 2 and
3 ($a1324ba$). Connections between $b$ and $a$ are in inverse order, i.e.
$ab321a$ corresponds to~\ref{fig:Colour_a123ba} ($a123ba$) with colour and
anti-colour swapped.
\begin{figure}
\centering
\subcaptionbox{$a123ba$\label{fig:Colour_a123ba}}{
\includegraphics[height=0.25\textwidth]{colour_a123ba.pdf}}
\subcaptionbox{$a13b2a$\label{fig:Colour_a13b2a}}{
\includegraphics[height=0.25\textwidth]{colour_a13b2a.pdf}}
\subcaptionbox{$a\_123ba$\label{fig:Colour_a_123ba}}{
\includegraphics[height=0.25\textwidth]{colour_a_123ba.pdf}}
\subcaptionbox{$a13b2\_a$\label{fig:Colour_a13b2_a}}{
\includegraphics[height=0.25\textwidth]{colour_a13b2_a.pdf}}
\subcaptionbox{$a14b3\_2a$\label{fig:Colour_a14b3_2a}}{
\includegraphics[height=0.25\textwidth]{colour_a14b3_2a.pdf}}
\caption{Different colour non-crossing colour connections. Both incoming
particles are drawn at the top or bottom and the outgoing left or right.
Outside arrows represent the the colour flow.}
\end{figure}
If we replace two gluons with a quark, (anti-)quark pair we break one of the
colour connections. We denote such a connection by a underscore (e.g. $1\_a$).
For example the equivalent of~\ref{fig:Colour_a123ba} ($a123ba$) with an
incoming antiquark is~\ref{fig:Colour_a_123ba} ($a\_123ba$). Such colour flows
are always possible for all leading and next-to-leading configurations, like
unordered emission~\ref{fig:Colour_a13b2_a} or central
$q\bar{q}$-pairs~\ref{fig:Colour_a14b3_2a} \footnote{Some sub-subleading
configurations are also possible. We could trivially chain multiple subleading
blocks, like $qQ\to gqQg$ from two unordered currents.}. We treat subleading
connections as one blob in which both $t$- and $u$-channels colour exchange is
allowed. E.g. $u$-channel equivalent of~\ref{fig:Colour_a14b3_2a} is
$a13\_24ba$. Each subleading blobs connect like gluons to the colour lines.
Some rapidity ordering allow multiple colour connections,
e.g.~\ref{fig:Colour_a123ba} and~\ref{fig:Colour_a13b2a}. This is always the
case if a gluon (or subleading blob) radiates off a gluon line. In that case we
randomly connect the gluon (or subleading blob) to either the colour or
anti-colour. In the generation we keep track whether we are on a quark or gluon
line, and act accordingly.
\subsection{The matrix element }
\label{sec:ME}
The derivation of the \HEJ matrix element is explained in some detail
in~\cite{Andersen:2017kfc}, where also results for leading and
subleading matrix elements for pure multijet production and production
of a Higgs boson with at least two associated jets are listed. Matrix
elements for $Z/\gamma^*$ production together with jets are
given in~\cite{Andersen:2016vkp}.
A full list of all implemented currents is given in
section~\ref{sec:currents_impl}.
The matrix elements are implemented in the \lstinline!MatrixElement!
class. To discuss the structure, let us consider the squared matrix
element for FKL multijet production with $n$ final-state partons:
\begin{align}
\label{eq:ME}
\begin{split}
\overline{\left|\mathcal{M}_\HEJ^{f_1 f_2 \to f_1
g\cdots g f_2}\right|}^2 = \ &\frac {(4\pi\alpha_s)^n} {4\ (N_c^2-1)}
\cdot\ \textcolor{blue}{\frac {K_{f_1}(p_1^-, p_a^-)} {t_1}\ \cdot\ \frac{K_{f_2}(p_n^+, p_b^+)}{t_{n-1}}\ \cdot\ \left\|S_{f_1 f_2\to f_1 f_2}\right\|^2}\\
& \cdot \prod_{i=1}^{n-2} \textcolor{gray}{\left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)}\\
& \cdot \prod_{j=1}^{n-1} \textcolor{red}{\exp\left[\omega^0(q_{j\perp})(y_{j+1}-y_j)\right]}.
\end{split}
\end{align}
The structure and momentum assignment of the unsquared matrix element is
as illustrated here:
\begin{center}
\includegraphics{HEJ_amplitude}
\end{center}
The square
of the complete matrix element as given in eq.~\eqref{eq:ME} is
calculated by \lstinline!MatrixElement::operator()!. The \textcolor{red}{last line} of
eq.~\eqref{eq:ME} constitutes the all-order virtual correction,
implemented in
\lstinline!MatrixElement::virtual_corrections!.
$\omega^0$ is the
\textit{regularised Regge trajectory}
\begin{equation}
\label{eq:omega_0}
\omega^0(q_\perp) = - C_A \frac{\alpha_s}{\pi} \log \left(\frac{q_\perp^2}{\lambda^2}\right)\,,
\end{equation}
where $\lambda$ is the slicing parameter limiting the softness of real
gluon emissions, cf. eq.~\eqref{eq:resumdijetFKLmatched2}. $\lambda$ can be
changed at runtime by setting \lstinline!regulator parameter! in
-\lstinline!conifg.yml!.
+the configuration file.
The remaining parts, which correspond to the square of the leading-order
\HEJ matrix element $\overline{\left|\mathcal{M}_\text{LO,
\HEJ}^{f_1f_2\to f_1g\cdots
gf_2}\big(\big\{p^B_j\big\}\big)\right|}^{2}$, are computed in
\lstinline!MatrixElement::tree!. We can further factor off the
scale-dependent ``parametric'' part
\lstinline!MatrixElement::tree_param! containing all factors of the
strong coupling $4\pi\alpha_s$. Using this function saves some CPU time
when adjusting the renormalisation scale, see
section~\ref{sec:resum}. The remaining ``kinematic'' factors are
calculated in \lstinline!MatrixElement::kin!.
+The ``colour acceleration multiplier'' (CAM) $\textcolor{blue}{K_{f}}$
+for a parton $f\in\{g,q,\bar{q}\}$ is defined as
+\begin{align}
+ \label{eq:K_g}
+\textcolor{blue}{ K_g(p_1^-, p_a^-)} ={}& \frac{1}{2}\left(\frac{p_1^-}{p_a^-} + \frac{p_a^-}{p_1^-}\right)\left(C_A -
+ \frac{1}{C_A}\right)+\frac{1}{C_A}\\
+ \label{eq:K_q}
+ \textcolor{blue}{K_q(p_1^-, p_a^-)} ={}&\textcolor{blue}{K_{\bar{q}}(p_1^-, p_a^-)} = C_F\,.
+\end{align}
+and the helicity-summed current contraction squares $\left\|S_{f_1
+f_2\to f_1 f_2}\right\|^2$ are explained in
+section~\ref{sec:currents}.
+
\subsubsection{FKL ladder and Lipatov vertices}
\label{sec:FKL_ladder}
The ``FKL ladder'' is the product
\begin{equation}
\label{eq:FKL_ladder}
\prod_{i=1}^{n-2} \left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)
\end{equation}
appearing in the square of the matrix element for $n$ parton production,
cf. eq.~(\ref{eq:ME}), and implemented in
\lstinline!MatrixElement::FKL_ladder_weight!. The Lipatov vertex contraction
$V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1})$ is implemented \lstinline!C2Lipatovots!.
It is given by \todo{equation} \todo{mention difference between the two versions of \lstinline!C2Lipatovots!, maybe even get rid of one}.
\subsubsection{Processes with interference}
\label{sec:interference}
For some processes several contributions can produce the same final state and it is necessary to take into account the interference between them. As an example let us consider the FKL squared matrix element for $Z/\gamma^*$ emission with two incoming quarks. It reads~\cite{Andersen:2016vkp}
\todo{This equation is copied from the paper}
\begin{align}
\label{eq:ME_Z}
\begin{split}
\left|\mathcal{M}_{\HEJ}^{qQ\to Z qg\cdots gQ}\right|^2 &=\ g_s^2 \frac{C_F}{8N_c}\ ( g_s^2
C_A)^{n-2}\ \\ \times \Bigg(& \textcolor{blue}{\frac{\| j_a^{Z}\cdot
j_b\|^2}{t_{a1}t_{a(n-1)}}}
\prod^{n-2}_{i=1} \textcolor{gray}{\frac{-V^2(q_{ai},
q_{a(i+1)})}{t_{ai} t_{a(i+1)}}} \prod_{i=1}^{n-1}
\textcolor{red}{\exp(\omega^0(q_{ai\perp}) (y_{i+1} - y_i))}\\
+\ &\textcolor{blue}{\frac{\|j_a \cdot j_b^{Z} \|^2}{t_{b1}t_{b(n-1)}}}
\prod^{n-2}_{i=1}\textcolor{gray}{\frac{-V^2(q_{bi}, q_{b(i+1)})}{t_{bi} t_{b(i+1)}}} \prod_{i=1}^{n-1} \textcolor{red}{\exp(\omega^0(q_{bi\perp})(y_{i+1} - y_i))} \\
-\ &\textcolor{blue}{\frac{2\Re\{ (j_a^{Z}\cdot j_b)(\overline{j_a \cdot
j_b^{Z}})\}}{\sqrt{t_{a1}t_{b1}}\sqrt{t_{a(n-1)} t_{b(n-1)}}}}\\
& \; \times \prod^{n-2}_{i=1}\textcolor{gray}{\frac{V(q_{ai}, q_{a(i+1)})\cdot V(q_{bi},
q_{b(i+1)})}{\sqrt{t_{ai}t_{bi}} \sqrt{t_{a(i+1)}t_{b(i+1)}}}} \prod_{i=1}^{n-1} \textcolor{red}{\exp(\omega^0(\sqrt{q_{ai\perp}q_{bi\perp}})(y_{i+1} - y_i))}\Bigg),
\end{split}
\end{align}
where a sum over helicities in the products of currents is
implied. The first two terms correspond to a boson emission from
either the upper quark line (labeled $a$) or lower quark line (labeled
$b$) in both the amplitude and the complex conjugate, while the last
term is the interference between the top and bottom emissions. To deal
with this structure the intermediate objects are kept as vectors. For
example, \lstinline!MatrixElement::FKL_ladder_weight_mix! returns the
ladder factors for top, bottom and mixed emission, the latter one
making use of \lstinline!C2Lipatovots_Mix! which implements the
contraction
$V^\mu(q_{ai},q_{a(i+1)})V_\mu(q_{bi},q_{b(i+1)})$. \lstinline!MatrixElement::operator()!
and \lstinline!MatrixElement::tree! then use these vectors to perform
the sum in eq.~(\ref{eq:ME_Z}).
-\subsubsection{Matrix elements for Higgs plus dijet}
+\subsubsection{Matrix elements for Higgs plus jets}
\label{sec:ME_h_jets}
In the production of a Higgs boson together with jets the parametric
parts and the virtual corrections only require minor changes in the
respective functions. However, in the ``kinematic'' parts we have to
distinguish between several cases, which is done in
\lstinline!MatrixElement::tree_kin_Higgs!. The Higgs boson can be
\emph{central}, i.e. inside the rapidity range spanned by the extremal
partons (\lstinline!MatrixElement::tree_kin_Higgs_central!) or
\emph{peripheral} and outside this range
(\lstinline!MatrixElement::tree_kin_Higgs_first! or
-\lstinline!MatrixElement::tree_kin_Higgs_last!). Currently the current for an
-unordered emission with an Higgs on the same side it not implemented
-\footnote{In principle emitting a Higgs boson \textit{on the other
-side} of the unordered gluon is possible by contracting an unordered and
-external Higgs current. Obviously this would not cover all possible
-configurations, e.g. $qQ\to HgqQ$ requires contraction of the standard $Q\to Q$
-current with an (unknown) $q\to Hgq$ one.}.
+\lstinline!MatrixElement::tree_kin_Higgs_last!).
If a Higgs boson with momentum $p_H$ is emitted centrally, after parton
$j$ in rapidity, the matrix element reads
\begin{equation}
\label{eq:ME_h_jets_central}
\begin{split}
\overline{\left|\mathcal{M}_\HEJ^{f_1 f_2 \to f_1 g\cdot H
\cdot g f_2}\right|}^2 = \ &\frac {\alpha_s^2 (4\pi\alpha_s)^n} {4\ (N_c^2-1)}
\cdot\ \textcolor{blue}{\frac {K_{f_1}(p_1^-, p_a^-)} {t_1}\
\cdot\ \frac{1}{t_j t_{j+1}} \cdot\ \frac{K_{f_2}(p_n^+, p_b^+)}{t_{n}}\ \cdot\ \left\|S_{f_1
f_2\to f_1 H f_2}\right\|^2}\\
& \cdot \prod_{\substack{i=1\\i \neq j}}^{n-1} \textcolor{gray}{\left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)}\\
& \cdot \textcolor{red}{\prod_{i=1}^{n-1}
\exp\left[\omega^0(q_{i\perp})\Delta y_i\right]}
\end{split}
\end{equation}
with the momentum definitions
\begin{center}
\includegraphics{HEJ_central_Higgs_amplitude}
\end{center}
$q_i$ is the $i$th $t$-channel momentum and $\Delta y_i$ the rapidity
gap between outgoing \emph{particles} (not partons) $i$ and $i+1$ in
rapidity ordering.
For \emph{peripheral} emission in the backward direction
(\lstinline!MatrixElement::tree_kin_Higgs_first!) we first check whether
the most backward parton is a gluon or an (anti-)quark. In the latter
case the leading contribution to the matrix element arises through
emission off the $t$-channel gluons and we can use the same formula
eq.~(\ref{eq:ME_h_jets_central}) as for central emission. If the most
backward parton is a gluon, the square of the matrix element can be
written as
\begin{equation}
\label{eq:ME_h_jets_peripheral}
\begin{split}
- \overline{\left|\mathcal{M}_\HEJ^{g f_2 \to H g\cdot g f_2}\right|}^2 = \ &\frac {\alpha_s^2 (4\pi\alpha_s)^n} {\textcolor{blue}{4\ (N_c^2-1)}}
- \textcolor{blue}{\cdot\ K_{H}\
+ \overline{\left|\mathcal{M}_\HEJ^{g f_2 \to H g\cdot g f_2}\right|}^2 = \ &\frac {\alpha_s^2 (4\pi\alpha_s)^n} {4(N_c^2-1)}
+ \textcolor{blue}{\cdot\ \frac{1}{t_1}\
\frac{K_{f_2}(p_n^+, p_b^+)}{t_{n-1}}\ \cdot\ \left\|S_{g
- f_2\to H g f_2}\right\|^2}\\
+ f_2\to H f_2}\right\|^2}\\
& \cdot \prod_{\substack{i=1}}^{n-2} \textcolor{gray}{\left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)}\\
& \cdot \textcolor{red}{\prod_{i=1}^{n-1}
- \exp\left[\omega^0(q_{i\perp}) (y_{i+1} - y_i)\right]}
+ \exp\left[\omega^0(q_{i\perp}) (y_{i+1} - y_i)\right]}\,.
\end{split}
\end{equation}
-with the momenta as follows:
+The current contraction $\textcolor{blue}{S_{gf_2\to H f_2}}$ has only
+one final-state parton; in contrast to all other \HEJ processes it is
+enough to have a \emph{single} jet together with the Higgs boson.
+
+The momenta are assigned as follows:
\begin{center}
\includegraphics{HEJ_peripheral_Higgs_amplitude}
\end{center}
The \textcolor{blue}{blue part} is implemented in
-\lstinline!MatrixElement::MH2_forwardH!. All other building blocks are
-already available.\todo{Impact factors} The actual current contraction
-is calculated in \lstinline!MH2gq_outsideH! inside
-\lstinline!src/Hjets.cc!, which corresponds to $\tfrac{16 \pi^2}{t_1} \left\|S_{g
- f_2\to H g f_2}\right\|^2$.\todo{Fix this insane normalisation}
+\lstinline!MatrixElement::MH2_backwardH!. The actual current contraction $\textcolor{blue}{\|S\|^2}$
+is calculated in \lstinline!ME_jgH_j! inside
+\lstinline!src/Hjets.cc!. All other building blocks are
+already available.
The forward emission of a Higgs boson is completely analogous. We can
-use the same function \lstinline!MatrixElement::MH2_forwardH!, swapping
-$p_1 \leftrightarrow p_n,\,p_a \leftrightarrow p_b$.
+use the same function \lstinline!MatrixElement::MH2_backwardH!, replacing
+$p_n \to p_1 ,\, p_b \to p_a$.
\subsubsection{Currents}
\label{sec:currents}
The current factors $\frac{K_{f_1}K_{f_2}}{t_1 t_{n-1}}\left\|S_{f_1
-f_2\to f_1 f_2}\right\|^2$ and their extensions for unordered and Higgs
-boson emissions are implemented in the \lstinline!jM2!$\dots$ functions
-of \texttt{src/Hjets.cc}. \todo{Only $\|S\|^2$ should be in currents}
-\footnote{The current implementation for
-Higgs production in \texttt{src/Hjets.cc} includes the $1/4$ factor
-inside $S$, opposing to~\eqref{eq:ME}. Thus the overall normalisation is
-unaffected.} The ``colour acceleration multiplier'' (CAM) $K_{f}$
-for a parton $f\in\{g,q,\bar{q}\}$ is defined as
-\begin{align}
- \label{eq:K_g}
- K_g(p_1^-, p_a^-) ={}& \frac{1}{2}\left(\frac{p_1^-}{p_a^-} + \frac{p_a^-}{p_1^-}\right)\left(C_A -
- \frac{1}{C_A}\right)+\frac{1}{C_A}\\
- \label{eq:K_q}
- K_q(p_1^-, p_a^-) ={}&K_{\bar{q}}(p_1^-, p_a^-) = C_F\,.
-\end{align}
-The Higgs current CAM used in eq.~(\ref{eq:ME_h_jets_peripheral}) is
-\begin{equation}
- \label{eq:K_H}
- K_H = C_A\,.
-\end{equation}
-The current contractions are given by\todo{check all this
- carefully!}
+f_2\to f_1 f_2}\right\|^2$ and their extensions for unordered and
+boson emissions are implemented in the \lstinline!ME_!$\dots$ functions
+of \texttt{src/jets.cc}, \texttt{src/Hjets.cc}, \texttt{src/Wjets.cc}, and \texttt{src/Zjets.cc}. \todo{Only $\|S\|^2$ should be in currents}
+The current contractions are given by\todo{many missing (W, Z, uno)}
\begin{align}
\label{eq:S}
\left\|S_{f_1 f_2\to f_1 f_2}\right\|^2 ={}& \sum_{\substack{\lambda_a =
+,-\\\lambda_b = +,-}} \left|j^{\lambda_a}_\mu(p_1, p_a)\
j^{\lambda_b\,\mu}(p_n, p_b)\right|^2 = 2\sum_{\lambda =
+,-} \left|j^{-}_\mu(p_1, p_a)\ j^{\lambda\,\mu}(p_n, p_b)\right|^2\,,\\
+ \label{eq:S_ff_fHf}
\left\|S_{f_1 f_2\to f_1 H f_2}\right\|^2 ={}& \sum_{\substack{\lambda_a =
+,-\\\lambda_b = +,-}} \left|j^{\lambda_a}_\mu(p_1, p_a)V_H^{\mu\nu}(q_j, q_{j+1})\
j^{\lambda_b}_\nu(p_n, p_b)\right|^2\,,\\
- \left\|S_{g f_2 \to H g f_2}\right\|^2 ={}& \sum_{
+ \label{eq:S_gf_Hf}
+ \left\|S_{g f_2 \to H f_2}\right\|^2 ={}& \sum_{
\substack{
- \lambda_{a} = +,-\\
- \lambda_{1} =+,-\\
+ \lambda_{g} = +,-\\
\lambda_{b} = +,-
}}
- \left|j^{\lambda_a\lambda_1}_{H\,\mu}(p_1, p_a, p_H)\ j^{\lambda_b\,\mu}(p_n, p_b)\right|^2\,.
+ \left|\epsilon_\mu^{\lambda_g}(p_g, p_r)\ V_H^{\mu\nu}(p_g, p_g-p_H)\ j_\nu^{\lambda_b}(p_n, p_b)\right|^2\,,
\end{align}
-Currently, some of the expressions for the current contractions are hard-coded. Work is ongoing to use the current generator described in section~\ref{sec:cur_gen} instead.
+They individual pieces are listed in section~\ref{sec:currents_impl} and the contraction is done in the current generator, section~\ref{sec:cur_gen}.
\subsection{Unweighting}
\label{sec:unweight}
Straightforward event generation tends to produce many events with small
weights. Those events have a negligible contribution to the final
observables, but can take up considerable storage space and CPU time in
later processing stages. This problem can be addressed by unweighting.
For naive unweighting, one would determine the maximum weight
$w_\text{max}$ of all events, discard each event with weight $w$ with a
probability $p=w/w_\text{max}$, and set the weights of all remaining
events to $w_\text{max}$. The downside to this procedure is that it also
eliminates a sizeable fraction of events with moderate weight, so that
the statistical convergence deteriorates. Naive unweighting can be
performed by using the \lstinline!set_cut_to_maxwt! member function of the
\lstinline!Unweighter! on the events and then call the
\lstinline!unweight! member function. It can be enabled for the
resummation events as explained in the user documentation.
To ameliorate the problem of naive unweighting, we also implement
partial unweighting. That is, we perform unweighting only for events
with sufficiently small weights. When using the \lstinline!Unweighter!
member function \lstinline!set_cut_to_peakwt! we estimate the mean and
width of the weight-weight distribution from a sample of events. We
use these estimates to determine the maximum weight below which
unweighting is performed; events with a larger weight are not
touched. The actual unweighting is again done in the
\lstinline!Unweighter::unweight! function.
To estimate the peak weight we employ the following heuristic
algorithm. For a calibration sample of $n$ events, create a histogram
with $b=\sqrt{n}$ equal-sized bins. The histogram ranges from $
\log(\min |w_i|)$ to $\log(|\max w_i|)$, where $w_i$ are the event weights. For
each event, add $|w_i|$ to the corresponding bin. We then prune the
histogram by setting all bins containing less than $c=n/b$
events to zero. This effectively removes statistical outliers. The
logarithm of the peak weight is then the centre of the highest bin in
the histogram. In principle, the number of bins $b$ and the pruning
parameter $c$ could be tuned further.
To illustrate the principle, here is a weight-weight histogram
filled with a sample of 100000 event weights before the pruning:
\begin{center}
\includegraphics[width=0.7\linewidth]{wtwt}
\end{center}
The peaks to the right are clearly outliers caused by single
events. After pruning we get the following histogram:
\begin{center}
\includegraphics[width=0.7\linewidth]{wtwt_cut}
\end{center}
The actual peak weight probably lies above the cut, and the algorithm
can certainly be improved. Still, the estimate we get from the pruned
histogram is already good enough to eliminate about $99\%$ of the
low-weight events.
\section{The current generator}
\label{sec:cur_gen}
The current generator in the \texttt{current\_generator} directory is
automatically invoked when building \HEJ 2. Its task is to compute and
generate C++ code for the current contractions listed in
section~\ref{sec:currents}. For each source file \texttt{<j\_j>.frm}
inside \texttt{current\_generator} it generates a corresponding header
\texttt{include/HEJ/currents/<j\_j>.hh} inside the build directory. The
header can be included with
\begin{lstlisting}[language=C++,caption={}]
#include "HEJ/currents/<j>.hh"
\end{lstlisting}
The naming scheme is
\begin{itemize}
\item \texttt{j1\_j2.frm} for the contraction of current \texttt{j1} with current \texttt{j2}.
\item \texttt{j1\_vx\_j2.frm} for the contraction of current \texttt{j1}
with the vertex \texttt{vx} and the current \texttt{j2}.
\end{itemize}
For instance, \texttt{juno\_qqbarW\_j.frm} would indicate the
contraction of an unordered current with a (central) quark-antiquark-W
emission vertex and a standard FKL current.
\subsection{Implementing new current contractions}
\label{sec:cur_gen_new}
Before adding a new current contraction, first find a representation
where all momenta that appear inside the currents are \textcolor{red}{lightlike}
and have \textcolor{red}{positive energy}. Section~\ref{sec:p_massive} describes
how massive momenta can be decomposed into massless ones. For momenta
$p'$ with negative energies replace $p' \to - p$ and exploit that
negative- and positive-energy spinors are related by a phase, which is
usually irrelevant: $u^\lambda(-p) = \pm i u^\lambda(p)$.
To implement a current contraction \lstinline!jcontr! create a new
file \texttt{jcontr.frm} inside the \texttt{current\_generator}
directory. \texttt{jcontr.frm} should contain \FORM code, see
\url{https://www.nikhef.nl/~form/} for more information on
\FORM. Here is a small example:
\begin{lstlisting}[caption={}]
* FORM comments are started by an asterisk * at the beginning of a line
* First include the relevant headers
#include- include/helspin.frm
#include- include/write.frm
* Define the symbols that appear.
* UPPERCASE symbols are reserved for internal use
vectors p1,...,p10;
indices mu1,...,mu10;
* Define local expressions of the form [NAME HELICITIES]
* for the current contractions for all relevant helicity configurations
#do HELICITY1={+,-}
#do HELICITY2={+,-}
* We use the Current function
* Current(h, p1, mu1, ..., muX, p2) =
* u(p1) \gamma_{mu1} ... \gamma_{muX} u(p2)
* where h=+1 or h=-1 is the spinor helicity.
* All momenta appearing as arguments have to be *lightlike*
local [jcontr `HELICITY1'`HELICITY2'] =
Current(`HELICITY1'1, p1, mu1, p2, mu2, p3)
*Current(`HELICITY2'1, p4, mu2, p2, mu1, p1);
#enddo
#enddo
.sort
* Main procedure that calculates the contraction
#call ContractCurrents
.sort
* Optimise expression
format O4;
* Format in a (mostly) c compatible way
format c;
* Write start of C++ header file
#call WriteHeader(`OUTPUT')
* Write a template function jcontr
* taking as template arguments two helicities
* and as arguments the momenta p1,...,p4
* returning the contractions [jcontr HELICITIES] defined above
#call WriteOptimised(`OUTPUT',jcontr,2,p1,p2,p3,p4)
* Wrap up
#call WriteFooter(`OUTPUT')
.end
\end{lstlisting}
\subsection{Calculation of contractions}
\label{sec:contr_calc}
In order to describe the algorithm for the calculation of current
contractions we first have to define the currents and establish some
useful relations.
\subsubsection{Massive momenta}
\label{sec:p_massive}
We want to use relations for lightlike momenta. Momenta $P$ that are
\emph{not} lightlike can be written as the sum of two lightlike
momenta:
\begin{equation}
\label{eq:P_massive}
P^\mu = p^\mu + q^\mu\,, \qquad p^2 = q^2 = 0 \,.
\end{equation}
This decomposition is not unique. If we impose the arbitrary
constraint $q_\perp = 0$ and require real-valued momentum
components we can use the ansatz
\begin{align}
\label{eq:P_massive_p}
p_\mu ={}& P_\perp\*(\cosh y, \cos \phi, \sin \phi, \sinh y)\,,\\
\label{eq:P_massive_q}
q_\mu ={}& (E, 0, 0, s\,E)\,,
\end{align}
where $P_\perp$ is the transverse momentum of $P$ and $\phi$ the corresponding azimuthal angle. For the remaining parameters we obtain
\begin{align}
\label{eq:P_massive_plus}
P^+ > 0:& & y ={}& \log \frac{P^+}{P_\perp}\,,\qquad E = \frac{P^2}{2P^+}\,,\qquad s = -1\,,\\
\label{eq:P_massive_minus}
P^- > 0:& & y ={}& \log \frac{P_\perp}{P^-}\,,\qquad E = \frac{P^2}{2P^-}\,,\qquad s = +1\,.
\end{align}
The decomposition is implemented in the \lstinline!split_into_lightlike! function.
\subsubsection{Currents and current relations}
\label{sec:current_relations}
Our starting point are generalised currents
\begin{equation}
\label{eq:j_gen}
j^{\pm}(p, \mu_1,\dots,\mu_{2N-1},q) = \bar{u}^{\pm}(p)\gamma_{\mu_1} \dots \gamma_{\mu_{2N-1}} u^\pm(q)\,.
\end{equation}
Since there are no masses, we can consider two-component chiral spinors
\begin{align}
\label{eq:u_plus}
u^+(p)={}& \left(\sqrt{p^+}, \sqrt{p^-} \hat{p}_\perp \right) \,,\\
\label{eq:u_minus}
u^-(p)={}& \left(\sqrt{p^-} \hat{p}^*_\perp, -\sqrt{p^+}\right)\,,
\end{align}
with $p^\pm = E\pm p_z,\, \hat{p}_\perp = \tfrac{p_\perp}{|p_\perp|},\,
p_\perp = p_x + i p_y$. The spinors for vanishing transverse momentum
are obtained by replacing $\hat{p}_\perp \to -1$.
This gives
\begin{equation}
\label{eq:jminus_gen}
j^-(p,\mu_1,\dots,\mu_{2N-1},q) = u^{-,\dagger}(p)\ \sigma^-_{\mu_1}\ \sigma^+_{\mu_2}\dots\sigma^-_{\mu_{2N-1}}\ u^{-}(q)\,.
\end{equation}
where $\sigma_\mu^\pm = (1, \pm \sigma_i)$ and $\sigma_i$ are the Pauli
matrices
\begin{equation}
\label{eq:Pauli_matrices}
\sigma_1 =
\begin{pmatrix}
0 & 1\\ 1 & 0
\end{pmatrix}
\,,
\qquad \sigma_2 =
\begin{pmatrix}
0 & -i\\ i & 0
\end{pmatrix}
\,,
\qquad \sigma_3 =
\begin{pmatrix}
1 & 0\\ 0 & -1
\end{pmatrix}
\,.
\end{equation}
For positive-helicity currents we can either flip all helicities in
eq.~(\ref{eq:jminus_gen}) or reverse the order of the arguments, i.e.
\begin{equation}
\label{eq:jplus_gen}
j^+(p,\mu_1,\dots,\mu_{2N-1},q) = \big(j^-(p,\mu_1,\dots,\mu_{2N-1},q)\big)^* = j^-(q,\mu_{2N-1},\dots,\mu_1,p) \,.
\end{equation}
Using the standard spinor-helicity notation we have
\begin{gather}
\label{eq:spinors_spinhel}
u^+(p) = | p \rangle\,, \qquad u^-(p) = | p ]\,, \qquad u^{+,\dagger}(p) = [ p |\,, \qquad u^{-,\dagger}(p) = \langle p |\,,\\
\label{eq:current_spinhel}
j^-(p,\mu_1,\dots,\mu_{2N-1},q) = \langle p |\ \mu_1\ \dots\ \mu_{2N-1}\ | q ] \,.\\
\label{eq:contraction_spinhel}
P_{\mu_i} j^-(p,\mu_1,\dots,\mu_{2N-1},q) = \langle p |\ \mu_1\ \dots\ \mu_{i-1}\ P\ \mu_{i+1}\ \dots\ \mu_{2N-1}\ | q ] \,.
\end{gather}
Lightlike momenta $p$ can be decomposed into spinor products:
\begin{equation}
\label{eq:p_decomp}
\slashed{p} = |p\rangle [p| + |p] \langle p |\,.
\end{equation}
Taking into account helicity conservation this gives the following relations:
\begingroup
\addtolength{\jot}{1em}
\begin{align}
\label{eq:p_in_current}
\langle p |\ \mu_1\ \dots\ \mu_i\ P\ \mu_{i+1}\ \dots\ \mu_{2N-1}\ | q ] ={}&
\begin{cases}
\langle p |\ \mu_1\ \dots\ \mu_i\ |P]\ \langle P|\ \mu_{i+1}\ \dots\ \mu_{2N-1}\ | q ]& i \text{ even}\\
\langle p |\ \mu_1\ \dots\ \mu_i\ |P\rangle\ [ P|\ \mu_{i+1}\ \dots\ \mu_{2N-1}\ | q ]& i \text{ odd}
\end{cases}\,,\\
\label{eq:p_in_angle}
\langle p |\ \mu_1\ \dots\ \mu_i\ P\ \mu_{i+1}\ \dots\ \mu_{2N}\ | q \rangle ={}&
\begin{cases}
\langle p |\ \mu_1\ \dots\ \mu_i\ |P]\ \langle P| \mu_{i+1}\ \dots\ \mu_{2N}\ | q \rangle & i \text{ even}\\
\langle p |\ \mu_1\ \dots\ \mu_i\ |P\rangle\ \big(\langle P| \mu_{i+1}\ \dots\ \mu_{2N}\ | q ]\big)^* & i \text{ odd}
\end{cases}\,,\\
\label{eq:p_in_square}
[ p |\ \mu_1\ \dots\ \mu_i\ P\ \mu_{i+1}\ \dots\ \mu_{2N}\ | q ] ={}&
\begin{cases}
\big(\langle p |\ \mu_1\ \dots\ \mu_i\ |P]\big)^* \ [ P| \mu_{i+1}\ \dots\ \mu_{2N}\ | q ] & i \text{ even}\\
[ p |\ \mu_1\ \dots\ \mu_i\ |P]\ \langle P| \mu_{i+1}\ \dots\ \mu_{2N}\ | q ] & i \text{ odd}
\end{cases}\,.
\end{align}
\endgroup
For contractions of vector currents we can use the Fierz identity
\begin{equation}
\label{eq:Fierz}
\langle p|\ \mu\ |q]\ \langle k|\ \mu\ |l] = 2 \spa p.k \spb l.q\,.
\end{equation}
The scalar angle and square products are given by
\begin{align}
\label{eq:angle_product}
\spa p.q ={}& {\big(u^-(p)\big)}^\dagger u^+(q) =
\sqrt{p^-q^+}\hat{p}_{i,\perp} - \sqrt{p^+q^-}\hat{q}_{j,\perp} = - \spa q.p\,,\\
\label{eq:square_product}
\spb p.q ={}& {\big(u^+(p)\big)}^\dagger u^-(q) = -\spa p.q ^* = - \spb q.p\,.
\end{align}
We also define polarisation vectors
\begin{equation}
\label{eq:pol_vector}
\epsilon_\mu^-(p_g, p_r) = \frac{\langle p_r|\mu|p_g]}{\sqrt{2}\spa p_g.{p_r}}\,,\qquad\epsilon_\mu^+(p_g, p_r) = \frac{\langle p_g|\mu|p_r]}{\sqrt{2}\spb p_g.{p_r}}\,.
\end{equation}
fulfilling
\begin{equation}
\label{eq:pol_vector_norm}
\epsilon_\mu^\lambda(p_g, p_r)\big[\epsilon^{\mu\,\lambda'}(p_g, p_r)\big]^* = -\delta_{\lambda\lambda'}\,.
\end{equation}
\subsubsection{Contraction algorithm}
\label{sec:contr_calc_algo}
The contractions are now calculated as follows:
\begin{enumerate}
\item Use equations \eqref{eq:jplus_gen}, \eqref{eq:current_spinhel} to write all currents in a canonical form.
\item Assume that all momenta are lightlike and use the relations
\eqref{eq:p_in_current}, \eqref{eq:p_in_angle}, \eqref{eq:p_in_square}
to split up currents that are contracted with momenta.
\item Apply the Fierz transformation~\eqref{eq:Fierz} to eliminate
contractions between vector currents.
\item Write the arguments of the antisymmetric angle and scalar products in canonical order, see equations~\eqref{eq:angle_product} ,\eqref{eq:square_product}.
\end{enumerate}
The corresponding \lstinline!ContractCurrents! procedure is implemented in
\texttt{include/helspin.fm}.
\section{The fixed-order generator}
\label{sec:HEJFOG}
Even at leading order, standard fixed-order generators can only generate
events with a limited number of final-state particles within reasonable
CPU time. The purpose of the fixed-order generator is to supplement this
with high-multiplicity input events according to the first two lines of
eq.~\eqref{eq:resumdijetFKLmatched2} with the \HEJ approximation
$\mathcal{M}_\text{LO, \HEJ}^{f_1f_2\to f_1g\cdots gf_2}$ instead of the
full fixed-order matrix element $\mathcal{M}_\text{LO}^{f_1f_2\to
f_1g\cdots gf_2}$. Its usage is described in the user
documentation \url{https://hej.web.cern.ch/HEJ/doc/current/user/HEJFOG.html}.
\subsection{File structure}
\label{sec:HEJFOG_structure}
The code for the fixed-order generator is in the \texttt{FixedOrderGen}
directory, which contains the following:
\begin{description}
\item[include:] Contains the C++ header files.
\item[src:] Contains the C++ source files.
\item[t:] Contains the source code for the automated tests.
\item[CMakeLists.txt:] Configuration file for the \cmake build system.
\item[configFO.yml:] Sample configuration file for the fixed-order generator.
\end{description}
The code is generally in the \lstinline!HEJFOG! namespace. Functions and
classes \lstinline!MyClass! are usually declared in
\texttt{include/MyClass.hh} and implemented in \texttt{src/MyClass.cc}.
\subsection{Program flow}
\label{sec:prog_flow}
A single run of the fixed-order generator consists of three or four
stages.
First, we perform initialisation similar to \HEJ 2, see
section~\ref{sec:init}. Since there is a lot of overlap we frequently
reuse classes and functions from \HEJ 2, i.e. from the
\lstinline!HEJ! namespace. The code for parsing the configuration file
is in \texttt{include/config.hh} and implemented in
\texttt{src/config.cc}.
If partial unweighting is requested in the user settings \url{https://hej.web.cern.ch/HEJ/doc/current/user/HEJFOG.html#settings},
the initialisation is followed by a calibration phase. We use a
\lstinline!EventGenerator! to produce a number of trial
events. We use these to calibrate the \lstinline!Unweighter! in
its constructor and produce a first batch of partially unweighted
events. This also allows us to estimate our unweighting efficiency.
In the next step, we continue to generate events and potentially
unweight them. Once the user-defined target number of events is reached,
we adjust their weights according to the number of required trials. As
in \HEJ 2 (see section~\ref{sec:processing}), we pass the final
events to a number of \lstinline!HEJ::Analysis! objects and a
\lstinline!HEJ::CombinedEventWriter!.
\subsection{Event generation}
\label{sec:evgen}
Event generation is performed by the
\lstinline!EventGenerator::gen_event! member function. We begin by generating a
\lstinline!PhaseSpacePoint!. This is not to be confused with
the resummation phase space points represented by
\lstinline!HEJ::PhaseSpacePoint!! After jet clustering, we compute the
leading-order matrix element (see section~\ref{sec:ME}) and pdf factors.
The phase space point generation is performed in the
\lstinline!PhaseSpacePoint! constructor. We first construct the
user-defined number of $n_p$ partons (by default gluons) in
\lstinline!PhaseSpacePoint::gen_LO_partons!. We use flat sampling in
rapidity and azimuthal angle. The scalar transverse momenta is
generated based on a random variable $x_{p_\perp}$ according to
\begin{equation}
\label{eq:pt_sampling}
p_\perp = p_{\perp,\text{min}} +
p_{\perp,\text{par}}
\tan\left(
x_{p_\perp}
\arctan\left(
\frac{p_{\perp,\text{max}} - p_{\perp,\text{min}}}{p_{\perp,\text{par}}}
\right)
\right)\,,
\end{equation}
where $p_{\perp,\text{min}}$ is the minimum jet transverse momentum,
$p_{\perp,\text{max}}$ is the maximum transverse parton momentum,
tentatively set to the beam energy, and $p_{\perp,\text{par}}$
is a generation parameter set to the heuristically determined value of
\begin{equation}
\label{eq:pt_par}
p_{\perp,\text{par}}=p_{\perp,\min}+\frac{n_p}{5}.
\end{equation}
The problem with this generation is that the transverse momenta peak at
the minimum transverse momentum required for fixed-order jets. However,
if we use the generated events as input for \HEJ resummation, events
with such soft transverse momenta hardly contribute, see
section~\ref{sec:ptj_res}. To generate efficient input for resummation,
there is the user option \texttt{peak pt}, which specifies the
dominant transverse momentum for resummation jets. If this option is
set, most jets will be generated as above, but with
$p_{\perp,\text{min}}$ set to the peak transverse momentum $p_{\perp,
\text{peak}}$. In addition, there is a small chance of around $2\%$ to
generate softer jets. The heuristic ansatz for the transverse momentum
distribution in the ``soft'' region is
\begin{equation}
\label{FO_pt_soft}
\frac{\partial \sigma}{\partial p_\perp} \propto e^{n_p\frac{p_\perp- p_{\perp,
\text{peak}}}{\bar{p}_\perp}}\,,
\end{equation}
where $n_p$ is the number of partons and $\bar{p}_\perp \approx
4\,$GeV. To achieve this distribution, we use
\begin{equation}
\label{eq:FO_pt_soft_sampling}
p_\perp = p_{\perp, \text{peak}} + \bar{p}_\perp \frac{\log x_{p_\perp}}{n_p}
\end{equation}
and discard the phase space point if the parton is too soft, i.e. below the threshold for
fixed-order jets.
After ensuring that all partons form separate jets, we generate any
potential colourless emissions. We then determine the incoming momenta
and flavours in \lstinline!PhaseSpacePoint::reconstruct_incoming! and
adjust the outgoing flavours to ensure an FKL configuration. Finally, we
may reassign outgoing flavours to generate suppressed (for example
unordered) configurations.
\input{currents}
\appendix
\section{Continuous Integration}
\label{sec:CI}
Whenever you are implementing something new or fixed a bug, please also add a
test for the new behaviour to \texttt{t/CMakeLists.txt} via
\lstinline!add_test!. These test can be triggered by running
\lstinline!make test! or \lstinline!ctest! after compiling. A typical test
should be at most a few seconds, so it can be potentially run on each commit
change by each developer. If you require a longer, more careful test, preferably
on top of a small one, surround it with
\begin{lstlisting}[caption={}]
if(${TEST_ALL})
add_test(
NAME t_feature
COMMAND really_long_test
)
endif()
\end{lstlisting}
Afterwards you can execute the longer tests with\footnote{No recompiling is
needed, as long as only the \lstinline!add_test! command is guarded, not the
compiling commands itself.}
\begin{lstlisting}[language=sh,caption={}]
cmake base/directory -DTEST_ALL=TRUE
make test
\end{lstlisting}
On top of that you should add
\href{https://en.cppreference.com/w/cpp/error/assert}{\lstinline!assert!s} in
the code itself. They are only executed when compiled with
\lstinline!CMAKE_BUILD_TYPE=Debug!, without slowing down release code. So you
can use them everywhere to test \textit{expected} or \textit{assumed} behaviour,
e.g. requiring a Higgs boson or relying on rapidity ordering.
GitLab provides ways to directly test code via \textit{Continuous integrations}.
The CI is controlled by \texttt{.gitlab-ci.yml}. For all options for the YAML
file see \href{https://docs.gitlab.com/ee/ci/yaml/}{docs.gitlab.com/ee/ci/yaml/}.https://gitlab.dur.scotgrid.ac.uk/hej/docold/tree/master/Theses
GitLab also provides a small tool to check that YAML syntax is correct under
\lstinline!CI/CD > Pipelines > CI Lint! or
\href{https://gitlab.dur.scotgrid.ac.uk/hej/HEJ/-/ci/lint}{gitlab.dur.scotgrid.ac.uk/hej/HEJ/-/ci/lint}.
Currently the CI is configured to trigger a \textit{Pipeline} on each
\lstinline!git push!. The corresponding \textit{GitLab runners} are configured
under \lstinline!CI/CD Settings>Runners! in the GitLab UI. All runners use a
\href{https://www.docker.com/}{docker} image as virtual environments\footnote{To
use only Docker runners set the \lstinline!docker! tag in
\texttt{.gitlab-ci.yml}.}. The specific docker images maintained separately. If
you add a new dependencies, please also provide a docker image for the CI. The
goal to be able to test \HEJ with all possible configurations.
Each pipeline contains multiple stages (see \lstinline!stages! in
\texttt{.gitlab-ci.yml}) which are executed in order from top to bottom.
Additionally each stage contains multiple jobs. For example the stage
\lstinline!build! contains the jobs \lstinline!build:basic!,
\lstinline!build:qcdloop!, \lstinline!build:rivet!, etc., which compile \HEJ for
different environments and dependencies, by using different Docker images. Jobs
starting with an dot are ignored by the Runner, e.g. \lstinline!.HEJ_build! is
only used as a template, but never executed directly. Only after all jobs of the
previous stage was executed without any error the next stage will start.
To pass information between multiple stages we use \lstinline!artifacts!. The
runner will automatically load all artifacts form all \lstinline!dependencies!
for each job\footnote{If no dependencies are defined \textit{all} artifacts from
all previous jobs are downloaded. Thus please specify an empty dependence if you
do not want to load any artifacts.}. For example the compiled \HEJ code from
\lstinline!build:basic! gets loaded in \lstinline!test:basic! and
\lstinline!FOG:build:basic!, without recompiling \HEJ again. Additionally
artifacts can be downloaded from the GitLab web page, which could be handy for
debugging.
We also trigger some jobs \lstinline!only! on specific events. For example we
only push the code to
\href{https://phab.hepforge.org/source/hej/repository/v2.0/}{HepForge} on
release branches (e.g. v2.0). Also we only execute the \textit{long} tests for
merge requests, on pushes for any release or the \lstinline!master! branch, or
when triggered manually from the GitLab web page.
The actual commands are given in the \lstinline!before_script!,
\lstinline!script! and \lstinline!after_script!
\footnote{\lstinline!after_script! is always executed} sections, and are
standard Linux shell commands (dependent on the docker image). Any failed
command, i.e. returning not zero, stops the job and making the pipeline fail
entirely. Most tests are just running \lstinline!make test! or are based on it.
Thus, to emphasise it again, write tests for your code in \lstinline!cmake!. The
CI is only intended to make automated testing in different environments easier.
\section{Monte Carlo uncertainty}
\label{sec:MC_err}
Since \HEJ is reweighting each Fixed Order point with multiple resummation
events, the Monte Carlo uncertainty of \HEJ is a little bit more complicated
then usual. We start by defining the \HEJ cross section after $N$ FO points
\begin{align}
\sigma_N:=\sum_{i}^N x_i \sum_{j}^{M_i} y_{i,j}=:\sum_i^N\sum_j^{M_i} w_{i,j},
\end{align}
where $x_i$ are the FO weights\footnote{In this definition $x_i$ can be zero,
see the discussion in the next section.}, $y_{i,j}$ are the reweighting weights
, and $M_i$ the number of resummation points. We can set $M=M_i \forall i$ by
potentially adding some points with $y_{i,j}=0$, i.e. $M$ correspond to the
\lstinline!trials! in \lstinline!EventReweighter!. $w_{i,j}$ are the weights as
written out by \HEJ. The expectation value of $\sigma$ is then
\begin{align}
\ev{\sigma_N}= \sum_i \ev{x_i}\sum_j\ev{y_{i,j}}=M \mu_x\sum_i\mu_{y_i},\label{eq:true_sigma}
\end{align}
with $\mu_{x/y}$ being the (true) mean value of $x$ or $y$, i.e.
\begin{align}
\mu_{x}:=\ev{\bar{x}}=\ev{\frac{\sum_i x_i}{N}}=\ev{x}.
\end{align}
The true underlying standard derivation on $\sigma_N$, assuming $\delta_{x}$
and $\delta_{y_i}$ are the standard derivations of $x$ and $y_i$ is
\begin{align}
\delta_{\sigma_N}^2&=M^2 \delta_{x}^2 \sum_i \mu_{y_i}^2
+M \mu_x^2 \sum_i \delta_{y_i}^2. \label{eq:true_err}
\end{align}
Notice that each point $i$ can have an different expectation for $y_i$.
Since we do not know the true distribution of $x$ and $y$ we need to estimate
it. We use the standard derivation
\begin{align}
\tilde{\delta}_{x_i}^2&:=\left(x_i-\bar x\right)^2
=\left(\frac{N-1}{N} x_i - \frac{\sum_{j\neq i} x_j}{N}\right)^2
\label{eq:err_x}\\
\tilde{\delta}_{y_{i,j}}^2&:=\left(y_{i,j}-\bar y_i\right)^2 \label{eq:err_y},
\end{align}
and the mean values $\bar x$ and $\bar y$, to get an estimator for
$\delta_{\sigma_N}$
\begin{align}
\tilde\delta_{\sigma_N}^2&=M^2 \sum_i \tilde\delta_{x_i}^2 \bar{y_i}^2
+\sum_{i,j} x_i^2\tilde\delta_{y_{i,j}}^2. \label{eq:esti_err}
\end{align}
Trough error propagation we can connect the estimated uncertainties back to the
fundamental ones
\begin{align}
\delta_{\tilde{\delta}_{x_i}}^2=\frac{N-1}{N} \delta_x^2.
\end{align}
Together with $\delta_x^2=\ev{x^2}-\ev{x}^2$ and $\ev{\tilde\delta}=0$ this
leads to
\begin{align}
\ev{\tilde{\delta}_{x_i}^2 \bar y_i^2}&=\ev{\tilde{\delta}_{x_i} \bar y_i}^2
+\delta_{\tilde{\delta}_{x_i}}^2 \mu_{y_i}^2
+\delta_{y_i}^2 \mu_{\tilde\delta}^2 \\
&=\frac{N-1}{N} \delta_x^2\mu_{y_i}^2,
\end{align}
and a similar results for $y$. Therefore
\begin{align}
\ev{\delta_{\sigma_N}}=\frac{N-1}{N} M^2 \delta_{x}^2 \sum_i \mu_{y_i}^2
+\frac{M-1}{M} M \mu_x^2 \sum_i \delta_{y_i}^2,
\end{align}
where we can compensate for the additional factors compared to~\eqref{eq:true_err}, by replacing
\begin{align}
\tilde\delta_x&\to\frac{N}{N-1}\tilde\delta_x \label{eq:xcom_bias}\\
\tilde\delta_{y_i}&\to\frac{M}{M-1}\tilde\delta_{y_i}. \label{eq:ycom_bias}
\end{align}
Thus~\eqref{eq:esti_err} is an unbiased estimator of $\delta_{\sigma_N}$.
\subsection{Number of events vs. number of trials}
Even though the above calculation is completely valid, it is unpractical. Both
$x_i$ and $y_{ij}$ could be zero, but zero weight events are typically not
written out. In that sense $N$ and $M$ are the \textit{number of trials} it took
to generate $N'$ and $M'$ (non-zero) events. We can not naively replace all $N$
and $M$ with $N'$ and $M'$ in the above equations, since this would also change
the definition of the average $\bar x$ and $\bar y$.
For illustration let us consider unweighted events, with all weights equal to
$x'$, without changing the cross section $\sum_i^N x_i=\sum_i^{N'} x'_i=N' x'$.
Then the average trial weight is unequal to the average event weight
\begin{align}
\bar x = \frac{\sum_i^{N} x_i}{N} = \frac{\sum_i^{N'} x'}{N}=x'\frac{N'}{N}
\neq x'=\frac{\sum_i^{N'} x'}{N'}.
\end{align}
$N=N'$ would correspond to an $100\%$ efficient unweighting, i.e. a perfect
sampling, where we know the analytical results. In particular using $N'$ instead
of $N$ in the standard derivation gives
\begin{align}
\sum_i \left(x_i-\frac{\sum_i^{N} x_i}{N'}\right)^2=\sum_i \left(x'-x' \frac{\sum_i^{N'}}{N'}\right)^2=0,
\end{align}
which is obviously not true in general for $\tilde\delta^2_x$.
Hence we would have to use the number of trials $N$ everywhere. This would
require an additional parameter to be passed with each events, which is not
always available in practice\footnote{ \texttt{Sherpa} gives the number of
trials, as an \lstinline!attribute::trials! of \lstinline!HEPEUP! in the
\texttt{LHE} file, or similarly as a data member in the HDF5 format
\cite{Hoeche:2019rti}. The \texttt{LHE} standard itself provides the
variable \lstinline!ntries! per event (see
\href{https://phystev.cnrs.fr/wiki/2017:groups:tools:lhe}{this proposal}),
though I have not seen this used anywhere.}. Instead we use
\begin{align}
\tilde\delta_{x}'^2:=\sum_i^{N} x_i^2\geq\tilde\delta_x^2, \label{eq:err_prac}
\end{align}
where the bias of $\delta_x'^2$ vanishes for large $N$. Thus we can use the sum
of weight squares~\eqref{eq:err_prac} instead of~\eqref{eq:err_x}
and~\eqref{eq:err_y}, without worrying about the difference between trials and
generated events. The total error~\eqref{eq:esti_err} becomes
\begin{align}
\tilde\delta_{\sigma_N}^2=\sum_i \left(\sum_j w_{i,j}\right)^2+\sum_{i,j} \left(w_{i,j}\right)^2,
\end{align}
which (conveniently) only dependent on the \HEJ weights $w_{i,j}$.
\section{Explicit formulas for vector currents}
\label{sec:j_vec}
Using eqs.~\eqref{eq:u_plus}\eqref{eq:u_minus}\eqref{eq:jminus_gen}\eqref{eq:Pauli_matrices}\eqref{eq:jplus_gen}, the vector currents read
\begin{align}
\label{eq:j-_explicit}
j^-_\mu(p, q) ={}&
\begin{pmatrix}
\sqrt{p^+\,q^+} + \sqrt{p^-\,q^-} \hat{p}_{\perp} \hat{q}_{\perp}^*\\
\sqrt{p^-\,q^+}\, \hat{p}_{\perp} + \sqrt{p^+\,q^-}\,\hat{q}_{\perp}^*\\
-i \sqrt{p^-\,q^+}\, \hat{p}_{\perp} + i \sqrt{p^+\,q^-}\, \hat{q}_{\perp}^*\\
\sqrt{p^+\,q^+} - \sqrt{p^-\,q^-}\, \hat{p}_{\perp}\, \hat{q}_{\perp}^*
\end{pmatrix}\,,\\
j^+_\mu(p, q) ={}&\big(j^-_\mu(p, q)\big)^*\,,\\
j^\pm_\mu(q, p) ={}&\big(j^\pm_\mu(p, q)\big)^*\,.
\end{align}
If $q= p_{\text{in}}$ is the momentum of an incoming parton, we have
$\hat{p}_{\text{in} \perp} = -1$ and either $p_{\text{in}}^+ = 0$ or
$p_{\text{in}}^- = 0$. The current simplifies further:\todo{Helicities flipped w.r.t code}
\begin{align}
\label{eq:j_explicit}
j^-_\mu(p_{\text{out}}, p_{\text{in}}) ={}&
\begin{pmatrix}
\sqrt{p_{\text{in}}^+\,p_{\text{out}}^+}\\
\sqrt{p_{\text{in}}^+\,p_{\text{out}}^-} \ \hat{p}_{\text{out}\,\perp}\\
-i\,j^-_1\\
j^-_0
\end{pmatrix}
& p_{\text{in}\,z} > 0\,,\\
j^-_\mu(p_{\text{out}}, p_{\text{in}}) ={}&
\begin{pmatrix}
-\sqrt{p_{\text{in}}^-\,p_{\text{out}}^{-\phantom{+}}} \ \hat{p}_{\text{out}\,\perp}\\
- \sqrt{p_{\text{in}}^-\,p_{\text{out}}^+}\\
i\,j^-_1\\
-j^-_0
\end{pmatrix} & p_{\text{in}\,z} < 0\,.
\end{align}
\bibliographystyle{JHEP}
\bibliography{biblio}
\end{document}
diff --git a/doc/developer_manual/src/HEJ_peripheral_Higgs_amplitude.asy b/doc/developer_manual/src/HEJ_peripheral_Higgs_amplitude.asy
index 38b9780..1510de4 100644
--- a/doc/developer_manual/src/HEJ_peripheral_Higgs_amplitude.asy
+++ b/doc/developer_manual/src/HEJ_peripheral_Higgs_amplitude.asy
@@ -1,92 +1,79 @@
import feynman;
usepackage("fourier");
// usepackage("sansmathfonts");
// texpreamble("\renewcommand{\familydefault}{\sfdefault}");
defaultpen(fontsize(8));
path zigzag(path g, real step=2, real distance=2) {
real len = arclength(g);
int state = 0;
path zig;
for (real u = 0; u < len; u += step) {
real t = arctime(g, u);
pair p = point(g, t);
pair norm = unit(rotate(90) * dir(g, t));
if (state == 1)
p = p + distance * norm;
else if (state == 3)
p = p - distance * norm;
zig = zig -- p;
state = (state + 1) % 4;
}
zig = zig -- point(g, length(g));
return zig;
}
real h = 80;
real w = 60;
real arrsize = 15;
real arrdist = 7;
real vxsize=7;
pair[] v = {
(0,h), (0,h/3), (0,-h/3), (0,-h)
};
path box = scale(vxsize)*shift(SW/sqrt(2))*unitsquare;
path triangle = scale(vxsize)*(E -- N/2 -- S/2 --cycle);
path pa = (-w,h)--(-2*vxsize,h);
-draw(pa, currentpen+1);
draw(gluon(pa));
-draw("$p_a$", shift(arrdist*S)*((midpoint(pa)+arrsize/2*W) -- (midpoint(pa)+arrsize/2*E)), Arrow(4));
+draw("$p_g$", shift(arrdist*S)*((midpoint(pa)+arrsize/2*W) -- (midpoint(pa)+arrsize/2*E)), Arrow(4));
path p1 = (w,h)--(2*vxsize,h);
-draw(p1, currentpen+1);
-draw(gluon(p1));
-draw("$p_1$", shift(arrdist*S)*((midpoint(p1)+arrsize/2*W) -- (midpoint(p1)+arrsize/2*E)), Arrow(4));
+draw(p1, dashed);
+draw("$p_H$", shift(arrdist*S)*((midpoint(p1)+arrsize/2*W) -- (midpoint(p1)+arrsize/2*E)), Arrow(4));
path pb = (-w,-h)--(-2*vxsize,-h);
draw(pb, currentpen+1);
draw(gluon(pb));
draw(Label("$p_b$", MidPoint, N), shift(arrdist*N)*((midpoint(pb)+arrsize/2*W) -- (midpoint(pb)+arrsize/2*E)), Arrow(4));
path pn = (w,-h)--(2*vxsize,-h);
draw(pn, currentpen+1);
draw(gluon(pn));
draw(Label("$p_n$", MidPoint, N), shift(arrdist*N)*((midpoint(pn)+arrsize/2*W) -- (midpoint(pn)+arrsize/2*E)), Arrow(4));
path q1 = v[0]-(0,vxsize/2)--v[1]+(0,vxsize/2);
draw(zigzag(q1), red);
draw(Label("$q_1$", MidPoint, E), shift(arrdist*E)*((midpoint(q1)+arrsize/2*N) -- (midpoint(q1)+arrsize/2*S)), red, Arrow(4));
draw(
zigzag(v[1]-(0,vxsize/2)--v[1]-(0,vxsize/2)+7S),
red
);
draw(v[1]-(0,vxsize/2)+7S --v[2]+(0,vxsize/2)+7N, red+Dotted);
draw(
zigzag(v[2]+(0,vxsize/2)+7N--v[2]+(0,vxsize/2)),
red
);
path qn = v[2]-(0,vxsize/2)--v[3]+(0,vxsize/2);
draw(zigzag(qn), red);
draw(Label("$q_{n-1}$", MidPoint, E), shift(arrdist*E)*((midpoint(qn)+arrsize/2*N) -- (midpoint(qn)+arrsize/2*S)), red, Arrow(4));
draw(gluon(v[1]+(vxsize/2,0)--(w,v[1].y)));
filldraw(shift(v[1])*box,grey);
draw(gluon(v[2]+(vxsize/2,0)--(w,v[2].y)));
filldraw(shift(v[2])*box,grey);
draw(rotate(90)*"Increasing rapidity", (1.5w,h)--(1.5w,-h),Arrow);
filldraw(shift(0, h)*xscale(7)*box, blue);
filldraw(shift(0, -h)*xscale(7)*box, blue);
-
-path pH = (0,h)+vxsize/2*N -- (w,4/3*h);
-draw(pH, dashed);
-draw(
- Label(rotate(degrees(dir(pH)))*"$p_H$", MidPoint, N),
- shift(arrdist*(rotate(90)*dir(pH)))*
- shift(midpoint(pH))*
- rotate(degrees(dir(pH)))*
- (arrdist*W--arrdist*E),
- Arrow(4)
- );
diff --git a/include/HEJ/Event.hh b/include/HEJ/Event.hh
index 00ed131..77f9f53 100644
--- a/include/HEJ/Event.hh
+++ b/include/HEJ/Event.hh
@@ -1,376 +1,391 @@
/** \file
* \brief Declares the Event class and helpers
*
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#pragma once
#include <array>
#include <cstddef>
#include <iosfwd>
#include <iterator>
#include <unordered_map>
#include <utility>
#include <vector>
#include "boost/iterator/filter_iterator.hpp"
#include "fastjet/ClusterSequence.hh"
#include "fastjet/PseudoJet.hh"
#include "HEJ/Constants.hh"
#include "HEJ/Parameters.hh"
#include "HEJ/Particle.hh"
#include "HEJ/event_types.hh"
namespace LHEF {
class HEPEUP;
class HEPRUP;
}
namespace fastjet {
class JetDefinition;
}
namespace HEJ {
struct RNG;
struct UnclusteredEvent;
/** @brief An event with clustered jets
*
* This is the main HEJ 2 event class.
* It contains kinematic information including jet clustering,
* parameter (e.g. scale) settings and the event weight.
*/
class Event {
public:
class EventData;
//! Iterator over partons
using ConstPartonIterator = boost::filter_iterator<
bool (*)(Particle const &),
std::vector<Particle>::const_iterator
>;
//! Reverse Iterator over partons
using ConstReversePartonIterator = std::reverse_iterator<
ConstPartonIterator>;
//! No default Constructor
Event() = delete;
//! Event Constructor adding jet clustering to an unclustered event
//! @deprecated UnclusteredEvent got superseded by EventData
//! and will be removed in HEJ 2.2.0
[[deprecated("UnclusteredEvent got superseded by EventData")]]
Event(
UnclusteredEvent const & ev,
fastjet::JetDefinition const & jet_def, double min_jet_pt
);
//! @name Particle Access
//! @{
//! Incoming particles
std::array<Particle, 2> const & incoming() const{
return incoming_;
}
//! Outgoing particles
std::vector<Particle> const & outgoing() const{
return outgoing_;
}
//! Iterator to the first outgoing parton
ConstPartonIterator begin_partons() const;
//! Iterator to the first outgoing parton
ConstPartonIterator cbegin_partons() const;
//! Iterator to the end of the outgoing partons
ConstPartonIterator end_partons() const;
//! Iterator to the end of the outgoing partons
ConstPartonIterator cend_partons() const;
//! Reverse Iterator to the first outgoing parton
ConstReversePartonIterator rbegin_partons() const;
//! Reverse Iterator to the first outgoing parton
ConstReversePartonIterator crbegin_partons() const;
//! Reverse Iterator to the first outgoing parton
ConstReversePartonIterator rend_partons() const;
//! Reverse Iterator to the first outgoing parton
ConstReversePartonIterator crend_partons() const;
//! Particle decays
/**
* The key in the returned map corresponds to the index in the
* vector returned by outgoing()
*/
std::unordered_map<std::size_t, std::vector<Particle>> const & decays()
const {
return decays_;
}
//! The jets formed by the outgoing partons, sorted in rapidity
std::vector<fastjet::PseudoJet> const & jets() const{
return jets_;
}
//! @}
//! @name Weight variations
//! @{
//! All chosen parameter, i.e. scale choices (const version)
Parameters<EventParameters> const & parameters() const{
return parameters_;
}
//! All chosen parameter, i.e. scale choices
Parameters<EventParameters> & parameters(){
return parameters_;
}
//! Central parameter choice (const version)
EventParameters const & central() const{
return parameters_.central;
}
//! Central parameter choice
EventParameters & central(){
return parameters_.central;
}
//! Parameter (scale) variations (const version)
std::vector<EventParameters> const & variations() const{
return parameters_.variations;
}
//! Parameter (scale) variations
std::vector<EventParameters> & variations(){
return parameters_.variations;
}
//! Parameter (scale) variation (const version)
/**
* @param i Index of the requested variation
*/
EventParameters const & variations(std::size_t i) const{
return parameters_.variations.at(i);
}
//! Parameter (scale) variation
/**
* @param i Index of the requested variation
*/
EventParameters & variations(std::size_t i){
return parameters_.variations.at(i);
}
//! @}
//! Indices of the jets the outgoing partons belong to
/**
* @param jets Jets to be tested
* @returns A vector containing, for each outgoing parton,
* the index in the vector of jets the considered parton
* belongs to. If the parton is not inside any of the
* passed jets, the corresponding index is set to -1.
*/
std::vector<int> particle_jet_indices(
std::vector<fastjet::PseudoJet> const & jets
) const {
return cs_.particle_jet_indices(jets);
}
//! particle_jet_indices() of the Event jets()
std::vector<int> particle_jet_indices() const {
return particle_jet_indices(jets());
}
//! Jet definition used for clustering
fastjet::JetDefinition const & jet_def() const{
return cs_.jet_def();
}
//! Minimum jet transverse momentum
double min_jet_pt() const{
return min_jet_pt_;
}
//! Event type
event_type::EventType type() const{
return type_;
}
//! Give colours to each particle
/**
* @returns true if new colours are generated, i.e. same as is_resummable()
* @details Colour ordering is done according to leading colour in the MRK
* limit, see \cite Andersen:2011zd. This only affects \ref
* is_resummable() "HEJ" configurations, all other \ref event_type
* "EventTypes" will be ignored.
* @note This overwrites all previously set colours.
*/
bool generate_colours(RNG & /*ran*/);
//! Check that current colours are leading in the high energy limit
/**
* @details Checks that the colour configuration can be split up in
* multiple, rapidity ordered, non-overlapping ladders. Such
* configurations are leading in the MRK limit, see
* \cite Andersen:2011zd
*
* @note This is _not_ to be confused with \ref is_resummable(), however
* for all resummable states it is possible to create a leading colour
* configuration, see generate_colours()
*/
bool is_leading_colour() const;
/**
* @brief Check if given event could have been produced by HEJ
* @details A HEJ state has to fulfil:
* 1. type() has to be \ref is_resummable() "resummable"
* 2. Soft radiation in the tagging jets contributes at most to
* `soft_pt_regulator` of the total jet \f$ p_\perp \f$
*
* @note This is true for any resummed stated produced by the
* EventReweighter or any \ref is_resummable() "resummable" Leading
* Order state.
*
* @param soft_pt_regulator Maximum transverse momentum fraction from soft
* radiation in tagging jets
* @param min_pt Absolute minimal \f$ p_\perp \f$,
* \b deprecated use soft_pt_regulator instead
* @return True if this state could have been produced by HEJ
*/
bool valid_hej_state(
double soft_pt_regulator = DEFAULT_SOFT_PT_REGULATOR,
double min_pt = 0.
) const;
private:
//! \internal
//! @brief Construct Event explicitly from input.
/** This is only intended to be called from EventData.
*
* \warning The input is taken _as is_, sorting and classification has to be
* done externally, i.e. by EventData
*/
Event(
std::array<Particle, 2> && incoming,
std::vector<Particle> && outgoing,
std::unordered_map<std::size_t, std::vector<Particle>> && decays,
Parameters<EventParameters> && parameters,
fastjet::JetDefinition const & jet_def,
double min_jet_pt
);
//! Iterator over partons (non-const)
using PartonIterator = boost::filter_iterator<
bool (*)(Particle const &),
std::vector<Particle>::iterator
>;
//! Reverse Iterator over partons (non-const)
using ReversePartonIterator = std::reverse_iterator<PartonIterator>;
//! Iterator to the first outgoing parton (non-const)
PartonIterator begin_partons();
//! Iterator to the end of the outgoing partons (non-const)
PartonIterator end_partons();
//! Reverse Iterator to the first outgoing parton (non-const)
ReversePartonIterator rbegin_partons();
//! Reverse Iterator to the first outgoing parton (non-const)
ReversePartonIterator rend_partons();
std::array<Particle, 2> incoming_;
std::vector<Particle> outgoing_;
std::unordered_map<std::size_t, std::vector<Particle>> decays_;
std::vector<fastjet::PseudoJet> jets_;
Parameters<EventParameters> parameters_;
fastjet::ClusterSequence cs_;
double min_jet_pt_;
event_type::EventType type_;
}; // end class Event
+
+ //! Detect if a backward incoming gluon turns into a backward outgoing Higgs boson
+ inline
+ bool is_backward_g_to_h(Event const & ev) {
+ return ev.outgoing().front().type == pid::higgs
+ && ev.incoming().front().type == pid::gluon;
+ }
+
+ //! Detect if a forward incoming gluon turns into a forward outgoing Higgs boson
+ inline
+ bool is_forward_g_to_h(Event const & ev) {
+ return ev.outgoing().back().type == pid::higgs
+ && ev.incoming().back().type == pid::gluon;
+ }
+
//! Class to store general Event setup, i.e. Phase space and weights
class Event::EventData {
public:
//! Default Constructor
EventData() = default;
//! Constructor from LesHouches event information
EventData(LHEF::HEPEUP const & hepeup);
//! Constructor with all values given
EventData(
std::array<Particle, 2> incoming,
std::vector<Particle> outgoing,
std::unordered_map<std::size_t, std::vector<Particle>> decays,
Parameters<EventParameters> parameters
):
incoming(std::move(incoming)), outgoing(std::move(outgoing)),
decays(std::move(decays)), parameters(std::move(parameters))
{}
//! Generate an Event from the stored EventData.
/**
* @details Do jet clustering and classification.
* Use this to generate an Event.
*
* @note Calling this function destroys EventData
*
* @param jet_def Jet definition
* @param min_jet_pt minimal \f$p_T\f$ for each jet
*
* @returns Full clustered and classified event.
*/
Event cluster(
fastjet::JetDefinition const & jet_def, double min_jet_pt);
//! Alias for cluster()
Event operator()(
fastjet::JetDefinition const & jet_def, double const min_jet_pt){
return cluster(jet_def, min_jet_pt);
}
//! Sort particles in rapidity
void sort();
//! Reconstruct intermediate particles from final-state leptons
/**
* Final-state leptons are created from virtual photons, W, or Z bosons.
* This function tries to reconstruct such intermediate bosons if they
* are not part of the event record.
*/
void reconstruct_intermediate();
//! Incoming particles
std::array<Particle, 2> incoming;
//! Outcoing particles
std::vector<Particle> outgoing;
//! Particle decays in the format {outgoing index, decay products}
std::unordered_map<std::size_t, std::vector<Particle>> decays;
//! Parameters, e.g. scale or inital weight
Parameters<EventParameters> parameters;
}; // end class EventData
//! Print Event
std::ostream& operator<<(std::ostream & os, Event const & ev);
//! Square of the partonic centre-of-mass energy \f$\hat{s}\f$
double shat(Event const & ev);
//! Convert an event to a LHEF::HEPEUP
LHEF::HEPEUP to_HEPEUP(Event const & event, LHEF::HEPRUP * /*heprup*/);
// put deprecated warning at the end, so don't get the warning inside Event.hh,
// additionally doxygen can not identify [[deprecated]] correctly
struct [[deprecated("UnclusteredEvent will be replaced by EventData")]]
UnclusteredEvent;
//! An event before jet clustering
//! @deprecated UnclusteredEvent got superseded by EventData
//! and will be removed in HEJ 2.2.0
struct UnclusteredEvent{
//! Default Constructor
UnclusteredEvent() = default;
//! Constructor from LesHouches event information
UnclusteredEvent(LHEF::HEPEUP const & hepeup);
std::array<Particle, 2> incoming; /**< Incoming Particles */
std::vector<Particle> outgoing; /**< Outgoing Particles */
//! Particle decays in the format {outgoing index, decay products}
std::unordered_map<std::size_t, std::vector<Particle>> decays;
//! Central parameter (e.g. scale) choice
EventParameters central;
std::vector<EventParameters> variations; /**< For parameter variation */
};
} // namespace HEJ
diff --git a/include/HEJ/Hjets.hh b/include/HEJ/Hjets.hh
index bc87e04..0a174ef 100644
--- a/include/HEJ/Hjets.hh
+++ b/include/HEJ/Hjets.hh
@@ -1,412 +1,383 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
/** \file
* \brief Functions computing the square of current contractions in H+Jets.
*
* This file contains all the H+Jet specific components to compute
* the current contractions for valid HEJ processes, to form a full
* H+Jets ME, currently one would have to use functions from the
* jets.hh header also. We have FKL and also unordered components for
* H+Jets.
*/
#pragma once
#include "CLHEP/Vector/LorentzVector.h"
namespace HEJ {
namespace currents {
using HLV = CLHEP::HepLorentzVector;
//! Square of gg->gg Higgs+Jets Scattering Current
/**
* @param p1out Momentum of final state gluon
* @param p1in Momentum of initial state gluon
* @param p2out Momentum of final state gluon
* @param p2in Momentum of intial state gluon
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for gg->gg
*
* g~p1 g~p2
* should be called with qH1 meant to be contracted with p2 in first part of
* vertex (i.e. if g is backward, qH1 is forward)
*/
double ME_H_gg(HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
+ /**
+ * @brief Square of gq->Hq current contraction
+ * @param ph Outgoing Higgs boson momentum
+ * @param pg Incoming gluon momentum
+ * @param pn Momentum of outgoing particle in FKL current
+ * @param pb Momentum of incoming particle in FKL current
+ * @param mt top mass (inf or value)
+ * @param inc_bottom whether to include bottom mass effects (true) or not (false)
+ * @param mb bottom mass (value)
+ * @param vev Higgs vacuum expectation value
+ *
+ * Calculates helicity-averaged || \epsilon_\mu V_H^{\mu\nu} j_\nu ||^2.
+ * See eq:S_gf_Hf in developer manual
+ */
+ double ME_jgH_j(
+ HLV const & ph, HLV const & pa,
+ HLV const & pn, HLV const & pb,
+ double mt, bool inc_bottom, double mb, double vev
+ );
+
+ /**
+ * @brief Square of qg -> gqH current contraction
+ * @param pg Outgoing (unordered) gluon momentum
+ * @param ph Outgoing quark momentum
+ * @param pa Incoming quark momentum
+ * @param ph Outgoing Higgs boson momentum
+ * @param pb Incoming gluon momentum
+ * @param mt top mass (inf or value)
+ * @param inc_bottom whether to include bottom mass effects (true) or not (false)
+ * @param mb bottom mass (value)
+ * @param vev Higgs vacuum expectation value
+ *
+ * Calculates helicity-averaged || j_{uno \mu} V_H^{\mu\nu} \epsilon_\nu ||^2.
+ * See eq:S_gf_Hf in developer manual
+ */
+ double ME_juno_jgH(
+ HLV const & pg,
+ HLV const & p1, HLV const & pa,
+ HLV const & ph, HLV const & pb,
+ double mt, bool inc_bottom, double mb, double vev
+ );
+
//! Square of gq->gq Higgs+Jets Scattering Current with Higgs before Gluon
/**
* @param p1out Momentum of final state gluon
* @param p1in Momentum of initial state gluon
* @param p2out Momentum of final state gluon
* @param p2in Momentum of intial state gluon
* @param pH Momentum of Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contraction
*/
- double ME_Houtside_gq(HLV const & p1out, HLV const & p1in,
- HLV const & p2out, HLV const & p2in,
- HLV const & pH,
- double mt,
- bool include_bottom, double mb, double vev);
-
- //! Square of qg->qg Higgs+Jets Scattering Current
- /**
- * @param p1out Momentum of final state quark
- * @param p1in Momentum of initial state quark
- * @param p2out Momentum of final state gluon
- * @param p2in Momentum of intial state gluon
- * @param qH1 Momentum of t-channel propagator before Higgs
- * @param qH2 Momentum of t-channel propagator after Higgs
- * @param mt Top quark mass
- * @param include_bottom Specifies whether bottom corrections are included
- * @param mb Bottom quark mass
- * @param vev Vacuum expectation value
- * @returns Square of the current contractions for qg->qg
- *
- * q~p1 g~p2 (i.e. ALWAYS p1 for quark, p2 for gluon)
- * should be called with qH1 meant to be contracted with p2 in first part of
- * vertex (i.e. if g is backward, qH1 is forward)
- */
double ME_H_qg(HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qbarg->qbarg Higgs+Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state gluon
* @param p2in Momentum of intial state gluon
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for qbarg->qbarg
*
* qbar~p1 g~p2 (i.e. ALWAYS p1 for anti-quark, p2 for gluon)
* should be called with qH1 meant to be contracted with p2 in first part of
* vertex (i.e. if g is backward, qH1 is forward)
*/
double ME_H_qbarg(HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qQ->qQ Higgs+Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for qQ->qQ
*
* q~p1 Q~p2 (i.e. ALWAYS p1 for quark, p2 for quark)
* should be called with qH1 meant to be contracted with p2 in first part of
* vertex (i.e. if Q is backward, qH1 is forward)
*/
double ME_H_qQ(HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qQbar->qQbar Higgs+Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for qQ->qQ
*
* q~p1 Qbar~p2 (i.e. ALWAYS p1 for quark, p2 for anti-quark)
* should be called with qH1 meant to be contracted with p2 in first part of
* vertex (i.e. if Qbar is backward, qH1 is forward)
*/
double ME_H_qQbar(HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qbarQ->qbarQ Higgs+Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for qbarQ->qbarQ
*
* qbar~p1 Q~p2 (i.e. ALWAYS p1 for anti-quark, p2 for quark)
* should be called with qH1 meant to be contracted with p2 in first part of
* vertex (i.e. if Q is backward, qH1 is forward)
*/
double ME_H_qbarQ(HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qbarQbar->qbarQbar Higgs+Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for
* qbarQbar->qbarQbar
*
* qbar~p1 Qbar~p2 (i.e. ALWAYS p1 for anti-quark, p2 for anti-quark)
* should be called with qH1 meant to be contracted with p2 in first part of
* vertex (i.e. if Qbar is backward, qH1 is forward)
*/
double ME_H_qbarQbar(HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! @name Unordered backwards
//! @{
//! Square of qbarQ->qbarQg Higgs+Jets Unordered b Scattering Current
/**
* @param pg Momentum of unordered b gluon
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for
* qbarQ->qbarQg
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double ME_H_unob_qbarQ(HLV const & pg, HLV const & p1out,
HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1,
HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qQ->qQg Higgs+Jets Unordered b Scattering Current
/**
* @param pg Momentum of unordered b gluon
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for qQ->qQg
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double ME_H_unob_qQ(HLV const & pg, HLV const & p1out,
HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1,
HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qQbar->qQbarg Higgs+Jets Unordered b Scattering Current
/**
* @param pg Momentum of unordered b gluon
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for
* qQbar->qQbarg
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double ME_H_unob_qQbar(HLV const & pg, HLV const & p1out,
HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1,
HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of qbarQbar->qbarQbarg Higgs+Jets Unordered b Scattering Current
/**
* @param pg Momentum of unordered b gluon
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for
* qbarQbar->qbarQbarg
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double ME_H_unob_qbarQbar(HLV const & pg, HLV const & p1out,
HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1,
HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of gQbar->gQbarg Higgs+Jets Unordered b Scattering Current
/**
* @param pg Momentum of unordered b gluon
* @param p1out Momentum of final state gluon
* @param p1in Momentum of initial state gluon
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for
* gQbar->gQbarg
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double ME_H_unob_gQbar(HLV const & pg, HLV const & p1out,
HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1,
HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! Square of gQ->gQg Higgs+Jets Unordered b Scattering Current
/**
* @param pg Momentum of unordered b gluon
* @param p1out Momentum of final state gluon
* @param p1in Momentum of initial state gluon
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @param vev Vacuum expectation value
* @returns Square of the current contractions for gQ->gQg
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double ME_H_unob_gQ(HLV const & pg, HLV const & p1out,
HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1,
HLV const & qH2,
double mt,
bool include_bottom, double mb, double vev);
//! @}
- //! @name impact factors for Higgs + jet
- //! @{
-
- //! @brief Implements Eq. (4.22) in \cite DelDuca:2003ba with modifications to
- //! incoming plus momenta
- /**
- * @param p2 Momentum of Particle 2
- * @param p1 Momentum of Particle 1
- * @param pH Momentum of Higgs
- * @param vev Vacuum expectation value
- * @returns impact factor
- *
- * This gives the impact factor. First it determines whether this is the
- * case \f$p1p\sim php\gg p3p\f$ or the opposite
- */
- double C2gHgm(HLV const & p2, HLV const & p1, HLV const & pH, double vev);
-
- //! @brief Implements Eq. (4.23) in \cite DelDuca:2003ba with modifications to
- //! incoming plus momenta
- /**
- * @param p2 Momentum of Particle 2
- * @param p1 Momentum of Particle 1
- * @param pH Momentum of Higgs
- * @param vev Vacuum expectation value
- * @returns impact factor
- *
- * This gives the impact factor. First it determines whether this is the
- * case \f$p1p\sim php\gg p3p\f$ or the opposite
- */
- double C2gHgp(HLV const & p2, HLV const & p1, HLV const & pH, double vev);
-
- //! Implements Eq. (4.21) in \cite DelDuca:2003ba
- /**
- * @param p2 Momentum of Particle 2
- * @param p1 Momentum of Particle 1
- * @param pH Momentum of Higgs
- * @param vev Vacuum expectation value
- * @returns impact factor
- *
- * This gives the impact factor. First it determines whether this is the
- * case \f$p1p\sim php\gg p3p\f$ or the opposite
- *
- * @TODO remove this function is not used
- */
- double C2qHqm(HLV const & p2, HLV const & p1, HLV const & pH, double vev);
-
- //! @}
} // namespace currents
} // namespace HEJ
diff --git a/include/HEJ/MatrixElement.hh b/include/HEJ/MatrixElement.hh
index ddc25d6..e03dc19 100644
--- a/include/HEJ/MatrixElement.hh
+++ b/include/HEJ/MatrixElement.hh
@@ -1,204 +1,202 @@
/** \file
* \brief Contains the MatrixElement Class
*
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#pragma once
#include <functional>
#include <vector>
#include "fastjet/PseudoJet.hh"
#include "HEJ/Config.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/Parameters.hh"
namespace CLHEP {
class HepLorentzVector;
}
namespace HEJ {
class Event;
struct Particle;
//! Class to calculate the squares of matrix elements
class MatrixElement{
public:
/** \brief MatrixElement Constructor
* @param alpha_s Function taking the renormalisation scale
* and returning the strong coupling constant
* @param conf General matrix element settings
*/
MatrixElement(
std::function<double (double)> alpha_s,
MatrixElementConfig conf
);
/**
* \brief squares of regulated HEJ matrix elements
* @param event The event for which to calculate matrix elements
* @returns The squares of HEJ matrix elements including virtual corrections
*
* This function returns one value for the central parameter choice
* and one additional value for each entry in \ref Event.variations().
* See eq. (22) in \cite Andersen:2011hs for the definition of the squared
* matrix element.
*
* \internal Relation to standard HEJ Met2: MatrixElement = Met2*shat^2/(pdfta*pdftb)
*/
Weights operator()(Event const & event) const;
//! Squares of HEJ tree-level matrix elements
/**
* @param event The event for which to calculate matrix elements
* @returns The squares of HEJ matrix elements without virtual corrections
*
* cf. eq. (22) in \cite Andersen:2011hs
*/
Weights tree(Event const & event) const;
/**
* \brief Virtual corrections to matrix element squares
* @param event The event for which to calculate matrix elements
* @returns The virtual corrections to the squares of the matrix elements
*
* The all order virtual corrections to LL in the MRK limit is
* given by replacing 1/t in the scattering amplitude according to the
* lipatov ansatz.
*
* If there is more than one entry in the returned vector, each entry
* corresponds to the contribution from the interference of two
* channels. The order of these entries matches the one returned by
* the tree_kin member function, but is otherwise unspecified.
*
* cf. second-to-last line of eq. (22) in \cite Andersen:2011hs
* note that indices are off by one, i.e. out[0].p corresponds to p_1
*/
std::vector<Weights> virtual_corrections(Event const & event) const;
/**
* \brief Scale-dependent part of tree-level matrix element squares
* @param event The event for which to calculate matrix elements
* @returns The scale-dependent part of the squares of the
* tree-level matrix elements
*
* The tree-level matrix elements factorises into a renormalisation-scale
* dependent part, given by the strong coupling to some power, and a
* scale-independent remainder. This function only returns the former parts
* for the central scale choice and all \ref Event.variations().
*
* @see tree, tree_kin
*/
Weights tree_param(Event const & event) const;
/**
* \brief Kinematic part of tree-level matrix element squares
* @param event The event for which to calculate matrix elements
* @returns The kinematic part of the squares of the
* tree-level matrix elements
*
* The tree-level matrix elements factorises into a renormalisation-scale
* dependent part, given by the strong coupling to some power, and a
* scale-independent remainder. This function only returns the latter part.
*
* If there is more than one entry in the returned vector, each entry
* corresponds to the contribution from the interference of two
* channels. The order of these entries matches the one returned by
* the virtual_corrections member function, but is otherwise unspecified.
*
* @see tree, tree_param
*/
std::vector<double> tree_kin(Event const & event) const;
private:
double tree_param(
Event const & event,
double mur
) const;
double virtual_corrections_W(
Event const & event,
double mur,
Particle const & WBoson
) const;
std::vector <double> virtual_corrections_Z_qq(
Event const & event,
double mur,
Particle const & ZBoson
) const;
double virtual_corrections_Z_qg(
Event const & event,
double mur,
Particle const & ZBoson,
bool is_gq_event
) const;
std::vector<double> virtual_corrections(
Event const & event,
double mur
) const;
//! \internal cf. last line of eq. (22) in \cite Andersen:2011hs
double omega0(
double alpha_s, double mur,
fastjet::PseudoJet const & q_j
) const;
double tree_kin_jets(
Event const & ev
) const;
double tree_kin_W(
Event const & ev
) const;
std::vector <double> tree_kin_Z(
Event const & ev
) const;
double tree_kin_Higgs(
Event const & ev
) const;
double tree_kin_Higgs_first(
Event const & ev
) const;
double tree_kin_Higgs_last(
Event const & ev
) const;
- /**
- * \internal
- * \brief Higgs inbetween extremal partons.
- *
- * Note that in the case of unordered emission, the Higgs is *always*
- * treated as if in between the extremal (FKL) partons, even if its
- * rapidity is outside the extremal parton rapidities
- */
double tree_kin_Higgs_between(
Event const & ev
) const;
double tree_param_partons(
double alpha_s, double mur,
std::vector<Particle> const & partons
) const;
std::vector<int> in_extremal_jet_indices(
std::vector<fastjet::PseudoJet> const & partons
) const;
- double MH2_forwardH(
- CLHEP::HepLorentzVector const & p1out,
- CLHEP::HepLorentzVector const & p1in,
- pid::ParticleID type2,
- CLHEP::HepLorentzVector const & p2out,
- CLHEP::HepLorentzVector const & p2in,
- CLHEP::HepLorentzVector const & pH,
- double t1, double t2
+ double MH2_backwardH(
+ ParticleID type_forward,
+ CLHEP::HepLorentzVector const & pa,
+ CLHEP::HepLorentzVector const & pb,
+ CLHEP::HepLorentzVector const & pH,
+ CLHEP::HepLorentzVector const & pn
+ ) const;
+
+ double MH2_unob_forwardH(
+ CLHEP::HepLorentzVector const & pa,
+ CLHEP::HepLorentzVector const & pb,
+ CLHEP::HepLorentzVector const & pg,
+ CLHEP::HepLorentzVector const & p1,
+ CLHEP::HepLorentzVector const & pH
) const;
std::function<double (double)> alpha_s_;
MatrixElementConfig param_;
};
} // namespace HEJ
diff --git a/include/HEJ/PhaseSpacePoint.hh b/include/HEJ/PhaseSpacePoint.hh
index 6466d42..09d63f9 100644
--- a/include/HEJ/PhaseSpacePoint.hh
+++ b/include/HEJ/PhaseSpacePoint.hh
@@ -1,205 +1,208 @@
/** \file
* \brief Contains the PhaseSpacePoint Class
*
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#pragma once
#include <array>
#include <cstddef>
#include <unordered_map>
#include <utility>
#include <vector>
#include "fastjet/PseudoJet.hh"
#include "HEJ/Config.hh"
#include "HEJ/Event.hh"
#include "HEJ/Particle.hh"
#include "HEJ/StatusCode.hh"
namespace HEJ {
struct RNG;
//! Generated point in resummation phase space
class PhaseSpacePoint{
public:
//! No default PhaseSpacePoint Constructor
PhaseSpacePoint() = delete;
//! PhaseSpacePoint Constructor
/**
* @param ev Clustered Jet Event
* @param conf Configuration parameters
* @param ran Random number generator
*/
PhaseSpacePoint(
Event const & ev,
PhaseSpacePointConfig conf,
RNG & ran
);
//! Get phase space point weight
double weight() const{
return weight_;
}
//! Access incoming particles
std::array<Particle, 2> const & incoming() const{
return incoming_;
}
//! Access outgoing particles
std::vector<Particle> const & outgoing() const{
return outgoing_;
}
//! Particle decays
/**
* The key in the returned map corresponds to the index in the
* vector returned by outgoing()
*/
std::unordered_map<std::size_t, std::vector<Particle>> const & decays()
const{
return decays_;
}
//! Status code of generation
StatusCode status() const{
return status_;
}
static constexpr int NG_MAX = 1000; //!< maximum number of extra gluons
private:
friend Event::EventData to_EventData(PhaseSpacePoint psp);
//! /internal returns the clustered jets sorted in rapidity
std::vector<fastjet::PseudoJet> cluster_jets(
std::vector<fastjet::PseudoJet> const & partons
) const;
bool pass_resummation_cuts(
std::vector<fastjet::PseudoJet> const & jets
) const;
bool pass_extremal_cuts(
fastjet::PseudoJet const & ext_parton,
fastjet::PseudoJet const & jet
) const;
double estimate_emission_rapidity_range(Event const & event) const;
double estimate_ng_mean(Event const & event) const;
int sample_ng(Event const & event, RNG & ran);
int sample_ng_jets(Event const & event, int ng, RNG & ran);
double probability_in_jet(Event const & event) const;
std::vector<fastjet::PseudoJet> gen_non_jet(
int ng_non_jet, double ptmin, double ptmax, RNG & ran
);
void rescale_qqbar_rapidities(
std::vector<fastjet::PseudoJet> & out_partons,
std::vector<fastjet::PseudoJet> const & jets,
double ymin1, double ymax2,
int qqbar_backjet
);
void rescale_rapidities(
std::vector<fastjet::PseudoJet> & partons,
double ymin, double ymax
);
//! @return jets & Bosons
std::pair< std::vector<fastjet::PseudoJet>,
optional<fastjet::PseudoJet> >
reshuffle(
Event const & ev,
fastjet::PseudoJet const & q
);
/** \interal final jet test
* - number of jets must match Born kinematics
* - no partons designated as nonjet may end up inside jets
* - all other outgoing partons *must* end up inside jets
* - the extremal (in rapidity) partons must be inside the extremal jets
* - rapidities must be the same (by construction)
*/
bool jets_ok(
- std::vector<fastjet::PseudoJet> const & Born_jets,
- std::vector<fastjet::PseudoJet> const & partons
+ Event const & Born_event,
+ std::vector<fastjet::PseudoJet> const & partons
) const;
void reconstruct_incoming(std::array<Particle, 2> const & Born_incoming);
/** \interal Distribute gluon in jet
* @param jets jets to distribute gluon in
* @param ng_jets number of gluons
* @param qqbar_backjet position of first (backwards) qqbar jet
*
* relies on JetSplitter
*/
std::vector<fastjet::PseudoJet> split(
+ Event const & Born_event,
std::vector<fastjet::PseudoJet> const & jets,
- int ng_jets, std::size_t qqbar_backjet, RNG & ran
+ int ng_jets,
+ RNG & ran
);
std::vector<int> distribute_jet_partons(
int ng_jets, std::vector<fastjet::PseudoJet> const & jets, RNG & ran
);
std::vector<fastjet::PseudoJet> split(
- std::vector<fastjet::PseudoJet> const & jets,
- std::vector<int> const & np_in_jet,
- std::size_t qqbar_backjet,
- RNG & ran
+ Event const & Born_event,
+ std::vector<fastjet::PseudoJet> const & jets,
+ std::vector<int> const & np_in_jet,
+ RNG & ran
);
bool split_preserved_jets(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<fastjet::PseudoJet> const & jet_partons
) const;
template<class Particle>
Particle const & most_backward_FKL(
std::vector<Particle> const & partons
) const;
template<class Particle>
Particle const & most_forward_FKL(
std::vector<Particle> const & partons
) const;
template<class Particle>
Particle & most_backward_FKL(std::vector<Particle> & partons) const;
template<class Particle>
Particle & most_forward_FKL(std::vector<Particle> & partons) const;
bool extremal_ok(
- std::vector<fastjet::PseudoJet> const & partons
+ Event const & Born_event,
+ std::vector<fastjet::PseudoJet> const & partons
) const;
/** \internal
* Assigns PDG IDs to outgoing partons, i.e. labels them as quarks
*
* \note This function assumes outgoing_ to be pure partonic when called,
* i.e. A/W/Z/h bosons should _not be set_ at this stage
*/
void label_quarks(Event const & event);
/** \internal
* This function will label the qqbar pair in a qqbar event back to their
* original types from the input event.
*/
void label_qqbar(Event const & event);
void boost_AWZH_boson_from(
fastjet::PseudoJet const & boosted_boson, Event const & event
);
bool momentum_conserved() const;
bool contains_idx(
fastjet::PseudoJet const & jet, fastjet::PseudoJet const & parton
) const;
//! @TODO replace this with an type
bool unob_, unof_, qqbarb_, qqbarf_, qqbar_mid_;
double weight_;
PhaseSpacePointConfig param_;
std::array<Particle, 2> incoming_;
std::vector<Particle> outgoing_;
//! \internal Particle decays in the format {outgoing index, decay products}
std::unordered_map<std::size_t, std::vector<Particle>> decays_;
StatusCode status_;
};
//! Extract Event::EventData from PhaseSpacePoint
Event::EventData to_EventData(PhaseSpacePoint psp);
} // namespace HEJ
diff --git a/include/HEJ/event_types.hh b/include/HEJ/event_types.hh
index c354b3d..d83fcb4 100644
--- a/include/HEJ/event_types.hh
+++ b/include/HEJ/event_types.hh
@@ -1,109 +1,109 @@
/** \file
* \brief Define different types of events.
*
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#pragma once
#include <string>
#include "HEJ/exceptions.hh"
namespace HEJ {
//! Namespace for event types
namespace event_type {
//! Possible event types
enum EventType: std::size_t {
non_resummable = 0, //!< event configuration not covered by All Order resummation
bad_final_state = 1, //!< event with an unsupported final state
- no_2_jets = 2, //!< event with less than two jets
+ not_enough_jets = 2, //!< event with less than two jets
FKL = 4, //!< FKL-type event
unordered_backward = 8, //!< event with unordered backward emission
unordered_forward = 16, //!< event with unordered forward emission
extremal_qqbar_backward = 32, //!< event with a backward extremal qqbar
extremal_qqbar_forward = 64, //!< event with a forward extremal qqbar
central_qqbar = 128, //!< event with a central qqbar
unob = unordered_backward, //!< alias for unordered_backward
unof = unordered_forward, //!< alias for unordered_forward
qqbar_exb = extremal_qqbar_backward, //!< alias for extremal_qqbar_backward
qqbar_exf = extremal_qqbar_forward, //!< alias for extremal_qqbar_forward
qqbar_mid = central_qqbar, //!< alias for central_qqbar
first_type = non_resummable, //!< alias for non_resummable
last_type = central_qqbar //!< alias for central_qqbar
};
//! Event type names
/**
* For example, name(FKL) is the string "FKL"
*/
inline
std::string name(EventType type) {
switch(type) {
case FKL:
return "FKL";
case unordered_backward:
return "unordered backward";
case unordered_forward:
return "unordered forward";
case extremal_qqbar_backward:
return "extremal qqbar backward";
case extremal_qqbar_forward:
return "extremal qqbar forward";
case central_qqbar:
return "central qqbar";
case non_resummable:
return "non-resummable";
- case no_2_jets:
- return "no 2 jets";
+ case not_enough_jets:
+ return "not enough jets";
case bad_final_state:
return "bad final state";
default:
throw std::logic_error{"Unreachable"};
}
}
//! Returns True for a HEJ \ref event_type::EventType "EventType"
inline
constexpr bool is_resummable(EventType type) {
switch(type) {
case FKL:
case unordered_backward:
case unordered_forward:
case extremal_qqbar_backward:
case extremal_qqbar_forward:
case central_qqbar:
return true;
default:
return false;
}
}
//! Returns True for an unordered \ref event_type::EventType "EventType"
inline
constexpr bool is_uno(EventType type) {
return type == unordered_backward || type == unordered_forward;
}
//! Returns True for an extremal_qqbar \ref event_type::EventType "EventType"
inline
constexpr bool is_ex_qqbar(EventType type) {
return type == extremal_qqbar_backward || type == extremal_qqbar_forward;
}
//! Returns True for an central_qqbar \ref event_type::EventType "EventType"
inline
constexpr bool is_mid_qqbar(EventType type) {
return type == central_qqbar;
}
//! Returns True for any qqbar event \ref event_type::EventType "EventType"
inline
constexpr bool is_qqbar(EventType type) {
return is_ex_qqbar(type) || is_mid_qqbar(type);
}
} // namespace event_type
} // namespace HEJ
diff --git a/src/Event.cc b/src/Event.cc
index fde91d0..35d38a0 100644
--- a/src/Event.cc
+++ b/src/Event.cc
@@ -1,1174 +1,1218 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/Event.hh"
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <iomanip>
#include <iterator>
#include <memory>
#include <numeric>
#include <ostream>
#include <string>
#include <utility>
#include "fastjet/ClusterSequence.hh"
#include "fastjet/JetDefinition.hh"
#include "fastjet/PseudoJet.hh"
#include "LHEF/LHEF.h"
#include "HEJ/Constants.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/RNG.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/optional.hh"
namespace HEJ {
namespace {
using std::size_t;
//! LHE status codes
namespace lhe_status {
enum Status: int {
in = -1,
decay = 2,
out = 1,
};
}
using LHE_Status = lhe_status::Status;
//! true if leptonic W decay
bool valid_W_decay( int const w_type, // sign of W
std::vector<Particle> const & decays
){
if(decays.size() != 2) // no 1->2 decay
return false;
const int pidsum = decays[0].type + decays[1].type;
if( std::abs(pidsum) != 1 || pidsum != w_type ) // correct charge
return false;
// leptonic decay (only check first, second follows from pidsum)
if( w_type == 1 ) // W+
return is_antilepton(decays[0]) || is_neutrino(decays[0]);
// W-
return is_lepton(decays[0]) || is_antineutrino(decays[0]);
}
//! true for Z decay to charged leptons
bool valid_Z_decay(std::vector<Particle> const & decays){
if(decays.size() != 2) // no 1->2 decay
return false;
const int pidsum = decays[0].type + decays[1].type;
if( std::abs(pidsum) != 0 ) // correct charge
return false;
// leptonic decay (only check first, second follows from pidsum)
return is_anylepton(decays[0]) && !is_anyneutrino(decays[0]);
}
/// @name helper functions to determine event type
//@{
/**
* \brief check if final state valid for HEJ
*
* check if there is at most one photon, W, H, Z in the final state
* and all the rest are quarks or gluons
*/
bool final_state_ok(Event const & ev){
std::vector<Particle> const & outgoing = ev.outgoing();
if(ev.decays().size() > 1) // at most one decay
return false;
bool has_AWZH_boson = false;
for( size_t i=0; i<outgoing.size(); ++i ){
auto const & out{ outgoing[i] };
if(is_AWZH_boson(out.type)){
// at most one boson
if(has_AWZH_boson) return false;
has_AWZH_boson = true;
// valid decay for W
if(std::abs(out.type) == ParticleID::Wp){
// exactly 1 decay of W
if( ev.decays().size() != 1 || ev.decays().cbegin()->first != i )
return false;
if( !valid_W_decay(out.type>0?+1:-1, ev.decays().cbegin()->second) )
return false;
}
// valid decay for Z
if(out.type == ParticleID::Z_photon_mix){
// exactly 1 decay
if( ev.decays().size() != 1 || ev.decays().cbegin()->first != i )
return false;
if( !valid_Z_decay(ev.decays().cbegin()->second) )
return false;
}
}
else if(! is_parton(out.type)) return false;
}
return true;
}
/**
* returns all EventTypes implemented in HEJ
*/
size_t implemented_types(std::vector<Particle> const & bosons){
using namespace event_type;
if(bosons.empty()) return FKL | unob | unof | qqbar_exb | qqbar_exf | qqbar_mid;
if(bosons.size()>1) return non_resummable; // multi boson
switch (bosons[0].type) {
case ParticleID::Wp:
case ParticleID::Wm:
return FKL | unob | unof | qqbar_exb | qqbar_exf | qqbar_mid;
case ParticleID::Z_photon_mix:
return FKL | unob | unof;
case ParticleID::h:
return FKL | unob | unof;
default:
return non_resummable;
}
}
/**
* \brief function which determines if type change is consistent with Wp emission.
* @param in incoming Particle id
* @param out outgoing Particle id
* @param is_qqbar Current both incoming/both outgoing?
*
* \see is_Wm_Change
*/
bool is_Wp_Change(ParticleID in, ParticleID out, bool is_qqbar){
using namespace pid;
if(!is_qqbar && (in==d_bar || in==u || in==s_bar || in==c))
return out == (in-1);
if( is_qqbar && (in==d || in==u_bar || in==s || in==c_bar))
return out == -(in+1);
return false;
}
/**
* \brief function which determines if type change is consistent with Wm emission.
* @param in incoming Particle id
* @param out outgoing Particle id
* @param is_qqbar Current both incoming/both outgoing?
*
* Ensures that change type of quark line is possible by a flavour changing
* Wm emission. Allows checking of is_qqbar currents also.
*/
bool is_Wm_Change(ParticleID in, ParticleID out, bool is_qqbar){
using namespace pid;
if(!is_qqbar && (in==d || in==u_bar || in==s || in==c_bar))
return out == (in+1);
if( is_qqbar && (in==d_bar || in==u || in==s_bar || in==c))
return out == -(in-1);
return false;
}
/**
* \brief checks if particle type remains same from incoming to outgoing
* @param in incoming Particle
* @param out outgoing Particle
* @param is_qqbar Current both incoming/outgoing?
*/
bool no_flavour_change(ParticleID in, ParticleID out, bool is_qqbar){
const int qqbarCurrent = is_qqbar?-1:1;
if(std::abs(in)<=pid::top || in==pid::gluon)
return (in==out*qqbarCurrent);
return false;
}
- bool has_2_jets(Event const & event){
- return event.jets().size() >= 2;
+ bool has_enough_jets(Event const & event){
+ if(event.jets().size() >= 2) return true;
+ if(event.jets().empty()) return false;
+ // check for h+jet
+ const auto the_higgs = std::find_if(
+ begin(event.outgoing()), end(event.outgoing()),
+ [](const auto & particle) { return particle.type == pid::higgs; }
+ );
+ return the_higgs != end(event.outgoing());
+ }
+
+ bool is_gluon_to_Higgs(const ParticleID in, const ParticleID out) {
+ return in == pid::gluon && out == pid::Higgs;
}
/**
* \brief check if we have a valid Impact factor
* @param in incoming Particle
* @param out outgoing Particle
* @param is_qqbar Current both incoming/outgoing?
* @param W_change returns +1 if Wp, -1 if Wm, else 0
*/
bool is_valid_impact_factor(
ParticleID in, ParticleID out, bool is_qqbar, int & W_change
){
- if( no_flavour_change(in, out, is_qqbar) ){
+ if( no_flavour_change(in, out, is_qqbar) || is_gluon_to_Higgs(in, out)) {
return true;
}
if( is_Wp_Change(in, out, is_qqbar) ) {
W_change+=1;
return true;
}
if( is_Wm_Change(in, out, is_qqbar) ) {
W_change-=1;
return true;
}
return false;
}
+ bool is_extremal_higgs_off_quark(
+ const ParticleID in,
+ const ParticleID extremal_out,
+ const ParticleID out
+ ) {
+ return in == out && extremal_out == pid::higgs && is_anyquark(in);
+ }
+
//! Returns all possible classifications from the impact factors
// the beginning points are changed s.t. after the the classification they
// point to the beginning of the (potential) FKL chain
// sets W_change: + if Wp change
// 0 if no change
// - if Wm change
// This function can be used with forward & backwards iterators
template<class OutIterator>
size_t possible_impact_factors(
ParticleID incoming_id, // incoming
OutIterator & begin_out, OutIterator const & end_out, // outgoing
int & W_change, std::vector<Particle> const & boson,
bool const backward // backward?
){
using namespace event_type;
assert(boson.size() < 2);
if(begin_out == end_out) return non_resummable;
// keep track of all states that we don't test
size_t not_tested = qqbar_mid;
if(backward)
not_tested |= unof | qqbar_exf;
else
not_tested |= unob | qqbar_exb;
// Is this LL current?
if( is_valid_impact_factor(incoming_id, begin_out->type, false, W_change) ){
++begin_out;
return not_tested | FKL;
}
+ // q -> H q and qbar -> H qbar are technically not LL,
+ // but we treat them as such anyway
+ if(is_extremal_higgs_off_quark(incoming_id, begin_out->type, std::next(begin_out)->type)) {
+ std::advance(begin_out, 2);
+ return not_tested | FKL;
+ }
// or NLL current?
// -> needs two partons in two different jets
if( std::distance(begin_out, end_out)>=2
){
auto next = std::next(begin_out);
// Is this unordered emisson?
if( incoming_id!=pid::gluon && begin_out->type==pid::gluon ){
if( is_valid_impact_factor(
incoming_id, next->type, false, W_change )
){
// veto Higgs inside uno
assert(next!=end_out);
if( !boson.empty() && boson.front().type == ParticleID::h
){
if( (backward && boson.front().rapidity() < next->rapidity())
||(!backward && boson.front().rapidity() > next->rapidity()))
return non_resummable;
}
begin_out = std::next(next);
return not_tested | (backward?unob:unof);
}
}
// Is this QQbar?
else if( incoming_id==pid::gluon ){
if( is_valid_impact_factor(
begin_out->type, next->type, true, W_change )
){
// veto Higgs inside qqbar
assert(next!=end_out);
if( !boson.empty() && boson.front().type == ParticleID::h
){
if( (backward && boson.front().rapidity() < next->rapidity())
||(!backward && boson.front().rapidity() > next->rapidity()))
return non_resummable;
}
begin_out = std::next(next);
return not_tested | (backward?qqbar_exb:qqbar_exf);
}
}
}
return non_resummable;
}
//! Returns all possible classifications from central emissions
// the beginning points are changed s.t. after the the classification they
// point to the end of the emission chain
// sets W_change: + if Wp change
// 0 if no change
// - if Wm change
template<class OutIterator>
size_t possible_central(
OutIterator & begin_out, OutIterator const & end_out,
int & W_change, std::vector<Particle> const & boson
){
using namespace event_type;
assert(boson.size() < 2);
// keep track of all states that we don't test
size_t possible = unob | unof
| qqbar_exb | qqbar_exf;
- // Find the first non-gluon/non-FKL
- while( (begin_out->type==pid::gluon) && (begin_out!=end_out) ){
- ++begin_out;
- }
+ // Find the first quark or antiquark emission
+ begin_out = std::find_if(
+ begin_out, end_out,
+ [](Particle const & p) { return is_anyquark(p); }
+ );
// end of chain -> FKL
if( begin_out==end_out ){
return possible | FKL;
}
// is this a qqbar-pair?
// needs two partons in two separate jets
auto next = std::next(begin_out);
if( is_valid_impact_factor(
begin_out->type, next->type, true, W_change )
){
// veto Higgs inside qqbar
if( !boson.empty() && boson.front().type == ParticleID::h
&& boson.front().rapidity() > begin_out->rapidity()
&& boson.front().rapidity() < next->rapidity()
){
return non_resummable;
}
begin_out = std::next(next);
- // remaining chain should be pure gluon/FKL
- for(; begin_out!=end_out; ++begin_out){
- if(begin_out->type != pid::gluon) return non_resummable;
+ // remaining chain should be pure FKL (gluon or higgs)
+ if(std::any_of(
+ begin_out, end_out,
+ [](Particle const & p) { return is_anyquark(p); }
+ )) {
+ return non_resummable;
}
return possible | qqbar_mid;
}
return non_resummable;
}
+ namespace {
+ bool is_parton_or_higgs(Particle const & p) {
+ return is_parton(p) || p.type == pid::higgs;
+ }
+ }
+
/**
* \brief Checks for all event types
* @param ev Event
* @returns Event Type
*
*/
event_type::EventType classify(Event const & ev){
using namespace event_type;
- if(! has_2_jets(ev))
- return no_2_jets;
+ if(! has_enough_jets(ev))
+ return not_enough_jets;
// currently we can't handle multiple boson states in the ME. So they are
// considered "bad_final_state" even though the "classify" could work with
// them.
if(! final_state_ok(ev))
return bad_final_state;
// initialise variables
auto const & in = ev.incoming();
// range for current checks
- auto begin_out{ev.cbegin_partons()};
- auto end_out{ev.crbegin_partons()};
+ auto begin_out = boost::make_filter_iterator(
+ is_parton_or_higgs, cbegin(ev.outgoing()), cend(ev.outgoing())
+ );
+ auto rbegin_out = std::make_reverse_iterator(
+ boost::make_filter_iterator(
+ is_parton_or_higgs, cend(ev.outgoing()), cend(ev.outgoing())
+ )
+ );
assert(std::distance(begin(in), end(in)) == 2);
- assert(std::distance(begin_out, end_out.base()) >= 2);
- assert(std::is_sorted(begin_out, end_out.base(), rapidity_less{}));
+ assert(std::distance(begin_out, rbegin_out.base()) >= 2);
+ assert(std::is_sorted(begin_out, rbegin_out.base(), rapidity_less{}));
auto const boson{ filter_AWZH_bosons(ev.outgoing()) };
// we only allow one boson through final_state_ok
assert(boson.size()<=1);
// keep track of potential W couplings, at the end the sum should be 0
int remaining_Wp = 0;
int remaining_Wm = 0;
if(!boson.empty() && std::abs(boson.front().type) == ParticleID::Wp ){
if(boson.front().type>0) ++remaining_Wp;
else ++remaining_Wm;
}
int W_change = 0;
- size_t final_type = ~(no_2_jets | bad_final_state);
+ size_t final_type = ~(not_enough_jets | bad_final_state);
// check forward impact factor
final_type &= possible_impact_factors(
in.front().type,
- begin_out, end_out.base(),
+ begin_out, rbegin_out.base(),
W_change, boson, true );
if( final_type == non_resummable )
return non_resummable;
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
W_change = 0;
// check backward impact factor
final_type &= possible_impact_factors(
in.back().type,
- end_out, std::make_reverse_iterator(begin_out),
+ rbegin_out, std::make_reverse_iterator(begin_out),
W_change, boson, false );
if( final_type == non_resummable )
return non_resummable;
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
W_change = 0;
// check central emissions
final_type &= possible_central(
- begin_out, end_out.base(), W_change, boson );
+ begin_out, rbegin_out.base(), W_change, boson );
if( final_type == non_resummable )
return non_resummable;
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
// Check whether the right number of Ws are present
if( remaining_Wp != 0 || remaining_Wm != 0 ) return non_resummable;
// result has to be unique
if( (final_type & (final_type-1)) != 0) return non_resummable;
// check that each sub processes is implemented
// (has to be done at the end)
if( (final_type & ~implemented_types(boson)) != 0 )
return non_resummable;
return static_cast<EventType>(final_type);
}
//@}
Particle extract_particle(LHEF::HEPEUP const & hepeup, size_t i){
auto id = static_cast<ParticleID>(hepeup.IDUP[i]);
auto colour = is_parton(id)?hepeup.ICOLUP[i]:optional<Colour>();
return { id,
{ hepeup.PUP[i][0], hepeup.PUP[i][1],
hepeup.PUP[i][2], hepeup.PUP[i][3] },
colour
};
}
bool is_decay_product(std::pair<int, int> const & mothers){
if(mothers.first == 0) return false;
return mothers.second == 0 || mothers.first == mothers.second;
}
} // namespace
Event::EventData::EventData(LHEF::HEPEUP const & hepeup){
parameters.central = EventParameters{
hepeup.scales.mur, hepeup.scales.muf, hepeup.XWGTUP
};
size_t in_idx = 0;
for (int i = 0; i < hepeup.NUP; ++i) {
// skip decay products
// we will add them later on, but we have to ensure that
// the decayed particle is added before
if(is_decay_product(hepeup.MOTHUP[i])) continue;
auto particle = extract_particle(hepeup, i);
// needed to identify mother particles for decay products
particle.p.set_user_index(i+1);
if(hepeup.ISTUP[i] == LHE_Status::in){
if(in_idx > incoming.size()) {
throw std::invalid_argument{
"Event has too many incoming particles"
};
}
incoming[in_idx++] = std::move(particle);
}
else outgoing.emplace_back(std::move(particle));
}
// add decay products
for (int i = 0; i < hepeup.NUP; ++i) {
if(!is_decay_product(hepeup.MOTHUP[i])) continue;
const int mother_id = hepeup.MOTHUP[i].first;
const auto mother = std::find_if(
begin(outgoing), end(outgoing),
[mother_id](Particle const & particle){
return particle.p.user_index() == mother_id;
}
);
if(mother == end(outgoing)){
throw std::invalid_argument{"invalid decay product parent"};
}
const int mother_idx = std::distance(begin(outgoing), mother);
assert(mother_idx >= 0);
decays[mother_idx].emplace_back(extract_particle(hepeup, i));
}
}
Event::Event(
UnclusteredEvent const & ev,
fastjet::JetDefinition const & jet_def, double const min_jet_pt
):
Event( Event::EventData{
ev.incoming, ev.outgoing, ev.decays,
Parameters<EventParameters>{ev.central, ev.variations}
}.cluster(jet_def, min_jet_pt) )
{}
//! @TODO remove in HEJ 2.2.0
UnclusteredEvent::UnclusteredEvent(LHEF::HEPEUP const & hepeup){
Event::EventData const evData{hepeup};
incoming = evData.incoming;
outgoing = evData.outgoing;
decays = evData.decays;
central = evData.parameters.central;
variations = evData.parameters.variations;
}
void Event::EventData::sort(){
// sort particles
std::sort(
begin(incoming), end(incoming),
[](Particle const & o1, Particle const & o2){return o1.p.pz()<o2.p.pz();}
);
auto old_outgoing = std::move(outgoing);
std::vector<size_t> idx(old_outgoing.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&old_outgoing](size_t i, size_t j){
return old_outgoing[i].rapidity() < old_outgoing[j].rapidity();
});
outgoing.clear();
outgoing.reserve(old_outgoing.size());
for(size_t i: idx) {
outgoing.emplace_back(std::move(old_outgoing[i]));
}
// find decays again
if(!decays.empty()){
auto old_decays = std::move(decays);
decays.clear();
for(size_t i=0; i<idx.size(); ++i) {
auto decay = old_decays.find(idx[i]);
if(decay != old_decays.end())
decays.emplace(i, std::move(decay->second));
}
assert(old_decays.size() == decays.size());
}
}
namespace {
Particle reconstruct_boson(std::vector<Particle> const & leptons) {
Particle decayed_boson;
decayed_boson.p = leptons[0].p + leptons[1].p;
const int pidsum = leptons[0].type + leptons[1].type;
if(pidsum == +1) {
assert(is_antilepton(leptons[0]));
if(is_antineutrino(leptons[0])) {
throw not_implemented{"lepton-flavour violating final state"};
}
assert(is_neutrino(leptons[1]));
// charged antilepton + neutrino means we had a W+
decayed_boson.type = pid::Wp;
}
else if(pidsum == -1) {
assert(is_antilepton(leptons[0]));
if(is_neutrino(leptons[1])) {
throw not_implemented{"lepton-flavour violating final state"};
}
assert(is_antineutrino(leptons[0]));
// charged lepton + antineutrino means we had a W-
decayed_boson.type = pid::Wm;
}
else if(pidsum == 0) {
assert(is_anylepton(leptons[0]));
if(is_anyneutrino(leptons[0])) {
throw not_implemented{"final state with two neutrinos"};
}
// charged lepton-antilepton pair means we had a Z/photon
decayed_boson.type = pid::Z_photon_mix;
}
else {
throw not_implemented{
"final state with leptons "
+ name(leptons[0].type)
+ " and "
+ name(leptons[1].type)
};
}
return decayed_boson;
}
} // namespace
void Event::EventData::reconstruct_intermediate() {
const auto begin_leptons = std::partition(
begin(outgoing), end(outgoing),
[](Particle const & p) {return !is_anylepton(p);}
);
// We can only reconstruct FS with 2 leptons
if(std::distance(begin_leptons, end(outgoing)) != 2) return;
std::vector<Particle> leptons(begin_leptons, end(outgoing));
std::sort(
begin(leptons), end(leptons),
[](Particle const & p0, Particle const & p1) {
assert(is_anylepton(p0) && is_anylepton(p1));
return p0.type < p1.type;
}
);
// `reconstruct_boson` can throw, it should therefore be called before
// changing `outgoing` to allow the user to recover the original EventData
auto boson = reconstruct_boson(leptons);
outgoing.erase(begin_leptons, end(outgoing));
outgoing.emplace_back(std::move(boson));
decays.emplace(outgoing.size()-1, std::move(leptons));
}
Event Event::EventData::cluster(
fastjet::JetDefinition const & jet_def, double const min_jet_pt
){
sort();
return Event{ std::move(incoming), std::move(outgoing), std::move(decays),
std::move(parameters),
jet_def, min_jet_pt
};
}
Event::Event(
std::array<Particle, 2> && incoming,
std::vector<Particle> && outgoing,
std::unordered_map<size_t, std::vector<Particle>> && decays,
Parameters<EventParameters> && parameters,
fastjet::JetDefinition const & jet_def,
double const min_jet_pt
): incoming_{std::move(incoming)},
outgoing_{std::move(outgoing)},
decays_{std::move(decays)},
parameters_{std::move(parameters)},
cs_{ to_PseudoJet( filter_partons(outgoing_) ), jet_def },
min_jet_pt_{min_jet_pt}
{
jets_ = sorted_by_rapidity(cs_.inclusive_jets(min_jet_pt_));
assert(std::is_sorted(begin(outgoing_), end(outgoing_),
rapidity_less{}));
type_ = classify(*this);
}
namespace {
//! check that Particles have a reasonable colour
bool correct_colour(Particle const & part){
ParticleID id{ part.type };
if(!is_parton(id))
return !part.colour;
if(!part.colour)
return false;
Colour const & col{ *part.colour };
if(is_quark(id))
return col.first != 0 && col.second == 0;
if(is_antiquark(id))
return col.first == 0 && col.second != 0;
assert(id==ParticleID::gluon);
return col.first != 0 && col.second != 0 && col.first != col.second;
}
//! Connect parton to t-channel colour line & update the line
//! returns false if connection not possible
template<class OutIterator>
bool try_connect_t(OutIterator const & it_part, Colour & line_colour){
if( line_colour.first == it_part->colour->second ){
line_colour.first = it_part->colour->first;
return true;
}
if( line_colour.second == it_part->colour->first ){
line_colour.second = it_part->colour->second;
return true;
}
return false;
}
//! Connect parton to u-channel colour line & update the line
//! returns false if connection not possible
template<class OutIterator>
bool try_connect_u(OutIterator & it_part, Colour & line_colour){
auto it_next = std::next(it_part);
if( try_connect_t(it_next, line_colour)
&& try_connect_t(it_part, line_colour)
){
it_part=it_next;
return true;
}
return false;
}
} // namespace
bool Event::is_leading_colour() const {
if( !correct_colour(incoming()[0]) || !correct_colour(incoming()[1]) )
return false;
Colour line_colour = *incoming()[0].colour;
std::swap(line_colour.first, line_colour.second);
// reasonable colour
if(!std::all_of(outgoing().cbegin(), outgoing().cend(), correct_colour))
return false;
for(auto it_part = cbegin_partons(); it_part!=cend_partons(); ++it_part){
switch (type()) {
case event_type::FKL:
if( !try_connect_t(it_part, line_colour) )
return false;
break;
case event_type::unob:
case event_type::qqbar_exb: {
if( !try_connect_t(it_part, line_colour)
// u-channel only allowed at impact factor
&& (std::distance(cbegin_partons(), it_part)!=0
|| !try_connect_u(it_part, line_colour)))
return false;
break;
}
case event_type::unof:
case event_type::qqbar_exf: {
if( !try_connect_t(it_part, line_colour)
// u-channel only allowed at impact factor
&& (std::distance(it_part, cend_partons())!=2
|| !try_connect_u(it_part, line_colour)))
return false;
break;
}
case event_type::qqbar_mid:{
auto it_next = std::next(it_part);
if( !try_connect_t(it_part, line_colour)
// u-channel only allowed at q-qbar/qbar-q pair
&& ( ( !(is_quark(*it_part) && is_antiquark(*it_next))
&& !(is_antiquark(*it_part) && is_quark(*it_next)))
|| !try_connect_u(it_part, line_colour))
)
return false;
break;
}
default:
throw std::logic_error{"unreachable"};
}
// no colour singlet exchange/disconnected diagram
if(line_colour.first == line_colour.second)
return false;
}
return (incoming()[1].colour->first == line_colour.first)
&& (incoming()[1].colour->second == line_colour.second);
}
namespace {
//! connect incoming Particle to colour flow
void connect_incoming(Particle & in, int & colour, int & anti_colour){
in.colour = std::make_pair(anti_colour, colour);
// gluon
if(in.type == pid::gluon)
return;
if(in.type > 0){
// quark
assert(is_quark(in));
in.colour->second = 0;
colour*=-1;
return;
}
// anti-quark
assert(is_antiquark(in));
in.colour->first = 0;
anti_colour*=-1;
}
//! connect outgoing Particle to t-channel colour flow
template<class OutIterator>
void connect_tchannel(
OutIterator & it_part, int & colour, int & anti_colour, RNG & ran
){
assert(colour>0 || anti_colour>0);
if(it_part->type == ParticleID::gluon){
// gluon
if(colour>0 && anti_colour>0){
// on g line => connect to colour OR anti-colour (random)
if(ran.flat() < 0.5){
it_part->colour = std::make_pair(colour+2,colour);
colour+=2;
} else {
it_part->colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(colour > 0){
// on q line => connect to available colour
it_part->colour = std::make_pair(colour+2, colour);
colour+=2;
} else {
assert(colour<0 && anti_colour>0);
// on qbar line => connect to available anti-colour
it_part->colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(is_quark(*it_part)) {
// quark
assert(anti_colour>0);
if(colour>0){
// on g line => connect and remove anti-colour
it_part->colour = std::make_pair(anti_colour, 0);
anti_colour+=2;
anti_colour*=-1;
} else {
// on qbar line => new colour
colour*=-1;
it_part->colour = std::make_pair(colour, 0);
}
} else if(is_antiquark(*it_part)) {
// anti-quark
assert(colour>0);
if(anti_colour>0){
// on g line => connect and remove colour
it_part->colour = std::make_pair(0, colour);
colour+=2;
colour*=-1;
} else {
// on q line => new anti-colour
anti_colour*=-1;
it_part->colour = std::make_pair(0, anti_colour);
}
} else { // not a parton
assert(!is_parton(*it_part));
it_part->colour = {};
}
}
//! connect to t- or u-channel colour flow
template<class OutIterator>
void connect_utchannel(
OutIterator & it_part, int & colour, int & anti_colour, RNG & ran
){
OutIterator it_first = it_part++;
if(ran.flat()<.5) {// t-channel
connect_tchannel(it_first, colour, anti_colour, ran);
connect_tchannel(it_part, colour, anti_colour, ran);
}
else { // u-channel
connect_tchannel(it_part, colour, anti_colour, ran);
connect_tchannel(it_first, colour, anti_colour, ran);
}
}
} // namespace
bool Event::generate_colours(RNG & ran){
// generate only for HEJ events
if(!event_type::is_resummable(type()))
return false;
assert(std::is_sorted(
begin(outgoing()), end(outgoing()), rapidity_less{}));
assert(incoming()[0].pz() < incoming()[1].pz());
// positive (anti-)colour -> can connect
// negative (anti-)colour -> not available/used up by (anti-)quark
int colour = COLOUR_OFFSET;
int anti_colour = colour+1;
// initialise first
connect_incoming(incoming_[0], colour, anti_colour);
// reset outgoing colours
std::for_each(outgoing_.begin(), outgoing_.end(),
[](Particle & part){ part.colour = {};});
for(auto it_part = begin_partons(); it_part!=end_partons(); ++it_part){
switch (type()) {
// subleading can connect to t- or u-channel
case event_type::unob:
case event_type::qqbar_exb: {
if( std::distance(begin_partons(), it_part)==0)
connect_utchannel(it_part, colour, anti_colour, ran);
else
connect_tchannel(it_part, colour, anti_colour, ran);
break;
}
case event_type::unof:
case event_type::qqbar_exf: {
if( std::distance(it_part, end_partons())==2)
connect_utchannel(it_part, colour, anti_colour, ran);
else
connect_tchannel(it_part, colour, anti_colour, ran);
break;
}
case event_type::qqbar_mid:{
auto it_next = std::next(it_part);
if( std::distance(begin_partons(), it_part)>0
&& std::distance(it_part, end_partons())>2
&& ( (is_quark(*it_part) && is_antiquark(*it_next))
|| (is_antiquark(*it_part) && is_quark(*it_next)) )
)
connect_utchannel(it_part, colour, anti_colour, ran);
else
connect_tchannel(it_part, colour, anti_colour, ran);
break;
}
default: // rest has to be t-channel
connect_tchannel(it_part, colour, anti_colour, ran);
}
}
// Connect last
connect_incoming(incoming_[1], anti_colour, colour);
assert(is_leading_colour());
return true;
} // generate_colours
namespace {
bool valid_parton(
std::vector<fastjet::PseudoJet> const & jets,
Particle const & parton, int const idx,
double const soft_pt_regulator, double const min_extparton_pt
){
// TODO code overlap with PhaseSpacePoint::pass_extremal_cuts
if(min_extparton_pt > parton.pt()) return false;
if(idx<0) return false;
assert(static_cast<int>(jets.size())>=idx);
auto const & jet{ jets[idx] };
return (parton.p - jet).pt()/jet.pt() <= soft_pt_regulator;
}
+
} // namespace
// this should work with multiple types
bool Event::valid_hej_state(double const soft_pt_regulator,
double const min_pt
) const {
using namespace event_type;
if(!is_resummable(type()))
return false;
auto const & jet_idx{ particle_jet_indices() };
auto idx_begin{ jet_idx.cbegin() };
auto idx_end{ jet_idx.crbegin() };
auto part_begin{ cbegin_partons() };
auto part_end{ crbegin_partons() };
// always seperate extremal jets
- if( !valid_parton(jets(), *part_begin, *idx_begin,
- soft_pt_regulator, min_pt) )
- return false;
- ++part_begin;
- ++idx_begin;
- if( !valid_parton(jets(), *part_end, *idx_end,
- soft_pt_regulator, min_pt) )
- return false;
- ++part_end;
- ++idx_end;
-
- // unob -> second parton in own jet
- if( type() & (unob | qqbar_exb) ){
- if( !valid_parton(jets(), *part_begin, *idx_begin,
- soft_pt_regulator, min_pt) )
+ if(!is_backward_g_to_h(*this)) {
+ if(! valid_parton(jets(), *part_begin, *idx_begin, soft_pt_regulator, min_pt)) {
return false;
+ }
++part_begin;
++idx_begin;
+ // unob -> second parton in own jet
+ if( type() & (unob | qqbar_exb) ){
+ if( !valid_parton(jets(), *part_begin, *idx_begin,
+ soft_pt_regulator, min_pt) )
+ return false;
+ ++part_begin;
+ ++idx_begin;
+ }
}
-
- if( type() & (unof | qqbar_exf) ){
- if( !valid_parton(jets(), *part_end, *idx_end,
- soft_pt_regulator, min_pt) )
+ if(!is_forward_g_to_h(*this)) {
+ if(!valid_parton(jets(), *part_end, *idx_end, soft_pt_regulator, min_pt)) {
return false;
+ }
++part_end;
- // ++idx_end; // last check, we don't need idx_end afterwards
+ ++idx_end;
+ if( type() & (unof | qqbar_exf) ){
+ if( !valid_parton(jets(), *part_end, *idx_end,
+ soft_pt_regulator, min_pt) )
+ return false;
+ ++part_end;
+ // ++idx_end; // last check, we don't need idx_end afterwards
+ }
}
if( type() & qqbar_mid ){
// find qqbar pair
auto begin_qqbar{ std::find_if( part_begin, part_end.base(),
[](Particle const & part) -> bool {
return part.type != ParticleID::gluon;
}
)};
assert(begin_qqbar != part_end.base());
long int qqbar_pos{ std::distance(part_begin, begin_qqbar) };
assert(qqbar_pos >= 0);
idx_begin+=qqbar_pos;
if( !( valid_parton(jets(), *begin_qqbar, *idx_begin,
soft_pt_regulator, min_pt)
&& valid_parton(jets(), *std::next(begin_qqbar), *std::next(idx_begin),
soft_pt_regulator, min_pt)
))
return false;
}
return true;
}
Event::ConstPartonIterator Event::begin_partons() const {
return cbegin_partons();
}
Event::ConstPartonIterator Event::cbegin_partons() const {
return {HEJ::is_parton, cbegin(outgoing()), cend(outgoing())};
}
Event::ConstPartonIterator Event::end_partons() const {
return cend_partons();
}
Event::ConstPartonIterator Event::cend_partons() const {
return {HEJ::is_parton, cend(outgoing()), cend(outgoing())};
}
Event::ConstReversePartonIterator Event::rbegin_partons() const {
return crbegin_partons();
}
Event::ConstReversePartonIterator Event::crbegin_partons() const {
return std::reverse_iterator<ConstPartonIterator>( cend_partons() );
}
Event::ConstReversePartonIterator Event::rend_partons() const {
return crend_partons();
}
Event::ConstReversePartonIterator Event::crend_partons() const {
return std::reverse_iterator<ConstPartonIterator>( cbegin_partons() );
}
Event::PartonIterator Event::begin_partons() {
return {HEJ::is_parton, begin(outgoing_), end(outgoing_)};
}
Event::PartonIterator Event::end_partons() {
return {HEJ::is_parton, end(outgoing_), end(outgoing_)};
}
Event::ReversePartonIterator Event::rbegin_partons() {
return std::reverse_iterator<PartonIterator>( end_partons() );
}
Event::ReversePartonIterator Event::rend_partons() {
return std::reverse_iterator<PartonIterator>( begin_partons() );
}
namespace {
void print_momentum(std::ostream & os, fastjet::PseudoJet const & part){
constexpr int prec = 6;
const std::streamsize orig_prec = os.precision();
os <<std::scientific<<std::setprecision(prec) << "["
<<std::setw(2*prec+1)<<std::right<< part.px() << ", "
<<std::setw(2*prec+1)<<std::right<< part.py() << ", "
<<std::setw(2*prec+1)<<std::right<< part.pz() << ", "
<<std::setw(2*prec+1)<<std::right<< part.E() << "]"<< std::fixed;
os.precision(orig_prec);
}
void print_colour(std::ostream & os, optional<Colour> const & col){
constexpr int width = 3;
if(!col)
os << "(no color)"; // American spelling for better alignment
else
os << "(" <<std::setw(width)<<std::right<< col->first
<< ", " <<std::setw(width)<<std::right<< col->second << ")";
}
} // namespace
std::ostream& operator<<(std::ostream & os, Event const & ev){
constexpr int prec = 4;
constexpr int wtype = 3; // width for types
const std::streamsize orig_prec = os.precision();
os <<std::setprecision(prec)<<std::fixed;
os << "########## " << name(ev.type()) << " ##########" << std::endl;
os << "Incoming particles:\n";
for(auto const & in: ev.incoming()){
os <<std::setw(wtype)<< in.type << ": ";
print_colour(os, in.colour);
os << " ";
print_momentum(os, in.p);
os << std::endl;
}
os << "\nOutgoing particles: " << ev.outgoing().size() << "\n";
for(auto const & out: ev.outgoing()){
os <<std::setw(wtype)<< out.type << ": ";
print_colour(os, out.colour);
os << " ";
print_momentum(os, out.p);
os << " => rapidity="
<<std::setw(2*prec-1)<<std::right<< out.rapidity() << std::endl;
}
os << "\nForming Jets: " << ev.jets().size() << "\n";
for(auto const & jet: ev.jets()){
print_momentum(os, jet);
os << " => rapidity="
<<std::setw(2*prec-1)<<std::right<< jet.rapidity() << std::endl;
}
if(!ev.decays().empty() ){
os << "\nDecays: " << ev.decays().size() << "\n";
for(auto const & decay: ev.decays()){
os <<std::setw(wtype)<< ev.outgoing()[decay.first].type
<< " (" << decay.first << ") to:\n";
for(auto const & out: decay.second){
os <<" "<<std::setw(wtype)<< out.type << ": ";
print_momentum(os, out.p);
os << " => rapidity="
<<std::setw(2*prec-1)<<std::right<< out.rapidity() << std::endl;
}
}
}
os << std::defaultfloat;
os.precision(orig_prec);
return os;
}
double shat(Event const & ev){
return (ev.incoming()[0].p + ev.incoming()[1].p).m2();
}
LHEF::HEPEUP to_HEPEUP(Event const & event, LHEF::HEPRUP * heprup){
LHEF::HEPEUP result;
result.heprup = heprup;
result.weights = {{event.central().weight, nullptr}};
for(auto const & var: event.variations()){
result.weights.emplace_back(var.weight, nullptr);
}
size_t num_particles = event.incoming().size() + event.outgoing().size();
for(auto const & decay: event.decays()) num_particles += decay.second.size();
result.NUP = num_particles;
// the following entries are pretty much meaningless
result.IDPRUP = event.type(); // event type
result.AQEDUP = 1./128.; // alpha_EW
//result.AQCDUP = 0.118 // alpha_QCD
// end meaningless part
result.XWGTUP = event.central().weight;
result.SCALUP = event.central().muf;
result.scales.muf = event.central().muf;
result.scales.mur = event.central().mur;
result.scales.SCALUP = event.central().muf;
result.pdfinfo.p1 = event.incoming().front().type;
result.pdfinfo.p2 = event.incoming().back().type;
result.pdfinfo.scale = event.central().muf;
result.IDUP.reserve(num_particles); // PID
result.ISTUP.reserve(num_particles); // status (in, out, decay)
result.PUP.reserve(num_particles); // momentum
result.MOTHUP.reserve(num_particles); // index mother particle
result.ICOLUP.reserve(num_particles); // colour
// incoming
std::array<Particle, 2> incoming{ event.incoming() };
// First incoming should be positive pz according to LHE standard
// (or at least most (everyone?) do it this way, and Pythia assumes it)
if(incoming[0].pz() < incoming[1].pz())
std::swap(incoming[0], incoming[1]);
for(Particle const & in: incoming){
result.IDUP.emplace_back(in.type);
result.ISTUP.emplace_back(LHE_Status::in);
result.PUP.push_back({in.p[0], in.p[1], in.p[2], in.p[3], in.p.m()});
result.MOTHUP.emplace_back(0, 0);
assert(in.colour);
result.ICOLUP.emplace_back(*in.colour);
}
// outgoing
for(size_t i = 0; i < event.outgoing().size(); ++i){
Particle const & out = event.outgoing()[i];
result.IDUP.emplace_back(out.type);
const int status = event.decays().count(i) != 0u
?LHE_Status::decay
:LHE_Status::out;
result.ISTUP.emplace_back(status);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
result.MOTHUP.emplace_back(1, 2);
if(out.colour)
result.ICOLUP.emplace_back(*out.colour);
else{
result.ICOLUP.emplace_back(std::make_pair(0,0));
}
}
// decays
for(auto const & decay: event.decays()){
for(auto const & out: decay.second){
result.IDUP.emplace_back(out.type);
result.ISTUP.emplace_back(LHE_Status::out);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
const size_t mother_idx = 1 + event.incoming().size() + decay.first;
result.MOTHUP.emplace_back(mother_idx, mother_idx);
result.ICOLUP.emplace_back(0,0);
}
}
assert(result.ICOLUP.size() == num_particles);
static constexpr double unknown_spin = 9.; //per Les Houches accord
result.VTIMUP = std::vector<double>(num_particles, unknown_spin);
result.SPINUP = result.VTIMUP;
return result;
}
} // namespace HEJ
diff --git a/src/Hjets.cc b/src/Hjets.cc
index c120121..5369b21 100644
--- a/src/Hjets.cc
+++ b/src/Hjets.cc
@@ -1,965 +1,537 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/jets.hh"
#include "HEJ/Hjets.hh"
#include <array>
#include <cassert>
#include <cmath>
#include <complex>
#include <limits>
#include "HEJ/ConfigFlags.hh"
#include "HEJ/Constants.hh"
#include "HEJ/LorentzVector.hh"
#include "HEJ/utility.hh"
// generated headers
#include "HEJ/currents/j_h_j.hh"
+#include "HEJ/currents/jgh_j.hh"
#include "HEJ/currents/juno_h_j.hh"
+#include "HEJ/currents/juno_jgh.hh"
#ifdef HEJ_BUILD_WITH_QCDLOOP
#include "qcdloop/qcdloop.h"
-#include "HEJ/currents/jh_j.hh"
-
#else
#include "HEJ/exceptions.hh"
#endif
namespace HEJ {
namespace currents {
namespace {
// short hand for math functions
using std::norm;
- using std::abs;
using std::conj;
- using std::pow;
- using std::sqrt;
constexpr double infinity = std::numeric_limits<double>::infinity(); // NOLINT
// Loop integrals
#ifdef HEJ_BUILD_WITH_QCDLOOP
- const COM LOOPRWFACTOR = (COM(0.,1.)*M_PI*M_PI)/pow((2.*M_PI),4);
+ const COM LOOPRWFACTOR = (COM(0.,1.)*M_PI*M_PI)/std::pow((2.*M_PI),4);
COM B0DD(HLV const & q, double mq)
{
static std::vector<std::complex<double>> result(3);
static auto ql_B0 = [](){
ql::Bubble<std::complex<double>,double,double> ql_B0;
ql_B0.setCacheSize(100);
return ql_B0;
}();
static std::vector<double> masses(2);
static std::vector<double> momenta(1);
for(auto & m: masses) m = mq*mq;
momenta.front() = q.m2();
ql_B0.integral(result, 1, masses, momenta);
return result[0];
}
COM C0DD(HLV const & q1, HLV const & q2, double mq)
{
static std::vector<std::complex<double>> result(3);
static auto ql_C0 = [](){
ql::Triangle<std::complex<double>,double,double> ql_C0;
ql_C0.setCacheSize(100);
return ql_C0;
}();
static std::vector<double> masses(3);
static std::vector<double> momenta(3);
for(auto & m: masses) m = mq*mq;
momenta[0] = q1.m2();
momenta[1] = q2.m2();
momenta[2] = (q1+q2).m2();
ql_C0.integral(result, 1, masses, momenta);
return result[0];
}
- COM D0DD(HLV const & q1, HLV const & q2, HLV const & q3, double mq)
- {
- static std::vector<std::complex<double>> result(3);
- static auto ql_D0 = [](){
- ql::Box<std::complex<double>,double,double> ql_D0;
- ql_D0.setCacheSize(100);
- return ql_D0;
- }();
- static std::vector<double> masses(4);
- static std::vector<double> momenta(6);
- for(auto & m: masses) m = mq*mq;
- momenta[0] = q1.m2();
- momenta[1] = q2.m2();
- momenta[2] = q3.m2();
- momenta[3] = (q1+q2+q3).m2();
- momenta[4] = (q1+q2).m2();
- momenta[5] = (q2+q3).m2();
- ql_D0.integral(result, 1, masses, momenta);
- return result[0];
- }
// Kallen lambda functions, see eq:lambda in developer manual
double lambda(const double s1, const double s2, const double s3) {
return s1*s1 + s2*s2 + s3*s3 - 2*s1*s2 - 2*s1*s3 - 2*s2*s3;
}
// eq: T_1 in developer manual
COM T1(HLV const & q1, HLV const & q2, const double m) {
const double q12 = q1.m2();
const double q22 = q2.m2();
const HLV ph = q1 - q2;
const double ph2 = ph.m2();
const double lam = lambda(q12, q22, ph2);
assert(m > 0.);
const double m2 = m*m;
return
- C0DD(q1, -q2, m)*(2.*m2 + 1./2.*(q12 + q22 - ph2) + 2.*q12*q22*ph2/lam)
- (B0DD(q2, m) - B0DD(ph, m))*(q22 - q12 - ph2)*q22/lam
- (B0DD(q1, m) - B0DD(ph, m))*(q12 - q22 - ph2)*q12/lam
- 1.;
}
// eq: T_2 in developer manual
COM T2(HLV const & q1, HLV const & q2, const double m) {
const double q12 = q1.m2();
const double q22 = q2.m2();
const HLV ph = q1 - q2;
const double ph2 = ph.m2();
const double lam = lambda(q12, q22, ph2);
assert(m > 0.);
const double m2 = m*m;
return
C0DD(q1, -q2, m)*(
4.*m2/lam*(ph2 - q12 - q22) - 1. - 4.*q12*q22/lam*(
1 + 3.*ph2*(q12 + q22 - ph2)/lam
)
)
- (B0DD(q2, m) - B0DD(ph, m))*(1. + 6.*q12/lam*(q22 - q12 + ph2))*2.*q22/lam
- (B0DD(q1, m) - B0DD(ph, m))*(1. + 6.*q22/lam*(q12 - q22 + ph2))*2.*q12/lam
- 2.*(q12 + q22 - ph2)/lam;
}
#else // no QCDloop
COM T1(HLV const & /*q1*/, HLV const & /*q2*/, double /*mt*/){
throw std::logic_error{"T1 called without QCDloop support"};
}
COM T2(HLV const & /*q1*/, HLV const & /*q2*/, double /*mt*/){
throw std::logic_error{"T2 called without QCDloop support"};
}
#endif
// prefactors of g^{\mu \nu} and q_2^\mu q_1^\nu in Higgs boson emission vertex
// see eq:VH in developer manual, but *without* global factor \alpha_s
std::array<COM, 2> TT(
HLV const & qH1, HLV const & qH2,
const double mt, const bool inc_bottom,
const double mb, const double vev
) {
if(mt == infinity) {
std::array<COM, 2> res = {qH1.dot(qH2), 1.};
for(auto & tt: res) tt /= (3.*M_PI*vev);
return res;
}
std::array<COM, 2> res = {T1(qH1, qH2, mt), T2(qH1, qH2, mt)};
for(auto & tt: res) tt *= mt*mt;
if(inc_bottom) {
res[0] += mb*mb*T1(qH1, qH2, mb);
res[1] += mb*mb*T2(qH1, qH2, mb);
}
for(auto & tt: res) tt /= M_PI*vev;
return res;
}
/**
* @brief Higgs+Jets FKL Contributions, function to handle all incoming types.
* @param p1out Outgoing Particle 1
* @param p1in Incoming Particle 1
* @param p2out Outgoing Particle 2
* @param p2in Incoming Particle 2
* @param qH1 t-channel momenta into higgs vertex
* @param qH2 t-channel momenta out of higgs vertex
* @param mt top mass (inf or value)
* @param inc_bottom whether to include bottom mass effects (true) or not (false)
* @param mb bottom mass (value)
* @param vev Higgs vacuum expectation value
*
* Calculates j^\mu H j_\mu. FKL with higgs vertex somewhere in the FKL chain.
* Handles all possible incoming states.
*/
double j_h_j(
HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
const double mt, const bool inc_bottom, const double mb, const double vev
){
using helicity::plus;
using helicity::minus;
const auto qqH1 = split_into_lightlike(qH1);
const HLV qH11 = qqH1.first;
const HLV qH12 = -qqH1.second;
const auto qqH2 = split_into_lightlike(qH2);
const HLV qH21 = qqH2.first;
const HLV qH22 = -qqH2.second;
// since qH1.m2(), qH2.m2() < 0 the following assertions are always true
assert(qH11.e() > 0);
assert(qH12.e() > 0);
assert(qH21.e() > 0);
assert(qH22.e() > 0);
const auto T_pref = TT(qH1, qH2, mt, inc_bottom, mb, vev);
const COM amp_mm = HEJ::j_h_j<minus, minus>(
p1out, p1in, p2out, p2in, qH11, qH12, qH21, qH22, T_pref[0], T_pref[1]
);
const COM amp_mp = HEJ::j_h_j<minus, plus>(
p1out, p1in, p2out, p2in, qH11, qH12, qH21, qH22, T_pref[0], T_pref[1]
);
const COM amp_pm = HEJ::j_h_j<plus, minus>(
p1out, p1in, p2out, p2in, qH11, qH12, qH21, qH22, T_pref[0], T_pref[1]
);
const COM amp_pp = HEJ::j_h_j<plus, plus>(
p1out, p1in, p2out, p2in, qH11, qH12, qH21, qH22, T_pref[0], T_pref[1]
);
static constexpr double num_hel = 4.;
// square of amplitudes, averaged over helicities
const double amp2 = (norm(amp_mm) + norm(amp_mp) + norm(amp_pm) + norm(amp_pp))/num_hel;
return amp2/((p1in-p1out).m2()*(p2in-p2out).m2()*qH1.m2()*qH2.m2());
}
// }
} // namespace
double ME_H_qQ(HLV const & p1out, HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1, HLV const & qH2, double mt,
bool include_bottom, double mb, double vev
){
return j_h_j(p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_qQbar(HLV const & p1out, HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1, HLV const & qH2,
double mt, bool include_bottom, double mb, double vev
){
return j_h_j(p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_qbarQ(HLV const & p1out, HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1, HLV const & qH2,
double mt, bool include_bottom, double mb, double vev
){
return j_h_j(p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_qbarQbar(HLV const & p1out, HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1, HLV const & qH2,
double mt, bool include_bottom, double mb, double vev
){
return j_h_j(p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_qg(HLV const & p1out, HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1, HLV const & qH2,
double mt, bool include_bottom, double mb, double vev
){
return j_h_j(p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev)
* K_g(p2out,p2in)/C_A;
}
double ME_H_qbarg(HLV const & p1out, HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1, HLV const & qH2,
double mt, bool include_bottom, double mb, double vev
){
return j_h_j(p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev)
* K_g(p2out,p2in)/C_A;
}
double ME_H_gg(HLV const & p1out, HLV const & p1in, HLV const & p2out,
HLV const & p2in, HLV const & qH1, HLV const & qH2,
double mt, bool include_bottom, double mb, double vev
){
return j_h_j(p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev)
* K_g(p2out,p2in)/C_A * K_g(p1out,p1in)/C_A;
}
//@}
+
+ double ME_jgH_j(
+ HLV const & ph, HLV const & pa,
+ HLV const & pn, HLV const & pb,
+ const double mt, const bool inc_bottom, const double mb, const double vev
+ ){
+ using helicity::plus;
+ using helicity::minus;
+
+ const auto pH = split_into_lightlike(ph);
+ const HLV ph1 = pH.first;
+ const HLV ph2 = pH.second;
+ // since pH.m2() > 0 the following assertions are always true
+ assert(ph1.e() > 0);
+ assert(ph2.e() > 0);
+
+ const auto T_pref = TT(pa, pa-ph, mt, inc_bottom, mb, vev);
+
+ // only distinguish between same and different helicities,
+ // the other two combinations just add a factor of 2
+ const COM amp_mm = HEJ::jgh_j<minus, minus>(
+ pa, pb, pn, ph1, ph2, T_pref[0], T_pref[1]
+ );
+ const COM amp_mp = HEJ::jgh_j<minus, plus>(
+ pa, pb, pn, ph1, ph2, T_pref[0], T_pref[1]
+ );
+ constexpr double hel_factor = 2.;
+
+ // sum over squares of helicity amplitudes
+ return hel_factor*(norm(amp_mm) + norm(amp_mp));
+ }
+
+ namespace {
+
+ template<Helicity h1, Helicity h2, Helicity hg>
+ double amp_juno_jgh(
+ HLV const & pg, HLV const & p1, HLV const & pa,
+ HLV const & ph1, HLV const & ph2, HLV const & pb,
+ std::array<COM, 2> const & T_pref
+ ) {
+ // TODO: code duplication with Wjets and pure jets
+ const COM u1 = U1_jgh<h1, h2, hg>(pg, p1, pa, ph1, ph2, pb, T_pref[0], T_pref[1]);
+ const COM u2 = U2_jgh<h1, h2, hg>(pg, p1, pa, ph1, ph2, pb, T_pref[0], T_pref[1]);
+ const COM l = L_jgh<h1, h2, hg>(pg, p1, pa, ph1, ph2, pb, T_pref[0], T_pref[1]);
+ return C_F*std::norm(u1+u2) - C_A*std::real((u1-l)*std::conj(u2+l));
+ }
+
+ } // namespace
+
+ double ME_juno_jgH(
+ HLV const & pg,
+ HLV const & p1, HLV const & pa,
+ HLV const & ph, HLV const & pb,
+ const double mt, const bool inc_bottom, const double mb, const double vev
+ ) {
+ using Helicity::plus;
+ using Helicity::minus;
+
+ const auto T_pref = TT(pb, pb-ph, mt, inc_bottom, mb, vev);
+
+ const auto pH = split_into_lightlike(ph);
+ const HLV ph1 = pH.first;
+ const HLV ph2 = pH.second;
+ // since pH.m2() > 0 the following assertions are always true
+ assert(ph1.e() > 0);
+ assert(ph2.e() > 0);
+
+ // only 4 out of the 8 helicity amplitudes are independent
+ // we still compute all of them for better numerical stability (mirror check)
+ MultiArray<double, 2, 2, 2> amp;
+
+// NOLINTNEXTLINE
+#define ASSIGN_HEL(RES, J, H1, H2, HG) \
+ RES[H1][H2][HG] = J<H1, H2, HG>( \
+ pg, p1, pa, ph1, ph2, pb, T_pref \
+ )
+
+ ASSIGN_HEL(amp, amp_juno_jgh, minus, minus, minus);
+ ASSIGN_HEL(amp, amp_juno_jgh, minus, minus, plus);
+ ASSIGN_HEL(amp, amp_juno_jgh, minus, plus, minus);
+ ASSIGN_HEL(amp, amp_juno_jgh, minus, plus, plus);
+ ASSIGN_HEL(amp, amp_juno_jgh, plus, minus, minus);
+ ASSIGN_HEL(amp, amp_juno_jgh, plus, minus, plus);
+ ASSIGN_HEL(amp, amp_juno_jgh, plus, plus, minus);
+ ASSIGN_HEL(amp, amp_juno_jgh, plus, plus, plus);
+
+#undef ASSIGN_HEL
+
+ double ampsq = 0.;
+ for(Helicity h1: {minus, plus}) {
+ for(Helicity h2: {minus, plus}) {
+ for(Helicity hg: {minus, plus}) {
+ ampsq += amp[h1][h2][hg];
+ }
+ }
+ }
+
+ return ampsq;
+ }
+
+
namespace {
template<Helicity h1, Helicity h2, Helicity hg>
double amp_juno_h_j(
HLV const & pa, HLV const & pb,
HLV const & pg, HLV const & p1, HLV const & p2,
HLV const & qH11, HLV const & qH12, HLV const & qH21, HLV const & qH22,
std::array<COM, 2> const & T_pref
) {
// TODO: code duplication with Wjets and pure jets
const COM u1 = U1_h_j<h1, h2, hg>(pa,p1,pb,p2,pg,qH11,qH12,qH21,qH22,T_pref[0],T_pref[1]);
const COM u2 = U2_h_j<h1, h2, hg>(pa,p1,pb,p2,pg,qH11,qH12,qH21,qH22,T_pref[0],T_pref[1]);
const COM l = L_h_j<h1, h2, hg>(pa,p1,pb,p2,pg,qH11,qH12,qH21,qH22,T_pref[0],T_pref[1]);
return 2.*C_F*std::real((l-u1)*std::conj(l+u2))
+ 2.*C_F*C_F/3.*std::norm(u1+u2)
;
}
//@{
/**
* @brief Higgs+Jets Unordered Contributions, function to handle all incoming types.
* @param pg Unordered Gluon momenta
* @param p1out Outgoing Particle 1
* @param p1in Incoming Particle 1
* @param p2out Outgoing Particle 2
* @param p2in Incoming Particle 2
* @param qH1 t-channel momenta into higgs vertex
* @param qH2 t-channel momenta out of higgs vertex
* @param mt top mass (inf or value)
* @param inc_bottom whether to include bottom mass effects (true) or not (false)
* @param mb bottom mass (value)
*
* Calculates j_{uno}^\mu H j_\mu. Unordered with higgs vertex
* somewhere in the FKL chain. Handles all possible incoming states.
*/
double juno_h_j(
HLV const & pg, HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in,
HLV const & qH1, HLV const & qH2,
const double mt, const bool incBot, const double mb, const double vev
){
using helicity::plus;
using helicity::minus;
const auto qqH1 = split_into_lightlike(qH1);
const HLV qH11 = qqH1.first;
const HLV qH12 = -qqH1.second;
const auto qqH2 = split_into_lightlike(qH2);
const HLV qH21 = qqH2.first;
const HLV qH22 = -qqH2.second;
// since qH1.m2(), qH2.m2() < 0 the following assertions are always true
assert(qH11.e() > 0);
assert(qH12.e() > 0);
assert(qH21.e() > 0);
assert(qH22.e() > 0);
const auto T_pref = TT(qH1, qH2, mt, incBot, mb, vev);
// only 4 out of the 8 helicity amplitudes are independent
// we still compute all of them for better numerical stability (mirror check)
MultiArray<double, 2, 2, 2> amp{};
// NOLINTNEXTLINE
#define ASSIGN_HEL(RES, J, H1, H2, HG) \
RES[H1][H2][HG] = J<H1, H2, HG>( \
p1in, p2in, pg, p1out, p2out, qH11, qH12, qH21, qH22, T_pref \
)
ASSIGN_HEL(amp, amp_juno_h_j, minus, minus, minus);
ASSIGN_HEL(amp, amp_juno_h_j, minus, minus, plus);
ASSIGN_HEL(amp, amp_juno_h_j, minus, plus, minus);
ASSIGN_HEL(amp, amp_juno_h_j, minus, plus, plus);
ASSIGN_HEL(amp, amp_juno_h_j, plus, minus, minus);
ASSIGN_HEL(amp, amp_juno_h_j, plus, minus, plus);
ASSIGN_HEL(amp, amp_juno_h_j, plus, plus, minus);
ASSIGN_HEL(amp, amp_juno_h_j, plus, plus, plus);
#undef ASSIGN_HEL
const HLV q1 = p1in-p1out; // Top End
const HLV q2 = p2out-p2in; // Bottom End
const HLV qg = p1in-p1out-pg; // Extra bit post-gluon
double ampsq = 0.;
for(Helicity h1: {minus, plus}) {
for(Helicity h2: {minus, plus}) {
for(Helicity hg: {minus, plus}) {
ampsq += amp[h1][h2][hg];
}
}
}
ampsq /= 16.*qg.m2()*qH1.m2()*qH2.m2()*q2.m2();
// Factor of (Cf/Ca) for each quark to match ME_H_qQ.
ampsq*=C_F*C_F/C_A/C_A;
return ampsq;
}
} // namespace
double ME_H_unob_qQ(HLV const & pg, HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in, HLV const & qH1,
HLV const & qH2, double mt, bool include_bottom, double mb,
double vev
){
return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_unob_qbarQ(HLV const & pg, HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in, HLV const & qH1,
HLV const & qH2, double mt, bool include_bottom, double mb,
double vev
){
return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_unob_qQbar(HLV const & pg, HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in, HLV const & qH1,
HLV const & qH2, double mt, bool include_bottom, double mb,
double vev
){
return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_unob_qbarQbar(HLV const & pg, HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in, HLV const & qH1,
HLV const & qH2, double mt, bool include_bottom, double mb,
double vev
){
return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev);
}
double ME_H_unob_gQ(HLV const & pg, HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in, HLV const & qH1,
HLV const & qH2, double mt, bool include_bottom, double mb,
double vev
){
return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev)
*K_g(p2out,p2in)/C_F;
}
double ME_H_unob_gQbar(HLV const & pg, HLV const & p1out, HLV const & p1in,
HLV const & p2out, HLV const & p2in, HLV const & qH1,
HLV const & qH2, double mt, bool include_bottom, double mb,
double vev
){
return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, include_bottom, mb, vev)
*K_g(p2out,p2in)/C_F;
}
//@}
-
-// Begin finite mass stuff
-#ifdef HEJ_BUILD_WITH_QCDLOOP
-namespace {
-
- // All the stuff needed for the box functions in qg->qgH now...
- COM E1(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2=-(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
- double const Sigma = 4.*s12*s34 - pow(S1+S2,2);
-
- return LOOPRWFACTOR*(-s12*D0DD(k2, k1, q2, mq)*(1 - 8.*mq*mq/s12 + S2/(2.*s12) +
- S2*(s12 - 8.*mq*mq)*(s34 + S1)/(2.*s12*Delta) +
- 2.*(s34 + S1)*(s34 + S1)/Delta +
- S2*pow((s34 + S1),3)/Delta/Delta) - ((s12 + S2)*C0DD(k2,
- k1 + q2, mq) -
- s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
- S1*C0DD(k1, q2,
- mq))*(S2*(s12 - 4.*mq*mq)/(2.*s12*Delta) +
- 2.*(s34 + S1)/Delta +
- S2*pow((s34 + S1),2)/Delta/Delta) + (C0DD(k1, q2, mq) -
- C0DD(k1 + k2, q2, mq))*(1. - 4.*mq*mq/s12) -
- C0DD(k1 + k2, q2, mq)*2.*s34/
- S1 - (B0DD(k1 + q2, mq) -
- B0DD(k1 + k2 + q2, mq))*2.*s34*(s34 +
- S1)/(S1*Delta) + (B0DD(q2, mq) -
- B0DD(k1 + k2 + q2, mq) +
- s12*C0DD(k1 + k2, q2,
- mq))*(2.*s34*(s34 +
- S1)*(S1 - S2)/(Delta*Sigma) +
- 2.*s34*(s34 + S1)/(S1*Delta)) + (B0DD(k1 + k2, mq) -
- B0DD(k1 + k2 + q2,
- mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*2.*(s34 +
- S1)*(2.*s12*s34 -
- S2*(S1 + S2))/(Delta*Sigma));
- }
-
- COM F1(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
- double const Sigma = 4.*s12*s34 - pow(S1+S2,2);
-
- return LOOPRWFACTOR*(-S2*D0DD(k1, k2, q2,
- mq)*(0.5 - (s12 - 8.*mq*mq)*(s34 + S2)/(2.*Delta) -
- s12*pow((s34 + S2),3)/Delta/Delta) + ((s12 + S1)*C0DD(k1,
- k2 + q2, mq) -
- s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
- S2*C0DD(k2, q2,
- mq))*(S2*(s12 - 4.*mq*mq)/(2.*s12*Delta) +
- S2*pow((s34 + S2),2)/Delta/Delta)
- - (C0DD(k1 + k2, q2, mq) - C0DD(k1, k2 + q2, mq))*(1. - 4.*mq*mq/s12)
- - C0DD(k1, k2 + q2, mq) + (B0DD(k2 + q2, mq) -
- B0DD(k1 + k2 + q2,
- mq))*2.*pow((s34 + S2),2)/((s12 + S1)*Delta) - (B0DD(
- q2, mq) - B0DD(k1 + k2 + q2, mq) +
- s12*C0DD(k1 + k2, q2, mq))*2.*s34*(s34 +
- S2)*(S2 - S1)/(Delta*Sigma) + (B0DD(
- k1 + k2, mq) -
- B0DD(k1 + k2 + q2,
- mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*2.*(s34 +
- S2)*(2.*s12*s34 -
- S2*(S1 + S2))/(Delta*Sigma));
- }
-
- COM G1(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
-
- return LOOPRWFACTOR*(S2*D0DD(k1, q2, k2,
- mq)*(Delta/s12/s12 - 4.*mq*mq/s12) -
- S2*((s12 + S1)*C0DD(k1, k2 + q2, mq) -
- S1*C0DD(k1, q2, mq))*(1./
- s12/s12 - (s12 - 4.*mq*mq)/(2.*s12*Delta)) -
- S2*((s12 + S2)*C0DD(k1 + q2, k2, mq) -
- S2*C0DD(k2, q2, mq))*(1./
- s12/s12 + (s12 - 4.*mq*mq)/(2.*s12*Delta)) -
- C0DD(k1, q2, mq) - (C0DD(k1, k2 + q2, mq) -
- C0DD(k1, q2, mq))*4.*mq*mq/
- s12 + (B0DD(k1 + q2, mq) - B0DD(k1 + k2 + q2, mq))*2./
- s12 + (B0DD(k1 + q2, mq) -
- B0DD(q2, mq))*2.*s34/(s12*S1) + (B0DD(k2 + q2, mq) -
- B0DD(k1 + k2 + q2, mq))*2.*(s34 + S2)/(s12*(s12 + S1)));
- }
-
- COM E4(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
- double const Sigma = 4.*s12*s34 - pow(S1+S2,2);
-
- return LOOPRWFACTOR* (-s12*D0DD(k2, k1, q2,
- mq)*(0.5 - (S1 - 8.*mq*mq)*(s34 + S1)/(2.*Delta) -
- s12*pow((s34 + S1),3)/Delta/Delta) + ((s12 + S2)*C0DD(k2,
- k1 + q2, mq) -
- s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
- S1*C0DD(k1, q2, mq))*((S1 - 4.*mq*mq)/(2.*Delta) +
- s12*pow((s34 + S1),2)/Delta/Delta) -
- C0DD(k1 + k2, q2, mq) + (B0DD(k1 + q2, mq) -
- B0DD(k1 + k2 + q2, mq))*(2.*s34/Delta +
- 2.*s12*(s34 + S1)/((s12 + S2)*Delta)) - (B0DD(
- q2, mq) - B0DD(k1 + k2 + q2, mq) +
- s12*C0DD(k1 + k2, q2,
- mq))*((2.*s34*(2.*s12*s34 - S2*(S1 + S2) +
- s12*(S1 - S2)))/(Delta*Sigma)) + (B0DD(k1 + k2, mq) -
- B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))
- *((2.*s12*(2.*s12*s34 - S1*(S1 + S2) + s34*(S2 - S1)))/(Delta*Sigma)));
- }
-
- COM F4(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
- double const Sigma = 4.*s12*s34 - pow(S1+S2,2);
-
- return LOOPRWFACTOR* (-s12*D0DD(k1, k2, q2,
- mq)*(0.5 + (S1 - 8.*mq*mq)*(s34 + S2)/(2.*Delta) +
- s12*pow((s34 + S2),3)/Delta/Delta) - ((s12 + S1)*C0DD(k1,
- k2 + q2, mq) -
- s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
- S2*C0DD(k2, q2, mq))*((S1 - 4.*mq*mq)/(2.*Delta) +
- s12*pow((s34 + S2),2)/Delta/Delta) -
- C0DD(k1 + k2, q2, mq) - (B0DD(k2 + q2, mq) -
- B0DD(k1 + k2 + q2, mq))*2.*(s34 +
- S2)/Delta + (B0DD(q2, mq) -
- B0DD(k1 + k2 + q2, mq) +
- s12*C0DD(k1 + k2, q2, mq))*2.*s34*(2.*s12*s34 -
- S1*(S1 + S2) +
- s12*(S2 - S1))/(Delta*Sigma) - (B0DD(k1 + k2, mq) -
- B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))
- *(2.*s12*(2.*s12*s34 - S2*(S1 + S2) + s34*(S1 - S2))/(Delta*Sigma)));
- }
-
- COM G4(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
-
- return LOOPRWFACTOR* (-D0DD(k1, q2, k2,
- mq)*(Delta/s12 + (s12 + S1)/2. -
- 4.*mq*mq) + ((s12 + S1)*C0DD(k1, k2 + q2, mq) -
- S1*C0DD(k1, q2, mq))*(1./
- s12 - (S1 - 4.*mq*mq)/(2.*Delta)) + ((s12 + S2)*C0DD(
- k1 + q2, k2, mq) -
- S2*C0DD(k2, q2, mq))*(1./
- s12 + (S1 - 4.*mq*mq)/(2.*Delta)) + (B0DD(
- k1 + k2 + q2, mq) -
- B0DD(k1 + q2, mq))*2./(s12 + S2));
- }
-
- COM E10(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
- double const Sigma = 4.*s12*s34 - pow(S1+S2,2);
-
- return LOOPRWFACTOR*(-s12*D0DD(k2, k1, q2, mq)*((s34 + S1)/Delta +
- 12.*mq*mq*S1*(s34 + S1)/Delta/Delta -
- 4.*s12*S1*pow((s34 + S1),3)/Delta/Delta/Delta) - ((s12 + S2)*C0DD(k2, k1 + q2, mq) -
- s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
- S1*C0DD(k1, q2, mq))*(1./Delta +
- 4.*mq*mq*S1/Delta/Delta -
- 4.*s12*S1*pow((s34 + S1),2)/Delta/Delta/Delta) +
- C0DD(k1 + k2, q2, mq)*(4.*s12*s34*(S1 - S2)/(Delta*Sigma) -
- 4.*(s12 -
- 2.*mq*mq)*(2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma)) + (B0DD(k1 + q2, mq) -
- B0DD(k1 + k2 + q2, mq))*(4.*(s34 + S1)/((s12 + S2)*Delta) +
- 8.*S1*(s34 + S1)/Delta/Delta) + (B0DD(q2, mq) -
- B0DD(k1 + k2 + q2, mq) +
- s12*C0DD(k1 + k2, q2, mq))*(12.*s34*(2.*s12 + S1 +
- S2)*(2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma*Sigma) -
- 4.*s34*(4.*s12 + 3.*S1 +
- S2)/(Delta*Sigma) +
- 8.*s12*s34*(s34*(s12 + S2) -
- S1*(s34 +
- S1))/(Delta*Delta*Sigma)) + (B0DD(k1 + k2, mq) -
- B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2,
- mq))*(12.*s12*(2.*s34 + S1 +
- S2)*(2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma*Sigma) +
- 8.*s12*S1*(s34*(s12 + S2) -
- S1*(s34 +
- S1))/(Delta*Delta*Sigma))) + (COM(0.,1.)/(4.*M_PI*M_PI))*((2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma));
- }
-
- COM F10(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
- double const Sigma = 4.*s12*s34 - pow(S1+S2,2);
-
- return LOOPRWFACTOR* (s12*D0DD(k1, k2, q2,
- mq)*((s34 + S2)/Delta - 4.*mq*mq/Delta +
- 12.*mq*mq*s34*(s12 + S1)/Delta/Delta -
- 4.*s12*pow((s34 + S2),2)/Delta/Delta -
- 4.*s12*S1*pow((s34 + S2),3)/Delta/Delta/Delta) + ((s12 + S1)*C0DD(k1, k2 + q2, mq) -
- s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
- S2*C0DD(k2, q2, mq))*(1./Delta +
- 4.*mq*mq*S1/Delta/Delta -
- 4.*s12*(s34 + S2)/Delta/Delta -
- 4.*s12*S1*pow((s34 + S2),2)/Delta/Delta/Delta) -
- C0DD(k1 + k2, q2, mq)*(4.*s12*s34/(S2*Delta) +
- 4.*s12*s34*(S2 - S1)/(Delta*Sigma) +
- 4.*(s12 -
- 2.*mq*mq)*(2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma)) - (B0DD(
- k2 + q2, mq) -
- B0DD(k1 + k2 + q2, mq))*(4.*s34/(S2*Delta) +
- 8.*s34*(s12 + S1)/Delta/Delta) - (B0DD(q2, mq) -
- B0DD(k1 + k2 + q2, mq) +
- s12*C0DD(k1 + k2, q2,
- mq))*(-12*s34*(2*s12 + S1 +
- S2)*(2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma*Sigma) -
- 4.*s12*s34*s34/(S2*Delta*Delta) +
- 4.*s34*S1/(Delta*Sigma) -
- 4.*s34*(s12*s34*(2.*s12 + S2) -
- S1*S1*(2.*s12 +
- S1))/(Delta*Delta*Sigma)) - (B0DD(k1 + k2, mq) -
- B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*(-12.*s12*(2.*s34 + S1 +
- S2)*(2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma*Sigma) +
- 8.*s12*(2.*s34 + S1)/(Delta*Sigma) -
- 8.*s12*s34*(2.*s12*s34 - S1*(S1 + S2) +
- s12*(S2 -
- S1))/(Delta*Delta*Sigma))) + (COM(0.,1.)/(4.*M_PI*M_PI))*((2.*s12*s34 -
- S1*(S1 + S2))/(Delta*Sigma));
-
- }
-
- COM G10(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- HLV const q2 = -(k1+k2+kh);
- double const S1 = 2.*k1.dot(q2);
- double const S2 = 2.*k2.dot(q2);
- double const s12 = 2.*k1.dot(k2);
- double const s34 = q2.m2();
- double const Delta = s12*s34 - S1*S2;
-
- return LOOPRWFACTOR* (-D0DD(k1, q2, k2, mq)*(1. +
- 4.*S1*mq*mq/Delta) + ((s12 + S1)*C0DD(k1,
- k2 + q2, mq) -
- S1*C0DD(k1, q2, mq))*(1./Delta +
- 4.*S1*mq*mq/Delta/Delta) - ((s12 + S2)*C0DD(k1 + q2,
- k2, mq) - S2*C0DD(k2, q2, mq))*(1./Delta +
- 4.*S1*mq*mq/Delta/Delta) + (B0DD(k1 + k2 + q2, mq) -
- B0DD(k1 + q2, mq))*4.*(s34 +
- S1)/(Delta*(s12 + S2)) + (B0DD(q2, mq) -
- B0DD(k2 + q2, mq))*4.*s34/(Delta*S2));
- }
-
- COM H1DD(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- return E1(k1,k2,kh,mq)+F1(k1,k2,kh,mq)+G1(k1,k2,kh,mq);
- }
-
- COM H4DD(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- return E4(k1,k2,kh,mq)+F4(k1,k2,kh,mq)+G4(k1,k2,kh,mq);
- }
-
- COM H10DD(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- return E10(k1,k2,kh,mq)+F10(k1,k2,kh,mq)+G10(k1,k2,kh,mq);
- }
-
- COM H2DD(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- return -1.*H1DD(k2,k1,kh,mq);
- }
-
- COM H5DD(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- return -1.*H4DD(k2,k1,kh,mq);
- }
-
- COM H12DD(HLV const & k1, HLV const & k2, HLV const & kh, double mq){
- return -1.*H10DD(k2,k1,kh,mq);
- }
-
- HLV parity_flip(HLV const & p){
- HLV flippedVector;
- flippedVector.setE(p.e());
- flippedVector.setX(-p.x());
- flippedVector.setY(-p.y());
- flippedVector.setZ(-p.z());
- return flippedVector;
- }
-
- template<Helicity hout, Helicity h2>
- COM jh_j(
- HLV const & pa,
- HLV const & p1,
- HLV const & pb,
- HLV const & p2,
- HLV const & ph1,
- HLV const & ph2,
- double const mq
- ) {
- return (pa.z() > 0)?
- jh_j_forward<hout, h2>(pa, p1, pb, p2, ph1, ph2, mq):
- jh_j_backward<hout, h2>(pa, p1, pb, p2, ph1, ph2, mq)
- ;
- }
-
- template<Helicity hout, Helicity h2>
- COM amp_jh_j(
- HLV const & pa,
- HLV const & p1,
- HLV const & pb,
- HLV const & p2,
- HLV const & ph1,
- HLV const & ph2,
- double const mq,
- bool const include_bottom,
- double const mq2,
- double const vev
- ) {
- COM res = 4.*mq*mq/vev*jh_j<hout, h2>(pa, p1, pb, p2, ph1, ph2, mq);
- if(include_bottom) {
- res += 4.*mq2*mq2/vev*jh_j<hout, h2>(pa, p1, pb, p2, ph1, ph2, mq2);
- }
- return res;
- }
-
- // sum over jh_j helicity amplitudes squared with + incoming gluon
- double ampsq_sum_jh_j(
- HLV const & pa,
- HLV const & p1,
- HLV const & pb,
- HLV const & p2,
- HLV const & ph1,
- HLV const & ph2,
- double const mq,
- bool const include_bottom,
- double const mq2,
- double const vev
- ) {
- using helicity::plus;
- using helicity::minus;
- using std::norm;
-
- const COM appp = amp_jh_j<plus, plus>(
- pa, p1, pb, p2, ph1, ph2,
- mq, include_bottom, mq2, vev
- );
- const COM appm = amp_jh_j<plus, minus>(
- pa, p1, pb, p2, ph1, ph2,
- mq, include_bottom, mq2, vev
- );
- const COM apmp = amp_jh_j<minus, plus>(
- pa, p1, pb, p2, ph1, ph2,
- mq, include_bottom, mq2, vev
- );
- const COM apmm = amp_jh_j<minus, minus>(
- pa, p1, pb, p2, ph1, ph2,
- mq, include_bottom, mq2, vev
- );
-
- return norm(appp) + norm(appm) + norm(apmp) + norm(apmm);
- }
-
-} // namespace
-
-// Higgs emitted close to gluon with full mt effects.
-double ME_Houtside_gq(
- HLV const & p1out, HLV const & p1in,
- HLV const & p2out, HLV const & p2in, HLV const & pH,
- const double mt, const bool include_bottom, const double mb, const double vev
-){
- using helicity::plus;
- using helicity::minus;
-
- const auto ph = split_into_lightlike(pH);
- assert(ph.first.e() > 0);
- assert(ph.second.e() > 0);
-
- // incoming gluon with + helicity
- const double ME_plus = ampsq_sum_jh_j(
- p1in, p1out, p2in, p2out, ph.first, ph.second,
- mt, include_bottom, mb, vev
- );
-
- // incoming gluon with - helicity
- const double ME_minus = ampsq_sum_jh_j(
- parity_flip(p1in), parity_flip(p1out), parity_flip(p2in), parity_flip(p2out),
- parity_flip(ph.first), parity_flip(ph.second),
- mt, include_bottom, mb, vev
- );
-
- const double prop = m2(p1in - p1out - pH);
- return (ME_plus + ME_minus)/(prop*prop);
-}
-#endif // HEJ_BUILD_WITH_QCDLOOP
-
-double C2gHgm(HLV const & p2, HLV const & p1, HLV const & pH, double vev){
- const double A=1./(3.*M_PI*vev);
- // Implements Eq. (4.22) in hep-ph/0301013 with modifications to incoming plus momenta
- double s12 = NAN;
- double p1p = NAN;
- double p2p = NAN;
- COM p1perp;
- COM p3perp;
- COM phperp;
- // Determine first whether this is the case p1p\sim php>>p3p or the opposite
- s12=p1.invariantMass2(-p2);
- if (p2.pz()>0.) { // case considered in hep-ph/0301013
- p1p=p1.plus();
- p2p=p2.plus();
- } else { // opposite case
- p1p=p1.minus();
- p2p=p2.minus();
- }
- p1perp=p1.px()+COM(0,1)*p1.py();
- phperp=pH.px()+COM(0,1)*pH.py();
- p3perp=-(p1perp+phperp);
-
- COM temp=COM(0,1)*A/(2.*s12)*(p2p/p1p*conj(p1perp)*p3perp
- +p1p/p2p*p1perp*conj(p3perp));
- temp=temp*conj(temp);
- return temp.real();
-}
-
-double C2gHgp(HLV const & p2, HLV const & p1, HLV const & pH, double vev){
- const double A=1./(3.*M_PI*vev);
- // Implements Eq. (4.23) in hep-ph/0301013
- double s12 = NAN;
- double php = NAN;
- double p1p = NAN;
- double phm = NAN;
- COM p1perp;
- COM p3perp;
- COM phperp;
- // Determine first whether this is the case p1p\sim php>>p3p or the opposite
- s12=p1.invariantMass2(-p2);
- if (p2.pz()>0.) { // case considered in hep-ph/0301013
- php=pH.plus();
- phm=pH.minus();
- p1p=p1.plus();
- } else { // opposite case
- php=pH.minus();
- phm=pH.plus();
- p1p=p1.minus();
- }
- p1perp=p1.px()+COM(0,1)*p1.py();
- phperp=pH.px()+COM(0,1)*pH.py();
- p3perp=-(p1perp+phperp);
-
- COM temp=-COM(0,1)*A/(2.*s12)*( conj(p1perp*p3perp)*pow(php/p1p,2)/(1.+php/p1p)
- +s12*(pow(conj(phperp),2)/(pow(abs(phperp),2)+p1p*phm)
- -pow(conj(p3perp)+(1.+php/p1p)*conj(p1perp),2)
- /((1.+php/p1p)*(pH.m2()+2.*p1.dot(pH)))) );
- temp=temp*conj(temp);
- return temp.real();
-}
-
-double C2qHqm(HLV const & p2, HLV const & p1, HLV const & pH, double vev){
- const double A=1./(3.*M_PI*vev);
- // Implements Eq. (4.21) in hep-ph/0301013
- double s12 = NAN;
- double p2p = NAN;
- double p1p = NAN;
- COM p1perp;
- COM p3perp;
- COM phperp;
- // Determine first whether this is the case p1p\sim php>>p3p or the opposite
- s12=p1.invariantMass2(-p2);
- if (p2.pz()>0.) { // case considered in hep-ph/0301013
- p2p=p2.plus();
- p1p=p1.plus();
- } else { // opposite case
- p2p=p2.minus();
- p1p=p1.minus();
- }
- p1perp=p1.px()+COM(0,1)*p1.py();
- phperp=pH.px()+COM(0,1)*pH.py();
- p3perp=-(p1perp+phperp);
-
- COM temp=A/(2.*s12)*( sqrt(p2p/p1p)*p3perp*conj(p1perp)
- +sqrt(p1p/p2p)*p1perp*conj(p3perp) );
- temp=temp*conj(temp);
- return temp.real();
-}
} // namespace currents
} // namespace HEJ
diff --git a/src/MatrixElement.cc b/src/MatrixElement.cc
index 3a740a3..92dfaaf 100644
--- a/src/MatrixElement.cc
+++ b/src/MatrixElement.cc
@@ -1,2135 +1,2164 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/MatrixElement.hh"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <cstdlib>
#include <iterator>
#include <limits>
#include <unordered_map>
#include <utility>
#include "fastjet/PseudoJet.hh"
#include "HEJ/ConfigFlags.hh"
#include "HEJ/Constants.hh"
#include "HEJ/EWConstants.hh"
#include "HEJ/Event.hh"
#include "HEJ/HiggsCouplingSettings.hh"
#include "HEJ/Hjets.hh"
#include "HEJ/LorentzVector.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/Particle.hh"
#include "HEJ/Wjets.hh"
#include "HEJ/Zjets.hh"
#include "HEJ/event_types.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/jets.hh"
#include "HEJ/utility.hh"
namespace HEJ {
double MatrixElement::omega0(
double alpha_s, double mur,
fastjet::PseudoJet const & q_j
) const {
const double lambda = param_.regulator_lambda;
const double result = - alpha_s*N_C/M_PI*std::log(q_j.perp2()/(lambda*lambda));
if(! param_.log_correction) return result;
return (
1. + alpha_s/(4.*M_PI)*BETA0*std::log(mur*mur/(q_j.perp()*lambda))
)*result;
}
Weights MatrixElement::operator()(Event const & event) const {
std::vector <double> tree_kin_part=tree_kin(event);
std::vector <Weights> virtual_part=virtual_corrections(event);
if(tree_kin_part.size() != virtual_part.size()) {
throw std::logic_error("tree and virtuals have different sizes");
}
Weights sum = Weights{0., std::vector<double>(event.variations().size(), 0.)};
for(size_t i=0; i<tree_kin_part.size(); ++i) {
sum += tree_kin_part.at(i)*virtual_part.at(i);
}
return tree_param(event)*sum;
}
Weights MatrixElement::tree(Event const & event) const {
std::vector <double> tree_kin_part=tree_kin(event);
double sum = 0.;
for(double i : tree_kin_part) {
sum += i;
}
return tree_param(event)*sum;
}
Weights MatrixElement::tree_param(Event const & event) const {
if(! is_resummable(event.type())) {
return Weights{0., std::vector<double>(event.variations().size(), 0.)};
}
Weights result;
// only compute once for each renormalisation scale
std::unordered_map<double, double> known;
result.central = tree_param(event, event.central().mur);
known.emplace(event.central().mur, result.central);
for(auto const & var: event.variations()) {
const auto ME_it = known.find(var.mur);
if(ME_it == end(known)) {
const double wt = tree_param(event, var.mur);
result.variations.emplace_back(wt);
known.emplace(var.mur, wt);
}
else {
result.variations.emplace_back(ME_it->second);
}
}
return result;
}
std::vector<Weights> MatrixElement::virtual_corrections(Event const & event) const {
if(! is_resummable(event.type())) {
return {Weights{0., std::vector<double>(event.variations().size(), 0.)}};
}
// only compute once for each renormalisation scale
std::unordered_map<double, std::vector<double> > known_vec;
std::vector<double> central_vec=virtual_corrections(event, event.central().mur);
known_vec.emplace(event.central().mur, central_vec);
for(auto const & var: event.variations()) {
const auto ME_it = known_vec.find(var.mur);
if(ME_it == end(known_vec)) {
known_vec.emplace(var.mur, virtual_corrections(event, var.mur));
}
}
// At this stage known_vec contains one vector of virtual corrections for each mur value
// Now put this into a vector of Weights
std::vector<Weights> result_vec;
for(size_t i=0; i<central_vec.size(); ++i) {
Weights result;
result.central = central_vec.at(i);
for(auto const & var: event.variations()) {
const auto ME_it = known_vec.find(var.mur);
result.variations.emplace_back(ME_it->second.at(i));
}
result_vec.emplace_back(result);
}
return result_vec;
}
double MatrixElement::virtual_corrections_W(
Event const & event,
const double mur,
Particle const & WBoson
) const{
auto const & in = event.incoming();
const auto partons = filter_partons(event.outgoing());
fastjet::PseudoJet const & pa = in.front().p;
#ifndef NDEBUG
fastjet::PseudoJet const & pb = in.back().p;
double const norm = (in.front().p + in.back().p).E();
#endif
assert(std::is_sorted(partons.begin(), partons.end(), rapidity_less{}));
assert(partons.size() >= 2);
assert(pa.pz() < pb.pz());
fastjet::PseudoJet q = pa - partons[0].p;
std::size_t first_idx = 0;
std::size_t last_idx = partons.size() - 1;
#ifndef NDEBUG
bool wc = true;
#endif
bool wqq = false;
// With extremal qqbar or unordered gluon outside the extremal
// partons then it is not part of the FKL ladder and does not
// contribute to the virtual corrections. W emitted from the
// most backward leg must be taken into account in t-channel
if (event.type() == event_type::unob) {
q -= partons[1].p;
++first_idx;
if (in[0].type != partons[1].type ){
q -= WBoson.p;
#ifndef NDEBUG
wc=false;
#endif
}
}
else if (event.type() == event_type::qqbar_exb) {
q -= partons[1].p;
++first_idx;
if (std::abs(partons[0].type) != std::abs(partons[1].type)){
q -= WBoson.p;
#ifndef NDEBUG
wc=false;
#endif
}
}
else {
if(event.type() == event_type::unof
|| event.type() == event_type::qqbar_exf){
--last_idx;
}
if (in[0].type != partons[0].type ){
q -= WBoson.p;
#ifndef NDEBUG
wc=false;
#endif
}
}
std::size_t first_idx_qqbar = last_idx;
std::size_t last_idx_qqbar = last_idx;
//if qqbarMid event, virtual correction do not occur between qqbar pair.
if(event.type() == event_type::qqbar_mid){
const auto backquark = std::find_if(
begin(partons) + 1, end(partons) - 1 ,
[](Particle const & s){ return (s.type != pid::gluon); }
);
if(backquark == end(partons) || (backquark+1)->type==pid::gluon) return 0;
if(std::abs(backquark->type) != std::abs((backquark+1)->type)) {
wqq=true;
#ifndef NDEBUG
wc=false;
#endif
}
last_idx = std::distance(begin(partons), backquark);
first_idx_qqbar = last_idx+1;
}
double exponent = 0;
const double alpha_s = alpha_s_(mur);
for(std::size_t j = first_idx; j < last_idx; ++j){
exponent += omega0(alpha_s, mur, q)*(
partons[j+1].rapidity() - partons[j].rapidity()
);
q -=partons[j+1].p;
} // End Loop one
if (last_idx != first_idx_qqbar) q -= partons[last_idx+1].p;
if (wqq) q -= WBoson.p;
for(std::size_t j = first_idx_qqbar; j < last_idx_qqbar; ++j){
exponent += omega0(alpha_s, mur, q)*(
partons[j+1].rapidity() - partons[j].rapidity()
);
q -= partons[j+1].p;
}
#ifndef NDEBUG
if (wc) q -= WBoson.p;
assert(
nearby(q, -1*pb, norm)
|| is_AWZH_boson(partons.back().type)
|| event.type() == event_type::unof
|| event.type() == event_type::qqbar_exf
);
#endif
return std::exp(exponent);
}
std::vector <double> MatrixElement::virtual_corrections_Z_qq(
Event const & event,
const double mur,
Particle const & ZBoson
) const{
auto const & in = event.incoming();
const auto partons = filter_partons(event.outgoing());
fastjet::PseudoJet const & pa = in.front().p;
#ifndef NDEBUG
fastjet::PseudoJet const & pb = in.back().p;
#endif
assert(std::is_sorted(partons.begin(), partons.end(), rapidity_less{}));
assert(partons.size() >= 2);
assert(pa.pz() < pb.pz());
fastjet::PseudoJet q_t = pa - partons[0].p - ZBoson.p;
fastjet::PseudoJet q_b = pa - partons[0].p;
size_t first_idx = 0;
size_t last_idx = partons.size() - 1;
// Unordered gluon does not contribute to the virtual corrections
if (event.type() == event_type::unob) {
// Gluon is partons[0] and is already subtracted
// partons[1] is the backward quark
q_t -= partons[1].p;
q_b -= partons[1].p;
++first_idx;
} else if (event.type() == event_type::unof) {
// End sum at forward quark
--last_idx;
}
double sum_top=0.;
double sum_bot=0.;
double sum_mix=0.;
const double alpha_s = alpha_s_(mur);
for(size_t j = first_idx; j < last_idx; ++j){
const double dy = partons[j+1].rapidity() - partons[j].rapidity();
const double tmp_top = omega0(alpha_s, mur, q_t)*dy;
const double tmp_bot = omega0(alpha_s, mur, q_b)*dy;
sum_top += tmp_top;
sum_bot += tmp_bot;
sum_mix += (tmp_top + tmp_bot) / 2.;
q_t -= partons[j+1].p;
q_b -= partons[j+1].p;
}
return {exp(sum_top), exp(sum_bot), exp(sum_mix)};
}
double MatrixElement::virtual_corrections_Z_qg(
Event const & event,
const double mur,
Particle const & ZBoson,
const bool is_gq_event
) const{
auto const & in = event.incoming();
const auto partons = filter_partons(event.outgoing());
fastjet::PseudoJet const & pa = in.front().p;
#ifndef NDEBUG
fastjet::PseudoJet const & pb = in.back().p;
#endif
assert(std::is_sorted(partons.begin(), partons.end(), rapidity_less{}));
assert(partons.size() >= 2);
assert(pa.pz() < pb.pz());
// If this is a gq event, don't subtract the Z momentum from first q
fastjet::PseudoJet q = (is_gq_event ? pa - partons[0].p : pa - partons[0].p - ZBoson.p);
size_t first_idx = 0;
size_t last_idx = partons.size() - 1;
// Unordered gluon does not contribute to the virtual corrections
if (event.type() == event_type::unob) {
// Gluon is partons[0] and is already subtracted
// partons[1] is the backward quark
q -= partons[1].p;
++first_idx;
} else if (event.type() == event_type::unof) {
// End sum at forward quark
--last_idx;
}
double sum=0.;
const double alpha_s = alpha_s_(mur);
for(size_t j = first_idx; j < last_idx; ++j){
sum += omega0(alpha_s, mur, q)*(partons[j+1].rapidity()
- partons[j].rapidity());
q -= partons[j+1].p;
}
return exp(sum);
}
std::vector<double> MatrixElement::virtual_corrections(
Event const & event,
const double mur
) const{
auto const & in = event.incoming();
auto const & out = event.outgoing();
fastjet::PseudoJet const & pa = in.front().p;
#ifndef NDEBUG
fastjet::PseudoJet const & pb = in.back().p;
double const norm = (in.front().p + in.back().p).E();
#endif
const auto AWZH_boson = std::find_if(
begin(out), end(out),
[](Particle const & p){ return is_AWZH_boson(p); }
);
if(AWZH_boson != end(out) && std::abs(AWZH_boson->type) == pid::Wp){
return {virtual_corrections_W(event, mur, *AWZH_boson)};
}
if(AWZH_boson != end(out) && AWZH_boson->type == pid::Z_photon_mix){
if(is_gluon(in.back().type)){
// This is a qg event
return {virtual_corrections_Z_qg(event, mur, *AWZH_boson, false)};
}
if(is_gluon(in.front().type)){
// This is a gq event
return {virtual_corrections_Z_qg(event, mur, *AWZH_boson, true)};
}
// This is a qq event
return virtual_corrections_Z_qq(event, mur, *AWZH_boson);
}
assert(std::is_sorted(out.begin(), out.end(), rapidity_less{}));
assert(out.size() >= 2);
assert(pa.pz() < pb.pz());
fastjet::PseudoJet q = pa - out[0].p;
std::size_t first_idx = 0;
std::size_t last_idx = out.size() - 1;
- // if there is a Higgs boson, extremal qqbar or unordered gluon
- // outside the extremal partons then it is not part of the FKL
- // ladder and does not contribute to the virtual corrections
- if((out.front().type == pid::Higgs)
+ // if there is a Higgs boson _not_ emitted off an incoming gluon,
+ // extremal qqbar or unordered gluon outside the extremal partons
+ // then it is not part of the FKL ladder
+ // and does not contribute to the virtual corrections
+ if((out.front().type == pid::Higgs && in.front().type != pid::gluon)
|| event.type() == event_type::unob
|| event.type() == event_type::qqbar_exb){
q -= out[1].p;
++first_idx;
}
- if((out.back().type == pid::Higgs)
+ if((out.back().type == pid::Higgs && in.back().type != pid::gluon)
|| event.type() == event_type::unof
|| event.type() == event_type::qqbar_exf){
--last_idx;
}
std::size_t first_idx_qqbar = last_idx;
std::size_t last_idx_qqbar = last_idx;
//if central qqbar event, virtual correction do not occur between q-qbar.
if(event.type() == event_type::qqbar_mid){
const auto backquark = std::find_if(
begin(out) + 1, end(out) - 1 ,
[](Particle const & s){ return (s.type != pid::gluon && is_parton(s.type)); }
);
if(backquark == end(out) || (backquark+1)->type==pid::gluon) return {0.};
last_idx = std::distance(begin(out), backquark);
first_idx_qqbar = last_idx+1;
}
double exponent = 0;
const double alpha_s = alpha_s_(mur);
for(std::size_t j = first_idx; j < last_idx; ++j){
exponent += omega0(alpha_s, mur, q)*(
out[j+1].rapidity() - out[j].rapidity()
);
q -= out[j+1].p;
}
if (last_idx != first_idx_qqbar) q -= out[last_idx+1].p;
for(std::size_t j = first_idx_qqbar; j < last_idx_qqbar; ++j){
exponent += omega0(alpha_s, mur, q)*(
out[j+1].rapidity() - out[j].rapidity()
);
q -= out[j+1].p;
}
assert(
nearby(q, -1*pb, norm)
- || out.back().type == pid::Higgs
+ || (out.back().type == pid::Higgs && in.back().type != pid::gluon)
|| event.type() == event_type::unof
|| event.type() == event_type::qqbar_exf
);
return {std::exp(exponent)};
}
namespace {
//! Lipatov vertex for partons emitted into extremal jets
CLHEP::HepLorentzVector CLipatov(
CLHEP::HepLorentzVector const & qav, CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & p2
) {
const CLHEP::HepLorentzVector p5 = qav-qbv;
const CLHEP::HepLorentzVector CL = -(qav+qbv)
+ p1*(qav.m2()/p5.dot(p1) + 2.*p5.dot(p2)/p1.dot(p2))
- p2*(qbv.m2()/p5.dot(p2) + 2.*p5.dot(p1)/p1.dot(p2));
return CL;
}
double C2Lipatov(
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & p2
){
const CLHEP::HepLorentzVector CL = CLipatov(qav, qbv, p1, p2);
return -CL.dot(CL);
}
//! Lipatov vertex with soft subtraction for partons emitted into extremal jets
double C2Lipatovots(
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & p2,
const double lambda
) {
const double Cls=(C2Lipatov(qav, qbv, p1, p2)/(qav.m2()*qbv.m2()));
const double kperp=(qav-qbv).perp();
if (kperp>lambda)
return Cls;
return Cls-4./(kperp*kperp);
}
double C2Lipatov_Mix(
CLHEP::HepLorentzVector const & qav_t, CLHEP::HepLorentzVector const & qbv_t,
CLHEP::HepLorentzVector const & qav_b, CLHEP::HepLorentzVector const & qbv_b,
CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & p2
) {
const CLHEP::HepLorentzVector CL_t = CLipatov(qav_t, qbv_t, p1, p2);
const CLHEP::HepLorentzVector CL_b = CLipatov(qav_b, qbv_b, p1, p2);
return -CL_t.dot(CL_b);
}
double C2Lipatovots_Mix(
CLHEP::HepLorentzVector const & qav_t, CLHEP::HepLorentzVector const & qbv_t,
CLHEP::HepLorentzVector const & qav_b, CLHEP::HepLorentzVector const & qbv_b,
CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & p2,
const double lambda
) {
const double Cls = C2Lipatov_Mix(qav_t, qbv_t, qav_b, qbv_b, p1, p2)
/ sqrt(qav_t.m2() * qbv_t.m2() * qav_b.m2() * qbv_b.m2());
const double kperp = (qav_t - qbv_t).perp();
if (kperp > lambda){
return Cls;
}
return Cls - 4.0 / (kperp * kperp);
}
CLHEP::HepLorentzVector CLipatov(
CLHEP::HepLorentzVector const & qav, CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & pim, CLHEP::HepLorentzVector const & pip,
CLHEP::HepLorentzVector const & pom, CLHEP::HepLorentzVector const & pop
){
const CLHEP::HepLorentzVector p5 = qav-qbv;
const CLHEP::HepLorentzVector CL = -(qav+qbv)
+ qav.m2()*(1./p5.dot(pip)*pip + 1./p5.dot(pop)*pop)/2.
- qbv.m2()*(1./p5.dot(pim)*pim + 1./p5.dot(pom)*pom)/2.
+ ( pip*(p5.dot(pim)/pip.dot(pim) + p5.dot(pom)/pip.dot(pom))
+ pop*(p5.dot(pim)/pop.dot(pim) + p5.dot(pom)/pop.dot(pom))
- pim*(p5.dot(pip)/pip.dot(pim) + p5.dot(pop)/pop.dot(pim))
- pom*(p5.dot(pip)/pip.dot(pom) + p5.dot(pop)/pop.dot(pom)) )/2.;
return CL;
}
//! Lipatov vertex
double C2Lipatov( // B
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & pim,
CLHEP::HepLorentzVector const & pip,
CLHEP::HepLorentzVector const & pom,
CLHEP::HepLorentzVector const & pop
){
const CLHEP::HepLorentzVector CL = CLipatov(qav, qbv, pim, pip, pom, pop);
return -CL.dot(CL);
}
//! Lipatov vertex with soft subtraction
double C2Lipatovots(
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & p2,
const double lambda
) {
const double Cls=(C2Lipatov(qav, qbv, pa, pb, p1, p2)/(qav.m2()*qbv.m2()));
const double kperp=(qav-qbv).perp();
if (kperp>lambda)
return Cls;
return Cls-4./(kperp*kperp);
}
double C2Lipatov_Mix(
CLHEP::HepLorentzVector const & qav_t, CLHEP::HepLorentzVector const & qbv_t,
CLHEP::HepLorentzVector const & qav_b, CLHEP::HepLorentzVector const & qbv_b,
CLHEP::HepLorentzVector const & pim, CLHEP::HepLorentzVector const & pip,
CLHEP::HepLorentzVector const & pom, CLHEP::HepLorentzVector const & pop
) {
const CLHEP::HepLorentzVector CL_t = CLipatov(qav_t, qbv_t, pim, pip, pom, pop);
const CLHEP::HepLorentzVector CL_b = CLipatov(qav_b, qbv_b, pim, pip, pom, pop);
return -CL_t.dot(CL_b);
}
double C2Lipatovots_Mix(
CLHEP::HepLorentzVector const & qav_t, CLHEP::HepLorentzVector const & qbv_t,
CLHEP::HepLorentzVector const & qav_b, CLHEP::HepLorentzVector const & qbv_b,
CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & p2,
const double lambda
) {
const double Cls = C2Lipatov_Mix(qav_t, qbv_t, qav_b, qbv_b, pa, pb, p1, p2)
/ sqrt(qav_t.m2() * qbv_t.m2() * qav_b.m2() * qbv_b.m2());
const double kperp = (qav_t - qbv_t).perp();
if (kperp > lambda) {
return Cls;
}
return Cls - 4.0 / (kperp * kperp);
}
/** Matrix element squared for tree-level current-current scattering
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pg Unordered gluon momentum
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @returns ME Squared for Tree-Level Current-Current Scattering
*
* @note The unof contribution can be calculated by reversing the argument ordering.
*/
double ME_uno_current(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pg,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa
){
using namespace currents;
assert(aptype!=pid::gluon); // aptype cannot be gluon
if (bptype==pid::gluon) {
if (is_quark(aptype))
return ME_unob_qg(pg,p1,pa,pn,pb);
return ME_unob_qbarg(pg,p1,pa,pn,pb);
}
if (is_antiquark(bptype)) {
if (is_quark(aptype))
return ME_unob_qQbar(pg,p1,pa,pn,pb);
return ME_unob_qbarQbar(pg,p1,pa,pn,pb);
}
//bptype == quark
if (is_quark(aptype))
return ME_unob_qQ(pg,p1,pa,pn,pb);
return ME_unob_qbarQ(pg,p1,pa,pn,pb);
}
/** Matrix element squared for tree-level current-current scattering
* @param bptype Particle b PDG ID
* @param pgin Incoming gluon momentum
* @param pq Quark from splitting Momentum
* @param pqbar Anti-quark from splitting Momentum
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param swap_qqbar Ordering of qqbar pair. False: pqbar extremal.
* @returns ME Squared for Tree-Level Current-Current Scattering
*
* @note The forward qqbar contribution can be calculated by reversing the
* argument ordering.
*/
double ME_qqbar_current(
ParticleID bptype,
CLHEP::HepLorentzVector const & pgin,
CLHEP::HepLorentzVector const & pq,
CLHEP::HepLorentzVector const & pqbar,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
bool const swap_qqbar
){
using namespace currents;
if (bptype==pid::gluon) {
if (swap_qqbar) // pq extremal
return ME_Exqqbar_qqbarg(pgin,pq,pqbar,pn,pb);
// pqbar extremal
return ME_Exqqbar_qbarqg(pgin,pq,pqbar,pn,pb);
}
// b leg quark line
if (swap_qqbar) //extremal pq
return ME_Exqqbar_qqbarQ(pgin,pq,pqbar,pn,pb);
return ME_Exqqbar_qbarqQ(pgin,pq,pqbar,pn,pb);
}
/* \brief Matrix element squared for central qqbar tree-level current-current
* scattering
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param nabove Number of gluons emitted before central qqbarpair
* @param nbelow Number of gluons emitted after central qqbarpair
* @param pa Initial state a Momentum
* @param pb Initial state b Momentum
* @param pq Final state qbar Momentum
* @param pqbar Final state q Momentum
* @param partons Vector of all outgoing partons
* @returns ME Squared for qqbar_mid Tree-Level Current-Current Scattering
*/
double ME_qqbar_mid_current(
ParticleID aptype, ParticleID bptype, int nabove,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & pq,
CLHEP::HepLorentzVector const & pqbar,
std::vector<CLHEP::HepLorentzVector> const & partons
){
using namespace currents;
// CAM factors for the qqbar amps, and qqbar ordering (default, pq backwards)
const bool swap_qqbar=pqbar.rapidity() < pq.rapidity();
double wt=1.;
if (aptype==pid::gluon) wt*=K_g(partons.front(),pa)/C_F;
if (bptype==pid::gluon) wt*=K_g(partons.back(),pb)/C_F;
return wt*ME_Cenqqbar_qq(pa, pb, partons, is_antiquark(bptype),
is_antiquark(aptype), swap_qqbar, nabove);
}
/** Matrix element squared for tree-level current-current scattering
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @returns ME Squared for Tree-Level Current-Current Scattering
*/
double ME_current(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa
){
using namespace currents;
if (aptype==pid::gluon && bptype==pid::gluon) {
return ME_gg(pn,pb,p1,pa);
}
if (aptype==pid::gluon && bptype!=pid::gluon) {
if (is_quark(bptype))
return ME_qg(pn,pb,p1,pa);
return ME_qbarg(pn,pb,p1,pa);
}
if (bptype==pid::gluon && aptype!=pid::gluon) {
if (is_quark(aptype))
return ME_qg(p1,pa,pn,pb);
return ME_qbarg(p1,pa,pn,pb);
}
// they are both quark
if (is_quark(bptype)) {
if (is_quark(aptype))
return ME_qQ(pn,pb,p1,pa);
return ME_qQbar(pn,pb,p1,pa);
}
if (is_quark(aptype))
return ME_qQbar(p1,pa,pn,pb);
return ME_qbarQbar(pn,pb,p1,pa);
}
/** Matrix element squared for tree-level current-current scattering With W+Jets
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for Tree-Level Current-Current Scattering
*/
double ME_W_current(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wc, ParticleProperties const & Wprop
){
using namespace currents;
// We know it cannot be gg incoming.
assert(!(aptype==pid::gluon && bptype==pid::gluon));
if (aptype==pid::gluon && bptype!=pid::gluon) {
if (is_quark(bptype))
return ME_W_qg(pn,plbar,pl,pb,p1,pa,Wprop);
return ME_W_qbarg(pn,plbar,pl,pb,p1,pa,Wprop);
}
if (bptype==pid::gluon && aptype!=pid::gluon) {
if (is_quark(aptype))
return ME_W_qg(p1,plbar,pl,pa,pn,pb,Wprop);
return ME_W_qbarg(p1,plbar,pl,pa,pn,pb,Wprop);
}
// they are both quark
if (wc){ // emission off b, (first argument pbout)
if (is_quark(bptype)) {
if (is_quark(aptype))
return ME_W_qQ(pn,plbar,pl,pb,p1,pa,Wprop);
return ME_W_qQbar(pn,plbar,pl,pb,p1,pa,Wprop);
}
if (is_quark(aptype))
return ME_W_qbarQ(pn,plbar,pl,pb,p1,pa,Wprop);
return ME_W_qbarQbar(pn,plbar,pl,pb,p1,pa,Wprop);
}
// emission off a, (first argument paout)
if (is_quark(aptype)) {
if (is_quark(bptype))
return ME_W_qQ(p1,plbar,pl,pa,pn,pb,Wprop);
return ME_W_qQbar(p1,plbar,pl,pa,pn,pb,Wprop);
}
// a is anti-quark
if (is_quark(bptype))
return ME_W_qbarQ(p1,plbar,pl,pa,pn,pb,Wprop);
return ME_W_qbarQbar(p1,plbar,pl,pa,pn,pb,Wprop);
}
/** Matrix element squared for backwards uno tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param pg Unordered gluon momentum
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for unob Tree-Level Current-Current Scattering
*
* @note The unof contribution can be calculated by reversing the argument ordering.
*/
double ME_W_uno_current(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pg,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wc, ParticleProperties const & Wprop
){
using namespace currents;
// we know they are not both gluons
assert(bptype != pid::gluon || aptype != pid::gluon);
if (bptype == pid::gluon && aptype != pid::gluon) {
// b gluon => W emission off a
if (is_quark(aptype))
return ME_Wuno_qg(p1,pa,pn,pb,pg,plbar,pl,Wprop);
return ME_Wuno_qbarg(p1,pa,pn,pb,pg,plbar,pl,Wprop);
}
// they are both quark
if (wc) {// emission off b, i.e. b is first current
if (is_quark(bptype)){
if (is_quark(aptype))
return ME_W_unob_qQ(p1,pa,pn,pb,pg,plbar,pl,Wprop);
return ME_W_unob_qQbar(p1,pa,pn,pb,pg,plbar,pl,Wprop);
}
if (is_quark(aptype))
return ME_W_unob_qbarQ(p1,pa,pn,pb,pg,plbar,pl,Wprop);
return ME_W_unob_qbarQbar(p1,pa,pn,pb,pg,plbar,pl,Wprop);
}
// wc == false, emission off a, i.e. a is first current
if (is_quark(aptype)) {
if (is_quark(bptype)) //qq
return ME_Wuno_qQ(p1,pa,pn,pb,pg,plbar,pl,Wprop);
//qqbar
return ME_Wuno_qQbar(p1,pa,pn,pb,pg,plbar,pl,Wprop);
}
// a is anti-quark
if (is_quark(bptype)) //qbarq
return ME_Wuno_qbarQ(p1,pa,pn,pb,pg,plbar,pl,Wprop);
//qbarqbar
return ME_Wuno_qbarQbar(p1,pa,pn,pb,pg,plbar,pl,Wprop);
}
/** \brief Matrix element squared for backward qqbar tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pa Initial state a Momentum
* @param pb Initial state b Momentum
* @param pq Final state q Momentum
* @param pqbar Final state qbar Momentum
* @param pn Final state n Momentum
* @param plbar Final state anti-lepton momentum
* @param pl Final state lepton momentum
* @param swap_qqbar Ordering of qqbar pair. False: pqbar extremal.
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for qqbarb Tree-Level Current-Current Scattering
*
* @note calculate forwards qqbar contribution by reversing argument ordering.
*/
double ME_W_qqbar_current(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & pq,
CLHEP::HepLorentzVector const & pqbar,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const swap_qqbar, bool const wc,
ParticleProperties const & Wprop
){
using namespace currents;
// With qqbar we could have 2 incoming gluons and W Emission
if (aptype==pid::gluon && bptype==pid::gluon) {
//a gluon, b gluon gg->qqbarWg
// This will be a wqqbar emission as there is no other possible W Emission
// Site.
if (swap_qqbar)
return ME_WExqqbar_qqbarg(pa, pqbar, plbar, pl, pq, pn, pb, Wprop);
return ME_WExqqbar_qbarqg(pa, pq, plbar, pl, pqbar, pn, pb, Wprop);
}
assert(aptype==pid::gluon && bptype!=pid::gluon );
//a gluon => W emission off b leg or qqbar
if (!wc){ // W Emitted from backwards qqbar
if (swap_qqbar)
return ME_WExqqbar_qqbarQ(pa, pqbar, plbar, pl, pq, pn, pb, Wprop);
return ME_WExqqbar_qbarqQ(pa, pq, plbar, pl, pqbar, pn, pb, Wprop);
}
// W Must be emitted from forwards leg.
return ME_W_Exqqbar_QQq(pb, pa, pn, pq, pqbar, plbar, pl, is_antiquark(bptype), Wprop);
}
/* \brief Matrix element squared for central qqbar tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param nabove Number of gluons emitted before central qqbarpair
* @param nbelow Number of gluons emitted after central qqbarpair
* @param pa Initial state a Momentum
* @param pb Initial state b Momentum\
* @param pq Final state qbar Momentum
* @param pqbar Final state q Momentum
* @param partons Vector of all outgoing partons
* @param plbar Final state anti-lepton momentum
* @param pl Final state lepton momentum
* @param wqq Boolean. True siginfies W boson is emitted from Central qqbar
* @param wc Boolean. wc=true signifies w boson emitted from leg b; if wqq=false.
* @returns ME Squared for qqbar_mid Tree-Level Current-Current Scattering
*/
double ME_W_qqbar_mid_current(
ParticleID aptype, ParticleID bptype,
int nabove, int nbelow,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & pq,
CLHEP::HepLorentzVector const & pqbar,
std::vector<CLHEP::HepLorentzVector> const & partons,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wqq, bool const wc,
ParticleProperties const & Wprop
){
using namespace currents;
// CAM factors for the qqbar amps, and qqbar ordering (default, pq backwards)
const bool swap_qqbar=pqbar.rapidity() < pq.rapidity();
double wt=1.;
if (aptype==pid::gluon) wt*=K_g(partons.front(),pa)/C_F;
if (bptype==pid::gluon) wt*=K_g(partons.back(),pb)/C_F;
if(wqq)
return wt*ME_WCenqqbar_qq(pa, pb, pl, plbar, partons,
is_antiquark(aptype),is_antiquark(bptype),
swap_qqbar, nabove, Wprop);
return wt*ME_W_Cenqqbar_qq(pa, pb, pl, plbar, partons,
is_antiquark(aptype), is_antiquark(bptype),
swap_qqbar, nabove, nbelow, wc, Wprop);
}
/** Matrix element squared for tree-level current-current scattering With Z+Jets
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param plbar Final state positron momentum
* @param pl Final state electron momentum
* @param Zprop Z properties
* @param stw2 Value of sin(theta_w)^2
* @param ctw Value of cos(theta_w)
* @returns ME Squared for Tree-Level Current-Current Scattering
*/
std::vector<double> ME_Z_current(
const ParticleID aptype, const ParticleID bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
ParticleProperties const & Zprop,
const double stw2, const double ctw
){
using namespace currents;
// we know they are not both gluons
assert(!is_gluon(aptype) || !is_gluon(bptype));
if(is_anyquark(aptype) && is_gluon(bptype)){
// This is a qg event
return { ME_Z_qg(pa,pb,p1,pn,plbar,pl,aptype,bptype,Zprop,stw2,ctw) };
}
if(is_gluon(aptype) && is_anyquark(bptype)){
// This is a gq event
return { ME_Z_qg(pb,pa,pn,p1,plbar,pl,bptype,aptype,Zprop,stw2,ctw) };
}
assert(is_anyquark(aptype) && is_anyquark(bptype));
// This is a qq event
return ME_Z_qQ(pa,pb,p1,pn,plbar,pl,aptype,bptype,Zprop,stw2,ctw);
}
/** Matrix element squared for backwards uno tree-level current-current
* scattering With Z+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param pg Unordered gluon momentum
* @param plbar Final state positron momentum
* @param pl Final state electron momentum
* @param Zprop Z properties
* @param stw2 Value of sin(theta_w)^2
* @param ctw Value of cos(theta_w)
* @returns ME Squared for unob Tree-Level Current-Current Scattering
*
* @note The unof contribution can be calculated by reversing the argument ordering.
*/
std::vector<double> ME_Z_uno_current(
const ParticleID aptype, const ParticleID bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pg,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
ParticleProperties const & Zprop,
const double stw2, const double ctw
){
using namespace currents;
// we know they are not both gluons
assert(!is_gluon(aptype) || !is_gluon(bptype));
if (is_anyquark(aptype) && is_gluon(bptype)) {
// This is a qg event
return { ME_Zuno_qg(pa,pb,pg,p1,pn,plbar,pl,aptype,bptype,Zprop,stw2,ctw) };
}
if (is_gluon(aptype) && is_anyquark(bptype)) {
// This is a gq event
return { ME_Zuno_qg(pb,pa,pg,pn,p1,plbar,pl,bptype,aptype,Zprop,stw2,ctw) };
}
assert(is_anyquark(aptype) && is_anyquark(bptype));
// This is a qq event
return ME_Zuno_qQ(pa,pb,pg,p1,pn,plbar,pl,aptype,bptype,Zprop,stw2,ctw);
}
/** \brief Matrix element squared for tree-level current-current scattering with Higgs
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param qH t-channel momentum before Higgs
* @param qHp1 t-channel momentum after Higgs
* @returns ME Squared for Tree-Level Current-Current Scattering with Higgs
*/
double ME_Higgs_current(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & qH, // t-channel momentum before Higgs
CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
double mt, bool include_bottom, double mb, double vev
){
using namespace currents;
if (aptype==pid::gluon && bptype==pid::gluon)
// gg initial state
return ME_H_gg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb,vev);
if (aptype==pid::gluon&&bptype!=pid::gluon) {
if (is_quark(bptype))
return ME_H_qg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb,vev)*4./9.;
return ME_H_qbarg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb,vev)*4./9.;
}
if (bptype==pid::gluon && aptype!=pid::gluon) {
if (is_quark(aptype))
return ME_H_qg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev)*4./9.;
return ME_H_qbarg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev)*4./9.;
}
// they are both quark
if (is_quark(bptype)) {
if (is_quark(aptype))
return ME_H_qQ(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb,vev)*4.*4./(9.*9.);
return ME_H_qQbar(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb,vev)*4.*4./(9.*9.);
}
if (is_quark(aptype))
return ME_H_qbarQ(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb,vev)*4.*4./(9.*9.);
return ME_H_qbarQbar(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb,vev)*4.*4./(9.*9.);
}
/** \brief Current matrix element squared with Higgs and unordered backward emission
* @param aptype Particle A PDG ID
* @param bptype Particle B PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param pg Unordered back Particle Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param qH t-channel momentum before Higgs
* @param qHp1 t-channel momentum after Higgs
* @returns ME Squared with Higgs and unordered backward emission
*
* @note This function assumes unordered gluon backwards from pa-p1 current.
* For unof, reverse call order
*/
double ME_Higgs_current_uno(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pg,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & qH, // t-channel momentum before Higgs
CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
double mt, bool include_bottom, double mb, double vev
){
using namespace currents;
if (bptype==pid::gluon && aptype!=pid::gluon) {
if (is_quark(aptype))
return ME_H_unob_gQ(pg,p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev);
return ME_H_unob_gQbar(pg,p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev);
}
// they are both quark
if (is_quark(aptype)) {
if (is_quark(bptype))
return ME_H_unob_qQ(pg,p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev);
return ME_H_unob_qbarQ(pg,p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev);
}
if (is_quark(bptype))
return ME_H_unob_qQbar(pg,p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev);
return ME_H_unob_qbarQbar(pg,p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb,vev);
}
void validate(MatrixElementConfig const & config) {
#ifndef HEJ_BUILD_WITH_QCDLOOP
if(!config.Higgs_coupling.use_impact_factors) {
throw std::invalid_argument{
"Invalid Higgs coupling settings.\n"
"HEJ without QCDloop support can only use impact factors.\n"
"Set use_impact_factors to true or recompile HEJ.\n"
};
}
#endif
if(config.Higgs_coupling.use_impact_factors
&& config.Higgs_coupling.mt != std::numeric_limits<double>::infinity()) {
throw std::invalid_argument{
"Conflicting settings: "
"impact factors may only be used in the infinite top mass limit"
};
}
}
} // namespace
MatrixElement::MatrixElement(
std::function<double (double)> alpha_s,
MatrixElementConfig conf
):
alpha_s_{std::move(alpha_s)},
param_{std::move(conf)}
{
validate(param_);
}
std::vector<double> MatrixElement::tree_kin(
Event const & ev
) const {
if(!ev.valid_hej_state(param_.soft_pt_regulator)) return {0.};
auto AWZH_boson = std::find_if(
begin(ev.outgoing()), end(ev.outgoing()),
[](Particle const & p){return is_AWZH_boson(p);}
);
if(AWZH_boson == end(ev.outgoing()))
return {tree_kin_jets(ev)};
switch(AWZH_boson->type){
case pid::Higgs:
return {tree_kin_Higgs(ev)};
case pid::Wp:
case pid::Wm:
return {tree_kin_W(ev)};
case pid::Z_photon_mix:
return tree_kin_Z(ev);
// TODO
case pid::photon:
case pid::Z:
default:
throw not_implemented("Emission of boson of unsupported type");
}
}
namespace {
constexpr int EXTREMAL_JET_IDX = 1;
constexpr int NO_EXTREMAL_JET_IDX = 0;
bool treat_as_extremal(Particle const & parton){
return parton.p.user_index() == EXTREMAL_JET_IDX;
}
template<class InputIterator>
double FKL_ladder_weight(
InputIterator begin_gluon, InputIterator end_gluon,
CLHEP::HepLorentzVector const & q0,
CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & pn,
double lambda
){
double wt = 1;
auto qi = q0;
for(auto gluon_it = begin_gluon; gluon_it != end_gluon; ++gluon_it){
assert(gluon_it->type == pid::gluon);
const auto g = to_HepLorentzVector(*gluon_it);
const auto qip1 = qi - g;
if(treat_as_extremal(*gluon_it)){
wt *= C2Lipatovots(qip1, qi, pa, pb, lambda)*C_A;
} else{
wt *= C2Lipatovots(qip1, qi, pa, pb, p1, pn, lambda)*C_A;
}
qi = qip1;
}
return wt;
}
template<class InputIterator>
std::vector <double> FKL_ladder_weight_mix(
InputIterator begin_gluon, InputIterator end_gluon,
CLHEP::HepLorentzVector const & q0_t, CLHEP::HepLorentzVector const & q0_b,
CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & pn,
const double lambda
){
double wt_top = 1;
double wt_bot = 1;
double wt_mix = 1;
auto qi_t = q0_t;
auto qi_b = q0_b;
for(auto gluon_it = begin_gluon; gluon_it != end_gluon; ++gluon_it){
assert(gluon_it->type == pid::gluon);
const auto g = to_HepLorentzVector(*gluon_it);
const auto qip1_t = qi_t - g;
const auto qip1_b = qi_b - g;
if(treat_as_extremal(*gluon_it)){
wt_top *= C2Lipatovots(qip1_t, qi_t, pa, pb, lambda)*C_A;
wt_bot *= C2Lipatovots(qip1_b, qi_b, pa, pb, lambda)*C_A;
wt_mix *= C2Lipatovots_Mix(qip1_t, qi_t, qip1_b, qi_b, pa, pb, lambda)*C_A;
} else{
wt_top *= C2Lipatovots(qip1_t, qi_t, pa, pb, p1, pn, lambda)*C_A;
wt_bot *= C2Lipatovots(qip1_b, qi_b, pa, pb, p1, pn, lambda)*C_A;
wt_mix *= C2Lipatovots_Mix(qip1_t, qi_t, qip1_b, qi_b, pa, pb, p1, pn, lambda)*C_A;
}
qi_t = qip1_t;
qi_b = qip1_b;
}
return {wt_top, wt_bot, wt_mix};
}
std::vector<Particle> tag_extremal_jet_partons( Event const & ev ){
auto out_partons = filter_partons(ev.outgoing());
if(out_partons.size() == ev.jets().size()){
// no additional emissions in extremal jets, don't need to tag anything
for(auto & parton: out_partons){
parton.p.set_user_index(NO_EXTREMAL_JET_IDX);
}
return out_partons;
}
auto const & jets = ev.jets();
- assert(jets.size() >= 2);
- auto most_backward = begin(jets);
- auto most_forward = end(jets) - 1;
- // skip jets caused by unordered emission or qqbar
- if(ev.type() == event_type::unob || ev.type() == event_type::qqbar_exb){
- assert(jets.size() >= 3);
- ++most_backward;
+ std::vector<fastjet::PseudoJet> extremal_jets;
+ if(! is_backward_g_to_h(ev)) {
+ auto most_backward = begin(jets);
+ // skip jets caused by unordered emission or qqbar
+ if(ev.type() == event_type::unob || ev.type() == event_type::qqbar_exb){
+ assert(jets.size() >= 2);
+ ++most_backward;
+ }
+ extremal_jets.emplace_back(*most_backward);
}
- else if(ev.type() == event_type::unof || ev.type() == event_type::qqbar_exf){
- assert(jets.size() >= 3);
- --most_forward;
+ if(! is_forward_g_to_h(ev)) {
+ auto most_forward = end(jets) - 1;
+ if(ev.type() == event_type::unof || ev.type() == event_type::qqbar_exf){
+ assert(jets.size() >= 2);
+ --most_forward;
+ }
+ extremal_jets.emplace_back(*most_forward);
}
const auto extremal_jet_indices = ev.particle_jet_indices(
- {*most_backward, *most_forward}
+ extremal_jets
);
assert(extremal_jet_indices.size() == out_partons.size());
for(std::size_t i = 0; i < out_partons.size(); ++i){
assert(is_parton(out_partons[i]));
const int idx = (extremal_jet_indices[i]>=0)?
EXTREMAL_JET_IDX:
NO_EXTREMAL_JET_IDX;
out_partons[i].p.set_user_index(idx);
}
return out_partons;
}
double tree_kin_jets_qqbar_mid(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
std::vector<Particle> const & partons,
double lambda
){
CLHEP::HepLorentzVector pq;
CLHEP::HepLorentzVector pqbar;
const auto backmidquark = std::find_if(
begin(partons)+1, end(partons)-1,
[](Particle const & s){ return s.type != pid::gluon; }
);
assert(backmidquark!=end(partons)-1);
if (is_quark(backmidquark->type)){
pq = to_HepLorentzVector(*backmidquark);
pqbar = to_HepLorentzVector(*(backmidquark+1));
}
else {
pqbar = to_HepLorentzVector(*backmidquark);
pq = to_HepLorentzVector(*(backmidquark+1));
}
auto p1 = to_HepLorentzVector(partons[0]);
auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
auto q0 = pa - p1;
// t-channel momentum after qqbar
auto qqbart = q0;
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder_1 = (backmidquark);
const auto begin_ladder_2 = (backmidquark+2);
const auto end_ladder = cend(partons) - 1;
for(auto parton_it = begin_ladder; parton_it < begin_ladder_2; ++parton_it){
qqbart -= to_HepLorentzVector(*parton_it);
}
const int nabove = std::distance(begin_ladder, backmidquark);
std::vector<CLHEP::HepLorentzVector> partonsHLV;
partonsHLV.reserve(partons.size());
for (std::size_t i = 0; i != partons.size(); ++i) {
partonsHLV.push_back(to_HepLorentzVector(partons[i]));
}
const double current_factor = ME_qqbar_mid_current(
aptype, bptype, nabove, pa, pb,
pq, pqbar, partonsHLV
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder_1,
q0, pa, pb, p1, pn,
lambda
)*FKL_ladder_weight(
begin_ladder_2, end_ladder,
qqbart, pa, pb, p1, pn,
lambda
);
return current_factor*ladder_factor;
}
template<class InIter, class partIter>
double tree_kin_jets_qqbar(InIter BeginIn, InIter EndIn, partIter BeginPart,
partIter EndPart, double lambda){
const bool swap_qqbar = is_quark(*BeginPart);
const auto pgin = to_HepLorentzVector(*BeginIn);
const auto pb = to_HepLorentzVector(*(EndIn-1));
const auto pq = to_HepLorentzVector(*(BeginPart+(swap_qqbar?0:1)));
const auto pqbar = to_HepLorentzVector(*(BeginPart+(swap_qqbar?1:0)));
const auto p1 = to_HepLorentzVector(*(BeginPart));
const auto pn = to_HepLorentzVector(*(EndPart-1));
assert((BeginIn)->type==pid::gluon); // Incoming a must be gluon.
const double current_factor = ME_qqbar_current(
(EndIn-1)->type, pgin, pq, pqbar, pn, pb, swap_qqbar
)/(4.*(N_C*N_C - 1.));
const double ladder_factor = FKL_ladder_weight(
(BeginPart+2), (EndPart-1),
pgin-pq-pqbar, pgin, pb, p1, pn, lambda
);
return current_factor*ladder_factor;
}
template<class InIter, class partIter>
double tree_kin_jets_uno(InIter BeginIn, InIter EndIn, partIter BeginPart,
partIter EndPart, double lambda
){
const auto pa = to_HepLorentzVector(*BeginIn);
const auto pb = to_HepLorentzVector(*(EndIn-1));
const auto pg = to_HepLorentzVector(*BeginPart);
const auto p1 = to_HepLorentzVector(*(BeginPart+1));
const auto pn = to_HepLorentzVector(*(EndPart-1));
const double current_factor = ME_uno_current(
(BeginIn)->type, (EndIn-1)->type, pg, pn, pb, p1, pa
);
const double ladder_factor = FKL_ladder_weight(
(BeginPart+2), (EndPart-1),
pa-p1-pg, pa, pb, p1, pn, lambda
);
return current_factor*ladder_factor;
}
} // namespace
double MatrixElement::tree_kin_jets(Event const & ev) const {
auto const & incoming = ev.incoming();
const auto partons = tag_extremal_jet_partons(ev);
if (ev.type()==event_type::FKL){
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
const auto p1 = to_HepLorentzVector(partons.front());
const auto pn = to_HepLorentzVector(partons.back());
return ME_current(
incoming[0].type, incoming[1].type,
pn, pb, p1, pa
)/(4.*(N_C*N_C - 1.))*FKL_ladder_weight(
begin(partons) + 1, end(partons) - 1,
pa - p1, pa, pb, p1, pn,
param_.regulator_lambda
);
}
if (ev.type()==event_type::unordered_backward){
return tree_kin_jets_uno(incoming.begin(), incoming.end(),
partons.begin(), partons.end(),
param_.regulator_lambda);
}
if (ev.type()==event_type::unordered_forward){
return tree_kin_jets_uno(incoming.rbegin(), incoming.rend(),
partons.rbegin(), partons.rend(),
param_.regulator_lambda);
}
if (ev.type()==event_type::extremal_qqbar_backward){
return tree_kin_jets_qqbar(incoming.begin(), incoming.end(),
partons.begin(), partons.end(),
param_.regulator_lambda);
}
if (ev.type()==event_type::extremal_qqbar_forward){
return tree_kin_jets_qqbar(incoming.rbegin(), incoming.rend(),
partons.rbegin(), partons.rend(),
param_.regulator_lambda);
}
if (ev.type()==event_type::central_qqbar){
return tree_kin_jets_qqbar_mid(incoming[0].type, incoming[1].type,
to_HepLorentzVector(incoming[0]),
to_HepLorentzVector(incoming[1]),
partons, param_.regulator_lambda);
}
throw std::logic_error("Cannot reweight non-resummable processes in Pure Jets");
}
namespace {
double tree_kin_W_FKL(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
std::vector<Particle> const & partons,
CLHEP::HepLorentzVector const & plbar, CLHEP::HepLorentzVector const & pl,
double lambda, ParticleProperties const & Wprop
){
auto p1 = to_HepLorentzVector(partons[0]);
auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder = cend(partons) - 1;
bool wc = aptype==partons[0].type; //leg b emits w
auto q0 = pa - p1;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_current(
aptype, bptype, pn, pb,
p1, pa, plbar, pl, wc, Wprop
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*ladder_factor;
}
template<class InIter, class partIter>
double tree_kin_W_uno(InIter BeginIn, partIter BeginPart,
partIter EndPart,
const CLHEP::HepLorentzVector & plbar,
const CLHEP::HepLorentzVector & pl,
double lambda, ParticleProperties const & Wprop
){
const auto pa = to_HepLorentzVector(*BeginIn);
const auto pb = to_HepLorentzVector(*(BeginIn+1));
const auto pg = to_HepLorentzVector(*BeginPart);
const auto p1 = to_HepLorentzVector(*(BeginPart+1));
const auto pn = to_HepLorentzVector(*(EndPart-1));
bool wc = (BeginIn)->type==(BeginPart+1)->type; //leg b emits w
auto q0 = pa - p1 - pg;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_uno_current(
(BeginIn)->type, (BeginIn+1)->type, pn, pb,
p1, pa, pg, plbar, pl, wc, Wprop
);
const double ladder_factor = FKL_ladder_weight(
BeginPart+2, EndPart-1,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*ladder_factor;
}
template<class InIter, class partIter>
double tree_kin_W_qqbar(InIter BeginIn, partIter BeginPart,
partIter EndPart,
const CLHEP::HepLorentzVector & plbar,
const CLHEP::HepLorentzVector & pl,
double lambda, ParticleProperties const & Wprop
){
const bool swap_qqbar=is_quark(*BeginPart);
const auto pa = to_HepLorentzVector(*BeginIn);
const auto pb = to_HepLorentzVector(*(BeginIn+1));
const auto pq = to_HepLorentzVector(*(BeginPart+(swap_qqbar?0:1)));
const auto pqbar = to_HepLorentzVector(*(BeginPart+(swap_qqbar?1:0)));
const auto p1 = to_HepLorentzVector(*(BeginPart));
const auto pn = to_HepLorentzVector(*(EndPart-1));
const bool wc = (BeginIn+1)->type!=(EndPart-1)->type; //leg b emits w
auto q0 = pa - pq - pqbar;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_qqbar_current(
(BeginIn)->type, (BeginIn+1)->type, pa, pb,
pq, pqbar, pn, plbar, pl, swap_qqbar, wc, Wprop
);
const double ladder_factor = FKL_ladder_weight(
BeginPart+2, EndPart-1,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*ladder_factor;
}
double tree_kin_W_qqbar_mid(
ParticleID aptype, ParticleID bptype,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
std::vector<Particle> const & partons,
CLHEP::HepLorentzVector const & plbar, CLHEP::HepLorentzVector const & pl,
double lambda, ParticleProperties const & Wprop
){
CLHEP::HepLorentzVector pq;
CLHEP::HepLorentzVector pqbar;
const auto backmidquark = std::find_if(
begin(partons)+1, end(partons)-1,
[](Particle const & s){ return s.type != pid::gluon; }
);
assert(backmidquark!=end(partons)-1);
if (is_quark(backmidquark->type)){
pq = to_HepLorentzVector(*backmidquark);
pqbar = to_HepLorentzVector(*(backmidquark+1));
}
else {
pqbar = to_HepLorentzVector(*backmidquark);
pq = to_HepLorentzVector(*(backmidquark+1));
}
auto p1 = to_HepLorentzVector(partons.front());
auto pn = to_HepLorentzVector(partons.back());
auto q0 = pa - p1;
// t-channel momentum after qqbar
auto qqbart = q0;
bool wqq = backmidquark->type != -(backmidquark+1)->type; // qqbar emit W
bool wc = !wqq && (aptype==partons.front().type); //leg b emits w
assert(!wqq || !wc);
if(wqq){ // emission from qqbar
qqbart -= pl + plbar;
} else if(!wc) { // emission from leg a
q0 -= pl + plbar;
qqbart -= pl + plbar;
}
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder_1 = (backmidquark);
const auto begin_ladder_2 = (backmidquark+2);
const auto end_ladder = cend(partons) - 1;
for(auto parton_it = begin_ladder; parton_it < begin_ladder_2; ++parton_it){
qqbart -= to_HepLorentzVector(*parton_it);
}
const int nabove = std::distance(begin_ladder, backmidquark);
const int nbelow = std::distance(begin_ladder_2, end_ladder);
std::vector<CLHEP::HepLorentzVector> partonsHLV;
partonsHLV.reserve(partons.size());
for (std::size_t i = 0; i != partons.size(); ++i) {
partonsHLV.push_back(to_HepLorentzVector(partons[i]));
}
const double current_factor = ME_W_qqbar_mid_current(
aptype, bptype, nabove, nbelow, pa, pb,
pq, pqbar, partonsHLV, plbar, pl, wqq, wc, Wprop
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder_1,
q0, pa, pb, p1, pn,
lambda
)*FKL_ladder_weight(
begin_ladder_2, end_ladder,
qqbart, pa, pb, p1, pn,
lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
} // namespace
double MatrixElement::tree_kin_W(Event const & ev) const {
using namespace event_type;
auto const & incoming(ev.incoming());
#ifndef NDEBUG
// assert that there is exactly one decay corresponding to the W
assert(ev.decays().size() == 1);
auto const & w_boson{
std::find_if(ev.outgoing().cbegin(), ev.outgoing().cend(),
[] (Particle const & p) -> bool {
return std::abs(p.type) == ParticleID::Wp;
}) };
assert(w_boson != ev.outgoing().cend());
assert( static_cast<long int>(ev.decays().cbegin()->first)
== std::distance(ev.outgoing().cbegin(), w_boson) );
#endif
// find decay products of W
auto const & decay{ ev.decays().cbegin()->second };
assert(decay.size() == 2);
assert( ( is_anylepton(decay.at(0)) && is_anyneutrino(decay.at(1)) )
|| ( is_anylepton(decay.at(1)) && is_anyneutrino(decay.at(0)) ) );
// get lepton & neutrino
CLHEP::HepLorentzVector plbar;
CLHEP::HepLorentzVector pl;
if (decay.at(0).type < 0){
plbar = to_HepLorentzVector(decay.at(0));
pl = to_HepLorentzVector(decay.at(1));
}
else{
pl = to_HepLorentzVector(decay.at(0));
plbar = to_HepLorentzVector(decay.at(1));
}
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
const auto partons = tag_extremal_jet_partons(ev);
if(ev.type() == FKL){
return tree_kin_W_FKL(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Wprop());
}
if(ev.type() == unordered_backward){
return tree_kin_W_uno(cbegin(incoming), cbegin(partons),
cend(partons), plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Wprop());
}
if(ev.type() == unordered_forward){
return tree_kin_W_uno(crbegin(incoming), crbegin(partons),
crend(partons), plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Wprop());
}
if(ev.type() == extremal_qqbar_backward){
return tree_kin_W_qqbar(cbegin(incoming), cbegin(partons),
cend(partons), plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Wprop());
}
if(ev.type() == extremal_qqbar_forward){
return tree_kin_W_qqbar(crbegin(incoming), crbegin(partons),
crend(partons), plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Wprop());
}
assert(ev.type() == central_qqbar);
return tree_kin_W_qqbar_mid(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Wprop());
}
namespace {
std::vector <double> tree_kin_Z_FKL(
const ParticleID aptype, const ParticleID bptype,
CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
std::vector<Particle> const & partons,
CLHEP::HepLorentzVector const & plbar, CLHEP::HepLorentzVector const & pl,
const double lambda, ParticleProperties const & Zprop,
const double stw2, const double ctw
){
const auto p1 = to_HepLorentzVector(partons[0]);
const auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder = cend(partons) - 1;
const std::vector <double> current_factor = ME_Z_current(
aptype, bptype, pn, pb, p1, pa,
plbar, pl, Zprop, stw2, ctw
);
std::vector <double> ladder_factor;
if(is_gluon(bptype)){
// This is a qg event
const auto q0 = pa-p1-plbar-pl;
ladder_factor.push_back(FKL_ladder_weight(begin_ladder, end_ladder,
q0, pa, pb, p1, pn, lambda));
} else if(is_gluon(aptype)){
// This is a gq event
const auto q0 = pa-p1;
ladder_factor.push_back(FKL_ladder_weight(begin_ladder, end_ladder,
q0, pa, pb, p1, pn, lambda));
} else {
// This is a qq event
const auto q0 = pa-p1-plbar-pl;
const auto q1 = pa-p1;
ladder_factor=FKL_ladder_weight_mix(begin_ladder, end_ladder,
q0, q1, pa, pb, p1, pn, lambda);
}
std::vector <double> result;
for(size_t i=0; i<current_factor.size(); ++i){
result.push_back(current_factor.at(i)*ladder_factor.at(i));
}
return result;
}
template<class InIter, class partIter>
std::vector <double> tree_kin_Z_uno(InIter BeginIn, partIter BeginPart, partIter EndPart,
const CLHEP::HepLorentzVector & plbar,
const CLHEP::HepLorentzVector & pl,
const double lambda, ParticleProperties const & Zprop,
const double stw2, const double ctw){
const auto pa = to_HepLorentzVector(*BeginIn);
const auto pb = to_HepLorentzVector(*(BeginIn+1));
const auto pg = to_HepLorentzVector(*BeginPart);
const auto p1 = to_HepLorentzVector(*(BeginPart+1));
const auto pn = to_HepLorentzVector(*(EndPart-1));
const ParticleID aptype = (BeginIn)->type;
const ParticleID bptype = (BeginIn+1)->type;
const std::vector <double> current_factor = ME_Z_uno_current(
aptype, bptype, pn, pb, p1, pa, pg,
plbar, pl, Zprop, stw2, ctw
);
std::vector <double> ladder_factor;
if(is_gluon(bptype)){
// This is a qg event
const auto q0 = pa-pg-p1-plbar-pl;
ladder_factor.push_back(FKL_ladder_weight(BeginPart+2, EndPart-1,
q0, pa, pb, p1, pn, lambda));
}else if(is_gluon(aptype)){
// This is a gq event
const auto q0 = pa-pg-p1;
ladder_factor.push_back(FKL_ladder_weight(BeginPart+2, EndPart-1,
q0, pa, pb, p1, pn, lambda));
}else{
// This is a qq event
const auto q0 = pa-pg-p1-plbar-pl;
const auto q1 = pa-pg-p1;
ladder_factor=FKL_ladder_weight_mix(BeginPart+2, EndPart-1,
q0, q1, pa, pb, p1, pn, lambda);
}
std::vector <double> result;
for(size_t i=0; i<current_factor.size(); ++i){
result.push_back(current_factor.at(i)*ladder_factor.at(i));
}
return result;
}
} // namespace
std::vector<double> MatrixElement::tree_kin_Z(Event const & ev) const {
using namespace event_type;
auto const & incoming(ev.incoming());
// find decay products of Z
auto const & decay{ ev.decays().cbegin()->second };
assert(decay.size() == 2);
assert(is_anylepton(decay.at(0)) && !is_anyneutrino(decay.at(0))
&& decay.at(0).type==-decay.at(1).type);
// get leptons
CLHEP::HepLorentzVector plbar;
CLHEP::HepLorentzVector pl;
if (decay.at(0).type < 0){
plbar = to_HepLorentzVector(decay.at(0));
pl = to_HepLorentzVector(decay.at(1));
}
else{
pl = to_HepLorentzVector(decay.at(0));
plbar = to_HepLorentzVector(decay.at(1));
}
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
const auto partons = tag_extremal_jet_partons(ev);
const double stw2 = param_.ew_parameters.sin2_tw();
const double ctw = param_.ew_parameters.cos_tw();
if(ev.type() == FKL){
return tree_kin_Z_FKL(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Zprop(),
stw2, ctw);
}
if(ev.type() == unordered_backward){
return tree_kin_Z_uno(cbegin(incoming), cbegin(partons),
cend(partons), plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Zprop(),
stw2, ctw);
}
if(ev.type() == unordered_forward){
return tree_kin_Z_uno(crbegin(incoming), crbegin(partons),
crend(partons), plbar, pl,
param_.regulator_lambda,
param_.ew_parameters.Zprop(),
stw2, ctw);
}
throw std::logic_error("Can only reweight FKL or uno processes in Z+Jets");
}
double MatrixElement::tree_kin_Higgs(Event const & ev) const {
- if(is_uno(ev.type())){
- return tree_kin_Higgs_between(ev);
- }
if(ev.outgoing().front().type == pid::Higgs){
return tree_kin_Higgs_first(ev);
}
if(ev.outgoing().back().type == pid::Higgs){
return tree_kin_Higgs_last(ev);
}
return tree_kin_Higgs_between(ev);
}
namespace {
// Colour acceleration multipliers, for gluons see eq. (7) in arXiv:0910.5113
-#ifdef HEJ_BUILD_WITH_QCDLOOP
double K(
ParticleID type,
CLHEP::HepLorentzVector const & pout,
CLHEP::HepLorentzVector const & pin
){
if(type == pid::gluon) return currents::K_g(pout, pin);
return C_F;
}
-#endif
- // Colour factor in strict MRK limit
- double K_MRK(ParticleID type) {
- return (type == pid::gluon)?C_A:C_F;
- }
} // namespace
- double MatrixElement::MH2_forwardH(
- CLHEP::HepLorentzVector const & p1out,
- CLHEP::HepLorentzVector const & p1in,
- ParticleID type2,
- CLHEP::HepLorentzVector const & p2out,
- CLHEP::HepLorentzVector const & p2in,
- CLHEP::HepLorentzVector const & pH,
- double t1, double t2
- ) const{
+ // kinetic matrix element square for backward Higgs emission
+ // cf. eq:ME_h_jets_peripheral in developer manual,
+ // but without factors \alpha_s and the FKL ladder
+ double MatrixElement::MH2_backwardH(
+ const ParticleID type_forward,
+ CLHEP::HepLorentzVector const & pa,
+ CLHEP::HepLorentzVector const & pb,
+ CLHEP::HepLorentzVector const & pH,
+ CLHEP::HepLorentzVector const & pn
+ ) const {
using namespace currents;
- ignore(p2out, p2in);
- const double shat = p1in.invariantMass2(p2in);
const double vev = param_.ew_parameters.vev();
- // gluon case
-#ifdef HEJ_BUILD_WITH_QCDLOOP
- if(!param_.Higgs_coupling.use_impact_factors){
- return K(type2, p2out, p2in)*C_A*1./(16*M_PI*M_PI)*t1/t2*ME_Houtside_gq(
- p1out, p1in, p2out, p2in, pH,
- param_.Higgs_coupling.mt, param_.Higgs_coupling.include_bottom,
- param_.Higgs_coupling.mb, vev
- )/(4*(N_C*N_C - 1));
- }
-#endif
- return K_MRK(type2)/C_A*9./2.*shat*shat*(
- C2gHgp(p1in,p1out,pH,vev) + C2gHgm(p1in,p1out,pH,vev)
- )/(t1*t2);
+ return K(type_forward, pn, pb)*ME_jgH_j(
+ pH, pa, pn, pb,
+ param_.Higgs_coupling.mt, param_.Higgs_coupling.include_bottom,
+ param_.Higgs_coupling.mb, vev
+ )/(4.*(N_C*N_C - 1)*(pa-pH).m2()*(pb-pn).m2());
+ }
+
+ // kinetic matrix element square for backward unordered emission
+ // and forward g -> Higgs
+ double MatrixElement::MH2_unob_forwardH(
+ CLHEP::HepLorentzVector const & pa,
+ CLHEP::HepLorentzVector const & pb,
+ CLHEP::HepLorentzVector const & pg,
+ CLHEP::HepLorentzVector const & p1,
+ CLHEP::HepLorentzVector const & pH
+ ) const {
+ using namespace currents;
+ const double vev = param_.ew_parameters.vev();
+
+ // Colour Acceleration Modifiers for quarks,
+ // see eq:K_q in developer manual
+ constexpr double K_f1 = C_F;
+
+ constexpr double nhel = 4.;
+
+ return K_f1*ME_juno_jgH(
+ pg, p1, pa, pH, pb,
+ param_.Higgs_coupling.mt, param_.Higgs_coupling.include_bottom,
+ param_.Higgs_coupling.mb, vev
+ )/(nhel*(N_C*N_C - 1)*(pa - p1 - pg).m2()*(pb - pH).m2());
}
double MatrixElement::tree_kin_Higgs_first(Event const & ev) const {
auto const & incoming = ev.incoming();
auto const & outgoing = ev.outgoing();
assert(outgoing.front().type == pid::Higgs);
- if(outgoing[1].type != pid::gluon) {
+
+ if(is_anyquark(incoming.front())) {
assert(incoming.front().type == outgoing[1].type);
return tree_kin_Higgs_between(ev);
}
- const auto pH = to_HepLorentzVector(outgoing.front());
- const auto partons = tag_extremal_jet_partons(
- ev
- );
- const auto pa = to_HepLorentzVector(incoming[0]);
- const auto pb = to_HepLorentzVector(incoming[1]);
+ const auto partons = tag_extremal_jet_partons(ev);
- const auto p1 = to_HepLorentzVector(partons.front());
- const auto pn = to_HepLorentzVector(partons.back());
+ const auto pa = to_HepLorentzVector(incoming.front());
+ const auto pb = to_HepLorentzVector(incoming.back());
- const auto q0 = pa - p1 - pH;
+ const auto pH = to_HepLorentzVector(outgoing.front());
- const double t1 = q0.m2();
- const double t2 = (pn - pb).m2();
+ const auto end_ladder = end(partons) - ((ev.type() == event_type::unof)?2:1);
+ const auto pn = to_HepLorentzVector(*end_ladder);
- return MH2_forwardH(
- p1, pa, incoming[1].type, pn, pb, pH,
- t1, t2
- )*FKL_ladder_weight(
- begin(partons) + 1, end(partons) - 1,
- q0, pa, pb, p1, pn,
+ const double ladder = FKL_ladder_weight(
+ begin(partons), end_ladder,
+ pa - pH, pa, pb, pH, pn,
param_.regulator_lambda
);
+
+ if(ev.type() == event_type::unof) {
+ const auto pg = to_HepLorentzVector(outgoing.back());
+ return MH2_unob_forwardH(
+ pb, pa, pg, pn, pH
+ )*ladder;
+ }
+
+ return MH2_backwardH(
+ incoming.back().type,
+ pa, pb, pH, pn
+ )*ladder;
}
double MatrixElement::tree_kin_Higgs_last(Event const & ev) const {
auto const & incoming = ev.incoming();
auto const & outgoing = ev.outgoing();
assert(outgoing.back().type == pid::Higgs);
- if(outgoing[outgoing.size()-2].type != pid::gluon) {
+
+ if(is_anyquark(incoming.back())) {
assert(incoming.back().type == outgoing[outgoing.size()-2].type);
return tree_kin_Higgs_between(ev);
}
- const auto pH = to_HepLorentzVector(outgoing.back());
- const auto partons = tag_extremal_jet_partons(
- ev
- );
- const auto pa = to_HepLorentzVector(incoming[0]);
- const auto pb = to_HepLorentzVector(incoming[1]);
+ const auto partons = tag_extremal_jet_partons(ev);
- auto p1 = to_HepLorentzVector(partons.front());
- const auto pn = to_HepLorentzVector(partons.back());
+ const auto pa = to_HepLorentzVector(incoming.front());
+ const auto pb = to_HepLorentzVector(incoming.back());
- auto q0 = pa - p1;
+ const auto pH = to_HepLorentzVector(outgoing.back());
- const double t1 = q0.m2();
- const double t2 = (pn + pH - pb).m2();
+ auto begin_ladder = begin(partons) + 1;
+ auto q0 = pa - to_HepLorentzVector(partons.front());
+ if(ev.type() == event_type::unob) {
+ q0 -= to_HepLorentzVector(*begin_ladder);
+ ++begin_ladder;
+ }
+ const auto p1 = to_HepLorentzVector(*(begin_ladder - 1));
- return MH2_forwardH(
- pn, pb, incoming[0].type, p1, pa, pH,
- t2, t1
- )*FKL_ladder_weight(
- begin(partons) + 1, end(partons) - 1,
- q0, pa, pb, p1, pn,
+ const double ladder = FKL_ladder_weight(
+ begin_ladder, end(partons),
+ q0, pa, pb, p1, pH,
param_.regulator_lambda
);
+
+ if(ev.type() == event_type::unob) {
+ const auto pg = to_HepLorentzVector(outgoing.front());
+ return MH2_unob_forwardH(
+ pa, pb, pg, p1, pH
+ )*ladder;
+ }
+
+ return MH2_backwardH(
+ incoming.front().type,
+ pb, pa, pH, p1
+ )*ladder;
}
namespace {
template<class InIter, class partIter>
double tree_kin_Higgs_uno(InIter BeginIn, InIter EndIn, partIter BeginPart,
partIter EndPart,
CLHEP::HepLorentzVector const & qH,
CLHEP::HepLorentzVector const & qHp1,
double mt, bool inc_bot, double mb, double vev
){
const auto pa = to_HepLorentzVector(*BeginIn);
const auto pb = to_HepLorentzVector(*(EndIn-1));
const auto pg = to_HepLorentzVector(*BeginPart);
const auto p1 = to_HepLorentzVector(*(BeginPart+1));
const auto pn = to_HepLorentzVector(*(EndPart-1));
return ME_Higgs_current_uno(
(BeginIn)->type, (EndIn-1)->type, pg, pn, pb, p1, pa,
qH, qHp1, mt, inc_bot, mb, vev
);
}
} // namespace
double MatrixElement::tree_kin_Higgs_between(Event const & ev) const {
using namespace event_type;
auto const & incoming = ev.incoming();
auto const & outgoing = ev.outgoing();
const auto the_Higgs = std::find_if(
begin(outgoing), end(outgoing),
[](Particle const & s){ return s.type == pid::Higgs; }
);
assert(the_Higgs != end(outgoing));
const auto pH = to_HepLorentzVector(*the_Higgs);
const auto partons = tag_extremal_jet_partons(ev);
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
auto p1 = to_HepLorentzVector(
partons[(ev.type() == unob)?1:0]
);
auto pn = to_HepLorentzVector(
partons[partons.size() - ((ev.type() == unof)?2:1)]
);
auto first_after_Higgs = begin(partons) + (the_Higgs-begin(outgoing));
assert(
(first_after_Higgs == end(partons) && (
(ev.type() == unob)
|| partons.back().type != pid::gluon
))
|| first_after_Higgs->rapidity() >= the_Higgs->rapidity()
);
assert(
(first_after_Higgs == begin(partons) && (
(ev.type() == unof)
|| partons.front().type != pid::gluon
))
|| (first_after_Higgs-1)->rapidity() <= the_Higgs->rapidity()
);
// always treat the Higgs as if it were in between the extremal FKL partons
if(first_after_Higgs == begin(partons)) ++first_after_Higgs;
else if(first_after_Higgs == end(partons)) --first_after_Higgs;
// t-channel momentum before Higgs
auto qH = pa;
for(auto parton_it = begin(partons); parton_it != first_after_Higgs; ++parton_it){
qH -= to_HepLorentzVector(*parton_it);
}
auto q0 = pa - p1;
auto begin_ladder = begin(partons) + 1;
auto end_ladder = end(partons) - 1;
double current_factor = NAN;
if(ev.type() == FKL){
current_factor = ME_Higgs_current(
incoming[0].type, incoming[1].type,
pn, pb, p1, pa, qH, qH - pH,
param_.Higgs_coupling.mt,
param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb,
param_.ew_parameters.vev()
);
}
else if(ev.type() == unob){
current_factor = C_A*C_A/2*tree_kin_Higgs_uno(
begin(incoming), end(incoming), begin(partons),
end(partons), qH, qH-pH, param_.Higgs_coupling.mt,
param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb,
param_.ew_parameters.vev()
);
const auto p_unob = to_HepLorentzVector(partons.front());
q0 -= p_unob;
p1 += p_unob;
++begin_ladder;
}
else if(ev.type() == unof){
current_factor = C_A*C_A/2*tree_kin_Higgs_uno(
rbegin(incoming), rend(incoming), rbegin(partons),
rend(partons), qH-pH, qH, param_.Higgs_coupling.mt,
param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb,
param_.ew_parameters.vev()
);
pn += to_HepLorentzVector(partons.back());
--end_ladder;
}
else{
throw std::logic_error("Can only reweight FKL or uno processes in H+Jets");
}
const double ladder_factor = FKL_ladder_weight(
begin_ladder, first_after_Higgs,
q0, pa, pb, p1, pn,
param_.regulator_lambda
)*FKL_ladder_weight(
first_after_Higgs, end_ladder,
qH - pH, pa, pb, p1, pn,
param_.regulator_lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
namespace {
double get_AWZH_coupling(Event const & ev, double alpha_s, double alpha_w) {
const auto AWZH_boson = std::find_if(
begin(ev.outgoing()), end(ev.outgoing()),
[](auto const & p){return is_AWZH_boson(p);}
);
if(AWZH_boson == end(ev.outgoing())) return 1.;
switch(AWZH_boson->type){
case pid::Higgs:
return alpha_s*alpha_s;
case pid::Wp:
case pid::Wm:
case pid::Z_photon_mix:
return alpha_w*alpha_w;
// TODO
case pid::photon:
case pid::Z:
default:
throw not_implemented("Emission of boson of unsupported type");
}
}
} // namespace
double MatrixElement::tree_param(Event const & ev, double mur) const {
assert(is_resummable(ev.type()));
const auto begin_partons = ev.begin_partons();
const auto end_partons = ev.end_partons();
const auto num_partons = std::distance(begin_partons, end_partons);
const double alpha_s = alpha_s_(mur);
const double gs2 = 4.*M_PI*alpha_s;
double res = std::pow(gs2, num_partons);
if(param_.log_correction){
// use alpha_s(q_perp), evolved to mur
assert(num_partons >= 2);
const auto first_emission = std::next(begin_partons);
const auto last_emission = std::prev(end_partons);
for(auto parton = first_emission; parton != last_emission; ++parton){
res *= 1. + alpha_s/(2.*M_PI)*BETA0*std::log(mur/parton->perp());
}
}
return get_AWZH_coupling(ev, alpha_s, param_.ew_parameters.alpha_w())*res;
}
} // namespace HEJ
diff --git a/src/PhaseSpacePoint.cc b/src/PhaseSpacePoint.cc
index 7282592..3f549cb 100644
--- a/src/PhaseSpacePoint.cc
+++ b/src/PhaseSpacePoint.cc
@@ -1,925 +1,955 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/PhaseSpacePoint.hh"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <functional>
#include <iterator>
#include <limits>
#include <numeric>
#include <random>
#include <tuple>
#include "fastjet/ClusterSequence.hh"
#include "fastjet/JetDefinition.hh"
#include "HEJ/Constants.hh"
#include "HEJ/Event.hh"
#include "HEJ/JetSplitter.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/RNG.hh"
#include "HEJ/event_types.hh"
#include "HEJ/kinematics.hh"
#include "HEJ/resummation_jet.hh"
#include "HEJ/utility.hh"
namespace HEJ {
namespace {
constexpr int MAX_JET_USER_IDX = PhaseSpacePoint::NG_MAX;
bool is_nonjet_parton(fastjet::PseudoJet const & parton){
assert(parton.user_index() != -1);
return parton.user_index() > MAX_JET_USER_IDX;
}
bool is_jet_parton(fastjet::PseudoJet const & parton){
assert(parton.user_index() != -1);
return parton.user_index() <= MAX_JET_USER_IDX;
}
namespace user_idx {
//! user indices for partons with extremal rapidity
enum ID: int {
qqbar_mid1 = -9,
qqbar_mid2 = -8,
qqbarb = -7,
qqbarf = -6,
unob = -5,
unof = -4,
backward_fkl = -3,
forward_fkl = -2,
};
} // namespace user_idx
using UID = user_idx::ID;
double phase_space_normalisation(
int num_Born_jets, int num_out_partons
){
return std::pow(16.*std::pow(M_PI,3), num_Born_jets - num_out_partons);
}
} // namespace
Event::EventData to_EventData(PhaseSpacePoint psp){
Event::EventData result;
result.incoming = std::move(psp).incoming_; // NOLINT(bugprone-use-after-move)
result.outgoing = std::move(psp).outgoing_; // NOLINT(bugprone-use-after-move)
// technically Event::EventData doesn't have to be sorted,
// but PhaseSpacePoint should be anyway
assert(
std::is_sorted(
begin(result.outgoing), end(result.outgoing),
rapidity_less{}
)
);
assert(result.outgoing.size() >= 2);
static_assert(
std::numeric_limits<double>::has_quiet_NaN,
"no quiet NaN for double"
);
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
result.decays = std::move(psp).decays_; // NOLINT(bugprone-use-after-move)
result.parameters.central = {nan, nan, psp.weight()}; // NOLINT(bugprone-use-after-move)
return result;
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::cluster_jets(
std::vector<fastjet::PseudoJet> const & partons
) const{
fastjet::ClusterSequence cs(partons, param_.jet_param.def);
return sorted_by_rapidity(cs.inclusive_jets(param_.jet_param.min_pt));
}
bool PhaseSpacePoint::pass_resummation_cuts(
std::vector<fastjet::PseudoJet> const & jets
) const{
return cluster_jets(jets).size() == jets.size();
}
namespace {
// find iterators to central qqbar emission
auto get_central_qqbar(Event const & ev) {
// find born quarks (ignore extremal partons)
auto const firstquark = std::find_if(
std::next(ev.begin_partons()), std::prev(ev.end_partons(), 2),
[](Particle const & s){ return (is_anyquark(s)); }
);
// assert that it is a q-q_bar pair.
assert(std::distance(firstquark, ev.end_partons()) != 2);
assert(
( is_quark(*firstquark) && is_antiquark(*std::next(firstquark)) )
|| ( is_antiquark(*firstquark) && is_quark(*std::next(firstquark)) )
);
return std::make_pair(firstquark, std::next(firstquark));
}
//! returns index of most backward q-qbar jet
template<class Iterator>
int get_back_quark_jet(Event const & ev, Iterator firstquark){
// find jets at FO corresponding to the quarks
// technically this isn't necessary for LO
std::vector<int> const born_indices{ ev.particle_jet_indices() };
const auto firstquark_idx = std::distance(ev.begin_partons(), firstquark);
int const firstjet_idx = born_indices[firstquark_idx];
assert(firstjet_idx>0);
assert( born_indices[firstquark_idx+1] == firstjet_idx+1 );
return firstjet_idx;
}
//! returns index of most backward q-qbar jet
int getBackQuarkJet(Event const & ev){
const auto firstquark = get_central_qqbar(ev).first;
return get_back_quark_jet(ev, firstquark);
}
} // namespace
double PhaseSpacePoint::estimate_emission_rapidity_range(
Event const & ev
) const {
assert(std::is_sorted(begin(ev.jets()), end(ev.jets()), rapidity_less{}));
- double delta_y =
- most_forward_FKL(ev.jets()).rapidity()
- - most_backward_FKL(ev.jets()).rapidity();
+ const double ymin = is_backward_g_to_h(ev)?
+ ev.outgoing().front().rapidity():
+ most_backward_FKL(ev.jets()).rapidity();
+ const double ymax = is_forward_g_to_h(ev)?
+ ev.outgoing().back().rapidity():
+ most_forward_FKL(ev.jets()).rapidity();
+ double delta_y = ymax - ymin;
// neglect tiny probability for emission between central qqbar pair
if(ev.type() == event_type::central_qqbar) {
const int qjet = getBackQuarkJet(ev);
delta_y -= ev.jets()[qjet+1].rapidity() - ev.jets()[qjet].rapidity();
}
assert(delta_y >= 0);
return delta_y;
}
double PhaseSpacePoint::estimate_ng_mean(Event const & ev) const {
// Formula derived from fit in arXiv:1805.04446 (see Fig. 2)
constexpr double GLUONS_PER_RAPIDITY = 0.975052;
return GLUONS_PER_RAPIDITY*estimate_emission_rapidity_range(ev);
}
int PhaseSpacePoint::sample_ng(Event const & event, RNG & ran){
const double ng_mean = estimate_ng_mean(event);
std::poisson_distribution<int> dist(ng_mean);
const int ng = dist(ran);
assert(ng >= 0);
assert(ng < NG_MAX);
weight_ *= std::tgamma(ng + 1)*std::exp(ng_mean)*std::pow(ng_mean, -ng);
return ng;
}
void PhaseSpacePoint::boost_AWZH_boson_from(
fastjet::PseudoJet const & boosted_boson, Event const & event
){
auto const & from = event.outgoing();
const auto original_boson = std::find_if(
begin(from), end(from),
[](Particle const & p){ return is_AWZH_boson(p); }
);
if(original_boson == end(from)) return;
auto insertion_point = std::lower_bound(
begin(outgoing_), end(outgoing_), *original_boson, rapidity_less{}
);
// copy AWZH particle
outgoing_.insert(insertion_point,
{original_boson->type, boosted_boson, original_boson->colour}
);
assert(std::is_sorted(begin(outgoing_), end(outgoing_), rapidity_less{}));
// copy & boost decay products
const int idx = std::distance(begin(from), original_boson);
assert(idx >= 0);
const auto decay_it = event.decays().find(idx);
if(decay_it == end(event.decays()))
return;
const int new_idx = std::distance(begin(outgoing_), insertion_point);
assert(new_idx >= 0);
assert(outgoing_[new_idx].type == original_boson->type);
auto decayparticles=decay_it->second;
// change the momenta of the decay products.
for(auto & particle: decayparticles){
auto & p = particle.p;
// boost _to_ rest frame of input boson
p.unboost(original_boson->p);
// then boost _from_ rest frame of shuffled boson
p.boost(boosted_boson);
}
decays_.emplace(new_idx, decayparticles);
}
namespace {
template<class ConstIterator, class Iterator>
void label_extremal_qqbar(
ConstIterator born_begin, ConstIterator born_end,
Iterator first_out
){
// find born quarks
const auto firstquark = std::find_if(
born_begin, born_end-1,
[](Particle const & s){ return (is_anyquark(s)); }
);
assert(firstquark != born_end-1);
const auto secondquark = std::find_if(
firstquark+1, born_end,
[](Particle const & s){ return (is_anyquark(s)); }
);
assert(secondquark != born_end);
assert( ( is_quark(*firstquark) && is_antiquark(*secondquark) )
|| ( is_antiquark(*firstquark) && is_quark(*secondquark) ));
assert(first_out->type == ParticleID::gluon);
assert((first_out+1)->type == ParticleID::gluon);
// copy type from born
first_out->type = firstquark->type;
(first_out+1)->type = secondquark->type;
}
} // namespace
void PhaseSpacePoint::label_qqbar(Event const & event){
assert(std::is_sorted(begin(outgoing_), end(outgoing_), rapidity_less{}));
assert(filter_partons(outgoing_).size() == outgoing_.size());
if(qqbarb_){
label_extremal_qqbar(event.outgoing().cbegin(), event.outgoing().cend(),
outgoing_.begin() );
return;
}
if(qqbarf_){ // same as qqbarb with reversed order
label_extremal_qqbar( event.outgoing().crbegin(), event.outgoing().crend(),
outgoing_.rbegin() );
return;
}
// central qqbar
const auto firstquark = get_central_qqbar(event).first;
// find jets at FO corresponding to the quarks
// technically this isn't necessary for LO
const auto firstjet_idx = get_back_quark_jet(event, firstquark);
// find corresponding jets after resummation
fastjet::ClusterSequence cs{to_PseudoJet(outgoing_), param_.jet_param.def};
auto const jets = fastjet::sorted_by_rapidity(
cs.inclusive_jets( param_.jet_param.min_pt ));
std::vector<int> const resum_indices{ cs.particle_jet_indices({jets}) };
// assert that jets didn't move
assert(nearby_ep( ( event.jets().cbegin()+firstjet_idx )->rapidity(),
jets[ firstjet_idx ].rapidity(), 1e-2) );
assert(nearby_ep( ( event.jets().cbegin()+firstjet_idx+1 )->rapidity(),
jets[ firstjet_idx+1 ].rapidity(), 1e-2) );
// find last partons in first (central) jet
size_t idx_out = 0;
for(size_t i=resum_indices.size()-2; i>0; --i)
if(resum_indices[i] == firstjet_idx){
idx_out = i;
break;
}
assert(idx_out != 0);
// check that there is sufficient pt in jets from the quarks
const double minpartonjetpt = 1. - param_.soft_pt_regulator;
if (outgoing_[idx_out].p.pt()<minpartonjetpt*( event.jets().cbegin()+firstjet_idx )->pt()){
weight_=0.;
status_ = StatusCode::wrong_jets;
return;
}
if (outgoing_[idx_out+1].p.pt()<minpartonjetpt*( event.jets().cbegin()+firstjet_idx+1 )->pt()){
weight_=0.;
status_ = StatusCode::wrong_jets;
return;
}
// check that no additional emission between jets
// such configurations are possible if we have an gluon gets generated
// inside the rapidities of the qqbar chain, but clusted to a
// differnet/outside jet. Changing this is non trivial
if(resum_indices[idx_out+1] != resum_indices[idx_out]+1){
weight_=0.;
status_ = StatusCode::gluon_in_qqbar;
return;
}
outgoing_[idx_out].type = firstquark->type;
outgoing_[idx_out+1].type = std::next(firstquark)->type;
}
void PhaseSpacePoint::label_quarks(Event const & ev){
const auto WZEmit = std::find_if(
begin(ev.outgoing()), end(ev.outgoing()),
[](Particle const & s){ return (std::abs(s.type) == pid::Wp || s.type == pid::Z_photon_mix); }
);
if (WZEmit != end(ev.outgoing())){
if(!qqbarb_) {
const size_t backward_FKL_idx = unob_?1:0;
const auto backward_FKL = std::next(ev.begin_partons(), backward_FKL_idx);
outgoing_[backward_FKL_idx].type = backward_FKL->type;
}
if(!qqbarf_) {
const size_t forward_FKL_idx = unof_?1:0;
const auto forward_FKL = std::prev(ev.end_partons(), 1+forward_FKL_idx);
outgoing_.rbegin()[unof_].type = forward_FKL->type; // NOLINT
}
} else {
- most_backward_FKL(outgoing_).type = ev.incoming().front().type;
- most_forward_FKL(outgoing_).type = ev.incoming().back().type;
+ if(!is_backward_g_to_h(ev)) {
+ most_backward_FKL(outgoing_).type = ev.incoming().front().type;
+ }
+ if(!is_forward_g_to_h(ev)) {
+ most_forward_FKL(outgoing_).type = ev.incoming().back().type;
+ }
}
if(qqbar_mid_||qqbarb_||qqbarf_){
label_qqbar(ev);
}
}
PhaseSpacePoint::PhaseSpacePoint(
Event const & ev, PhaseSpacePointConfig conf, RNG & ran
):
unob_{ev.type() == event_type::unob},
unof_{ev.type() == event_type::unof},
qqbarb_{ev.type() == event_type::qqbar_exb},
qqbarf_{ev.type() == event_type::qqbar_exf},
qqbar_mid_{ev.type() == event_type::qqbar_mid},
param_{std::move(conf)},
status_{unspecified}
{
// legacy code: override new variable with old
if(param_.max_ext_soft_pt_fraction){
param_.soft_pt_regulator = *param_.max_ext_soft_pt_fraction;
param_.max_ext_soft_pt_fraction = {};
}
weight_ = 1;
auto const & Born_jets = ev.jets();
const int ng = sample_ng(ev, ran);
weight_ /= std::tgamma(ng + 1);
const int ng_jets = sample_ng_jets(ev, ng, ran);
std::vector<fastjet::PseudoJet> out_partons = gen_non_jet(
ng - ng_jets, CMINPT, param_.jet_param.min_pt, ran
);
- int qqbar_backjet(-1);
- if(qqbar_mid_){
- qqbar_backjet = getBackQuarkJet(ev);
- }
-
- // reshuffle soft momenta
const auto qperp = std::accumulate(
begin(out_partons), end(out_partons),
fastjet::PseudoJet{}
);
std::vector<fastjet::PseudoJet> jets;
optional<fastjet::PseudoJet> boson;
std::tie(jets, boson) = reshuffle(ev, qperp);
if(weight_ == 0.) {
status_ = failed_reshuffle;
return;
}
if(! pass_resummation_cuts(jets)){
status_ = failed_resummation_cuts;
weight_ = 0.;
return;
}
// split jets in multiple partons
std::vector<fastjet::PseudoJet> jet_partons = split(
- jets, ng_jets, qqbar_backjet, ran
+ ev, jets, ng_jets, ran
);
if(weight_ == 0.) {
status_ = StatusCode::failed_split;
return;
}
+
+ const double ymin = is_backward_g_to_h(ev)?
+ ev.outgoing().front().rapidity():
+ most_backward_FKL(jet_partons).rapidity()
+ ;
+ const double ymax = is_forward_g_to_h(ev)?
+ ev.outgoing().back().rapidity():
+ most_forward_FKL(jet_partons).rapidity()
+ ;
if(qqbar_mid_){
+ const int qqbar_backjet = getBackQuarkJet(ev);
rescale_qqbar_rapidities(
out_partons, jets,
- most_backward_FKL(jet_partons).rapidity(),
- most_forward_FKL(jet_partons).rapidity(),
+ ymin, ymax,
qqbar_backjet
- );
+ );
}
else{
- rescale_rapidities(
- out_partons,
- most_backward_FKL(jet_partons).rapidity(),
- most_forward_FKL(jet_partons).rapidity()
- );
+ rescale_rapidities(out_partons, ymin, ymax);
}
if(! cluster_jets(out_partons).empty()){
weight_ = 0.;
status_ = StatusCode::empty_jets;
return;
}
std::sort(begin(out_partons), end(out_partons), rapidity_less{});
assert(
std::is_sorted(begin(jet_partons), end(jet_partons), rapidity_less{})
);
const auto first_jet_parton = out_partons.insert(
end(out_partons), begin(jet_partons), end(jet_partons)
);
std::inplace_merge(
begin(out_partons), first_jet_parton, end(out_partons), rapidity_less{}
);
- if(! jets_ok(Born_jets, out_partons)){
+ if(! jets_ok(ev, out_partons)){
weight_ = 0.;
status_ = StatusCode::wrong_jets;
return;
}
weight_ *= phase_space_normalisation(Born_jets.size(), out_partons.size());
outgoing_.reserve(out_partons.size() + 1); // one slot for possible A, W, Z, H
for( auto it = std::make_move_iterator(out_partons.begin());
it != std::make_move_iterator(out_partons.end());
++it
){
outgoing_.emplace_back( Particle{pid::gluon, *it, {}});
}
assert(!outgoing_.empty());
label_quarks(ev);
if(weight_ == 0.) {
//! @TODO optimise s.t. this is not possible
// status is handled internally
return;
}
// reattach boson & decays
if(boson){
boost_AWZH_boson_from(*boson, ev);
}
reconstruct_incoming(ev.incoming());
status_ = StatusCode::good;
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::gen_non_jet(
int const ng_non_jet, double const ptmin, double const ptmax, RNG & ran
){
// heuristic parameters for pt sampling
const double ptpar = 1.3 + ng_non_jet/5.;
const double temp1 = std::atan((ptmax - ptmin)/ptpar);
std::vector<fastjet::PseudoJet> partons(ng_non_jet);
for(int i = 0; i < ng_non_jet; ++i){
const double r1 = ran.flat();
const double pt = ptmin + ptpar*std::tan(r1*temp1);
const double temp2 = std::cos(r1*temp1);
const double phi = 2*M_PI*ran.flat();
weight_ *= 2.0*M_PI*pt*ptpar*temp1/(temp2*temp2);
// we don't know the allowed rapidity span yet,
// set a random value to be rescaled later on
const double y = ran.flat();
partons[i].reset_PtYPhiM(pt, y, phi);
// Set user index higher than any jet-parton index
// in order to assert that these are not inside jets
partons[i].set_user_index(i + 1 + NG_MAX);
assert(ptmin-1e-5 <= partons[i].pt() && partons[i].pt() <= ptmax+1e-5);
}
assert(std::all_of(partons.cbegin(), partons.cend(), is_nonjet_parton));
return sorted_by_rapidity(partons);
}
void PhaseSpacePoint::rescale_qqbar_rapidities(
std::vector<fastjet::PseudoJet> & out_partons,
std::vector<fastjet::PseudoJet> const & jets,
const double ymin1, const double ymax2,
const int qqbar_backjet
){
const double ymax1 = jets[qqbar_backjet].rapidity();
const double ymin2 = jets[qqbar_backjet+1].rapidity();
constexpr double ep = 1e-7;
const double tot_y = ymax1 - ymin1 + ymax2 - ymin2;
std::vector<std::reference_wrapper<fastjet::PseudoJet>> refpart(
out_partons.begin(), out_partons.end());
double ratio = (ymax1 - ymin1)/tot_y;
const auto gap{ std::find_if(refpart.begin(), refpart.end(),
[ratio](fastjet::PseudoJet const & p){
return (p.rapidity()>=ratio);} ) };
double ymin = ymin1;
double ymax = ymax1;
double dy = ymax - ymin - 2*ep;
double offset = 0.;
for(auto it_part=refpart.begin(); it_part<refpart.end(); ++it_part){
if(it_part == gap){
ymin = ymin2;
ymax = ymax2;
dy = ymax - ymin - 2*ep;
offset = ratio;
ratio = 1-ratio;
}
fastjet::PseudoJet & part = *it_part;
assert(offset <= part.rapidity() && part.rapidity() < ratio+offset);
const double y = ymin + ep + dy*((part.rapidity()-offset)/ratio);
part.reset_momentum_PtYPhiM(part.pt(), y, part.phi());
weight_ *= tot_y-4.*ep;
assert(ymin <= part.rapidity() && part.rapidity() <= ymax);
}
assert(is_sorted(begin(out_partons), end(out_partons), rapidity_less{}));
}
void PhaseSpacePoint::rescale_rapidities(
std::vector<fastjet::PseudoJet> & partons,
double ymin, double ymax
){
constexpr double ep = 1e-7;
for(auto & parton: partons){
assert(0 <= parton.rapidity() && parton.rapidity() <= 1);
const double dy = ymax - ymin - 2*ep;
const double y = ymin + ep + dy*parton.rapidity();
parton.reset_momentum_PtYPhiM(parton.pt(), y, parton.phi());
weight_ *= dy;
assert(ymin <= parton.rapidity() && parton.rapidity() <= ymax);
}
}
namespace {
template<typename T, typename... Rest>
auto min(T const & a, T const & b, Rest&&... r) {
using std::min;
return min(a, min(b, std::forward<Rest>(r)...));
}
}
double PhaseSpacePoint::probability_in_jet(Event const & ev) const{
const double dy = estimate_emission_rapidity_range(ev);
const double R = param_.jet_param.def.R();
// jets into which we predominantly emit
- const auto njets = ev.jets().size() - unof_ - unob_ - qqbarb_ - qqbarf_; //NOLINT
- assert(njets >= 2);
- const double p_J_y_large = (njets-1.)*R*R/(2.*dy);
+ const int njets = ev.jets().size() - unof_ - unob_ - qqbarb_ - qqbarf_; //NOLINT
+ assert(njets >= 1);
+ const size_t nextremal_jets = std::min(njets, 2);
+ const double p_J_y_large = (njets - nextremal_jets/2.)*R*R/(2.*dy);
const double p_J_y0 = njets*R/M_PI;
return min(p_J_y_large, p_J_y0, 1.);
}
int PhaseSpacePoint::sample_ng_jets(Event const & event, int ng, RNG & ran){
const double p_J = probability_in_jet(event);
std::binomial_distribution<> bin_dist(ng, p_J);
const int ng_J = bin_dist(ran);
weight_ *= std::pow(p_J, -ng_J)*std::pow(1 - p_J, ng_J - ng);
return ng_J;
}
std::pair< std::vector<fastjet::PseudoJet>,
optional<fastjet::PseudoJet> >
PhaseSpacePoint::reshuffle(
Event const & ev,
fastjet::PseudoJet const & q
){
// Create a copy of the outgoing momenta not containing decay products
std::vector<fastjet::PseudoJet const *> born_momenta;
born_momenta.reserve(ev.jets().size());
std::transform(ev.jets().cbegin(), ev.jets().cend(),
back_inserter(born_momenta),
[](fastjet::PseudoJet const & t) { return &t; });
// check if there is one (or more) bosons in the event.
const auto AWZH_boson = std::find_if(
begin(ev.outgoing()), end(ev.outgoing()),
[](Particle const & p){ return is_AWZH_boson(p); }
);
optional<fastjet::PseudoJet> boson;
if(AWZH_boson != end(ev.outgoing())){
boson = AWZH_boson->p;
}
// reshuffle all momenta
if(q == fastjet::PseudoJet{0, 0, 0, 0}) return {ev.jets(), boson};
// add boson to reshuffling
if(boson) {
born_momenta.push_back(&*boson);
}
auto shuffle_momenta = resummation_jet_momenta(born_momenta, q);
if(shuffle_momenta.empty()){
weight_ = 0;
return {};
}
// additional Jacobian to ensure Born integration over delta gives 1
weight_ *= resummation_jet_weight(born_momenta, q);
// take out boson again
optional<fastjet::PseudoJet> shuffle_boson;
if(boson){
shuffle_boson = std::move(shuffle_momenta.back());
shuffle_momenta.pop_back();
}
return {shuffle_momenta, shuffle_boson};
}
std::vector<int> PhaseSpacePoint::distribute_jet_partons(
int ng_jets, std::vector<fastjet::PseudoJet> const & jets, RNG & ran
){
size_t first_valid_jet = 0;
size_t num_valid_jets = jets.size();
const double R_eff = 5./3.*param_.jet_param.def.R();
// if there is an unordered jet too far away from the FKL jets
// then extra gluon constituents of the unordered jet would
// violate the FKL rapidity ordering
if((unob_||qqbarb_) && jets[0].delta_R(jets[1]) > R_eff){
++first_valid_jet;
--num_valid_jets;
}
else if((unof_||qqbarf_) && jets[jets.size()-1].delta_R(jets[jets.size()-2]) > R_eff){
--num_valid_jets;
}
std::vector<int> np(jets.size(), 1);
for(int i = 0; i < ng_jets; ++i){
++np[first_valid_jet + ran.flat() * num_valid_jets];
}
weight_ *= std::pow(num_valid_jets, ng_jets);
return np;
}
#ifndef NDEBUG
namespace {
bool tagged_FKL_backward(
std::vector<fastjet::PseudoJet> const & jet_partons
){
return std::find_if(
begin(jet_partons), end(jet_partons),
[](fastjet::PseudoJet const & p){
return p.user_index() == UID::backward_fkl;
}
) != end(jet_partons);
}
bool tagged_FKL_forward(
std::vector<fastjet::PseudoJet> const & jet_partons
){
// the most forward FKL parton is most likely near the end of jet_partons;
// start search from there
return std::find_if(
jet_partons.rbegin(), jet_partons.rend(),
[](fastjet::PseudoJet const & p){
return p.user_index() == UID::forward_fkl;
}
) != jet_partons.rend();
}
- bool tagged_FKL_extremal(
- std::vector<fastjet::PseudoJet> const & jet_partons
- ){
- return tagged_FKL_backward(jet_partons) && tagged_FKL_forward(jet_partons);
- }
-
} // namespace
#endif
std::vector<fastjet::PseudoJet> PhaseSpacePoint::split(
- std::vector<fastjet::PseudoJet> const & jets,
- int ng_jets, size_t qqbar_backjet, RNG & ran
+ Event const & Born_event,
+ std::vector<fastjet::PseudoJet> const & jets,
+ int ng_jets
+ , RNG & ran
){
return split(
- jets, distribute_jet_partons(ng_jets, jets, ran), qqbar_backjet, ran);
+ Born_event,
+ jets,
+ distribute_jet_partons(ng_jets, jets, ran),
+ ran
+ );
}
bool PhaseSpacePoint::pass_extremal_cuts(
fastjet::PseudoJet const & ext_parton,
fastjet::PseudoJet const & jet
) const{
if(ext_parton.pt() < param_.min_extparton_pt) return false;
return (ext_parton - jet).pt()/jet.pt() < param_.soft_pt_regulator;
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::split(
- std::vector<fastjet::PseudoJet> const & jets,
- std::vector<int> const & np,
- size_t qqbar_backjet,
- RNG & ran
+ Event const & Born_event,
+ std::vector<fastjet::PseudoJet> const & jets,
+ std::vector<int> const & np,
+ RNG & ran
){
assert(! jets.empty());
assert(jets.size() == np.size());
assert(pass_resummation_cuts(jets));
-
- const size_t most_backward_FKL_idx = 0 + unob_ + qqbarb_; // NOLINT
- const size_t most_forward_FKL_idx = jets.size() - 1 - unof_ - qqbarf_; // NOLINT
+ constexpr auto no_such_jet_idx = std::numeric_limits<std::size_t>::max();
+
+ const size_t most_backward_FKL_idx = is_backward_g_to_h(Born_event)?
+ no_such_jet_idx: // we have backward Higgs instead of FKL jet
+ (0 + unob_ + qqbarb_); // NOLINT
+ const size_t most_forward_FKL_idx = is_forward_g_to_h(Born_event)?
+ no_such_jet_idx: // we have forward Higgs instead of FKL jet
+ (jets.size() - 1 - unof_ - qqbarf_); // NOLINT
+ const size_t qqbar_jet_idx = qqbar_mid_?
+ getBackQuarkJet(Born_event):
+ no_such_jet_idx;
auto const & jet = param_.jet_param;
const JetSplitter jet_splitter{jet.def, jet.min_pt};
std::vector<fastjet::PseudoJet> jet_partons;
// randomly distribute jet gluons among jets
for(size_t i = 0; i < jets.size(); ++i){
auto split_res = jet_splitter.split(jets[i], np[i], ran);
weight_ *= split_res.weight;
if(weight_ == 0) return {};
assert(
std::all_of(
begin(split_res.constituents), end(split_res.constituents),
is_jet_parton
)
);
const auto first_new_parton = jet_partons.insert(
end(jet_partons),
begin(split_res.constituents), end(split_res.constituents)
);
// mark uno and extremal FKL emissions here so we can check
// their position once all emissions are generated
// also mark qqbar_mid partons, and apply appropriate pt cut.
auto extremal = end(jet_partons);
if (i == most_backward_FKL_idx){ //FKL backward emission
extremal = std::min_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
extremal->set_user_index(UID::backward_fkl);
}
else if(((unob_ || qqbarb_) && i == 0)){
// unordered/qqbarb
extremal = std::min_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
extremal->set_user_index((unob_)?UID::unob:UID::qqbarb);
}
else if (i == most_forward_FKL_idx){
extremal = std::max_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
extremal->set_user_index(UID::forward_fkl);
}
else if(((unof_ || qqbarf_) && i == jets.size() - 1)){
// unordered/qqbarf
extremal = std::max_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
extremal->set_user_index((unof_)?UID::unof:UID::qqbarf);
}
- else if((qqbar_mid_ && i == qqbar_backjet)){
+ else if((qqbar_mid_ && i == qqbar_jet_idx)){
extremal = std::max_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
extremal->set_user_index(UID::qqbar_mid1);
}
- else if((qqbar_mid_ && i == qqbar_backjet+1)){
+ else if((qqbar_mid_ && i == qqbar_jet_idx+1)){
extremal = std::min_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
extremal->set_user_index(UID::qqbar_mid2);
}
if(
extremal != end(jet_partons)
&& !pass_extremal_cuts(*extremal, jets[i])
){
weight_ = 0;
return {};
}
}
- assert(tagged_FKL_extremal(jet_partons));
+ assert(is_backward_g_to_h(Born_event) || tagged_FKL_backward(jet_partons));
+ assert(is_forward_g_to_h(Born_event) || tagged_FKL_forward(jet_partons));
std::sort(begin(jet_partons), end(jet_partons), rapidity_less{});
if(
- !extremal_ok(jet_partons)
+ !extremal_ok(Born_event, jet_partons)
|| !split_preserved_jets(jets, jet_partons)
){
weight_ = 0.;
return {};
}
return jet_partons;
}
bool PhaseSpacePoint::extremal_ok(
- std::vector<fastjet::PseudoJet> const & partons
+ Event const & Born_event,
+ std::vector<fastjet::PseudoJet> const & partons
) const{
assert(std::is_sorted(begin(partons), end(partons), rapidity_less{}));
if(unob_ && partons.front().user_index() != UID::unob) return false;
if(unof_ && partons.back().user_index() != UID::unof) return false;
if(qqbarb_ && partons.front().user_index() != UID::qqbarb) return false;
if(qqbarf_ && partons.back().user_index() != UID::qqbarf) return false;
- return
- most_backward_FKL(partons).user_index() == UID::backward_fkl
- && most_forward_FKL(partons).user_index() == UID::forward_fkl;
+ if(is_backward_g_to_h(Born_event)) {
+ if(partons.front().rapidity() < Born_event.outgoing().front().rapidity()){
+ return false;
+ }
+ } else if(most_backward_FKL(partons).user_index() != UID::backward_fkl) {
+ return false;
+ }
+ if(is_forward_g_to_h(Born_event)) {
+ return partons.back().rapidity() <= Born_event.outgoing().back().rapidity();
+ }
+ return most_forward_FKL(partons).user_index() == UID::forward_fkl;
}
bool PhaseSpacePoint::split_preserved_jets(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<fastjet::PseudoJet> const & jet_partons
) const{
assert(std::is_sorted(begin(jets), end(jets), rapidity_less{}));
const auto split_jets = cluster_jets(jet_partons);
// this can happen if two overlapping jets
// are both split into more than one parton
if(split_jets.size() != jets.size()) return false;
for(size_t i = 0; i < split_jets.size(); ++i){
// this can happen if there are two overlapping jets
// and a parton is assigned to the "wrong" jet
if(!nearby_ep(jets[i].rapidity(), split_jets[i].rapidity(), 1e-2)){
return false;
}
}
return true;
}
template<class Particle>
Particle const & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> const & partons
) const{
return partons[0 + unob_ + qqbarb_];
}
template<class Particle>
Particle const & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> const & partons
) const{
const size_t idx = partons.size() - 1 - unof_ - qqbarf_;
assert(idx < partons.size());
return partons[idx];
}
template<class Particle>
Particle & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> & partons
) const{
return partons[0 + unob_ + qqbarb_];
}
template<class Particle>
Particle & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> & partons
) const{
const size_t idx = partons.size() - 1 - unof_ - qqbarf_;
assert(idx < partons.size());
return partons[idx];
}
bool PhaseSpacePoint::contains_idx(
fastjet::PseudoJet const & jet, fastjet::PseudoJet const & parton
) const {
auto const & constituents = jet.constituents();
const int idx = parton.user_index();
const bool injet = std::find_if(
begin(constituents), end(constituents),
[idx](fastjet::PseudoJet const & con){return con.user_index() == idx;}
) != end(constituents);
const double minpartonjetpt = 1. - param_.soft_pt_regulator;
return ((parton.pt()>minpartonjetpt*jet.pt())&&injet);
}
bool PhaseSpacePoint::jets_ok(
- std::vector<fastjet::PseudoJet> const & Born_jets,
- std::vector<fastjet::PseudoJet> const & partons
+ Event const & Born_event,
+ std::vector<fastjet::PseudoJet> const & partons
) const{
fastjet::ClusterSequence cs(partons, param_.jet_param.def);
const auto jets = sorted_by_rapidity(cs.inclusive_jets(param_.jet_param.min_pt));
- if(jets.size() != Born_jets.size()) return false;
+ if(jets.size() != Born_event.jets().size()) return false;
int in_jet = 0;
for(auto const & jet : jets){
assert(jet.has_constituents());
for(auto && parton: jet.constituents()){
if(is_nonjet_parton(parton)) return false;
}
in_jet += jet.constituents().size();
}
const int expect_in_jet = std::count_if(
partons.cbegin(), partons.cend(), is_jet_parton
);
if(in_jet != expect_in_jet) return false;
// note that PseudoJet::contains does not work here
- if(! (
- contains_idx(most_backward_FKL(jets), most_backward_FKL(partons))
- && contains_idx(most_forward_FKL(jets), most_forward_FKL(partons))
- )) return false;
+ if(
+ !is_backward_g_to_h(Born_event) &&
+ !contains_idx(most_backward_FKL(jets), most_backward_FKL(partons))
+ ) return false;
+ if(
+ !is_forward_g_to_h(Born_event)
+ && !contains_idx(most_forward_FKL(jets), most_forward_FKL(partons))
+ ) return false;
if(unob_ && !contains_idx(jets.front(), partons.front())) return false;
if(qqbarb_ && !contains_idx(jets.front(), partons.front())) return false;
if(unof_ && !contains_idx(jets.back(), partons.back())) return false;
if(qqbarf_ && !contains_idx(jets.back(), partons.back())) return false;
#ifndef NDEBUG
for(size_t i = 0; i < jets.size(); ++i){
- assert(nearby_ep(jets[i].rapidity(), Born_jets[i].rapidity(), 1e-2));
+ assert(nearby_ep(jets[i].rapidity(), Born_event.jets()[i].rapidity(), 1e-2));
}
#endif
return true;
}
void PhaseSpacePoint::reconstruct_incoming(
std::array<Particle, 2> const & Born_incoming
){
std::tie(incoming_[0].p, incoming_[1].p) = incoming_momenta(outgoing_);
for(size_t i = 0; i < incoming_.size(); ++i){
incoming_[i].type = Born_incoming[i].type;
}
assert(momentum_conserved());
}
bool PhaseSpacePoint::momentum_conserved() const{
fastjet::PseudoJet diff;
for(auto const & in: incoming()) diff += in.p;
const double norm = diff.E();
for(auto const & out: outgoing()) diff -= out.p;
return nearby(diff, fastjet::PseudoJet{}, norm);
}
} //namespace HEJ
diff --git a/src/YAMLreader.cc b/src/YAMLreader.cc
index 4e66832..b6a9073 100644
--- a/src/YAMLreader.cc
+++ b/src/YAMLreader.cc
@@ -1,574 +1,574 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/YAMLreader.hh"
#include <algorithm>
#include <iostream>
#include <limits>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
#include <dlfcn.h>
#include "HEJ/ConfigFlags.hh"
#include "HEJ/Constants.hh"
#include "HEJ/ScaleFunction.hh"
#include "HEJ/event_types.hh"
#include "HEJ/output_formats.hh"
namespace HEJ {
class Event;
namespace {
//! Get YAML tree of supported options
/**
* The configuration file is checked against this tree of options
* in assert_all_options_known.
*/
YAML::Node const & get_supported_options(){
const static YAML::Node supported = [](){
YAML::Node supported;
static const auto opts = {
"trials", "min extparton pt", "max ext soft pt fraction",
"soft pt regulator",
"scales", "scale factors", "max scale ratio", "import scales",
"log correction", "event output", "analysis", "analyses", "vev",
"regulator parameter", "max events"
};
// add subnodes to "supported" - the assigned value is irrelevant
for(auto && opt: opts) supported[opt] = "";
for(auto && jet_opt: {"min pt", "algorithm", "R"}){
supported["resummation jets"][jet_opt] = "";
supported["fixed order jets"][jet_opt] = "";
}
for(auto && opt: {"mt", "use impact factors", "include bottom", "mb"}){
supported["Higgs coupling"][opt] = "";
}
for(auto && opt: {"name", "seed"}){
supported["random generator"][opt] = "";
}
for(auto && opt: {"FKL", "unordered", "extremal qqbar", "central qqbar", "non-resummable"}){
supported["event treatment"][opt] = "";
}
for(auto && particle_type: {"Higgs", "W", "Z"}){
for(auto && particle_opt: {"mass", "width"}){
supported["particle properties"][particle_type][particle_opt] = "";
}
}
for(auto && opt: {"type", "trials", "max deviation"}){
supported["unweight"][opt] = "";
}
return supported;
}();
return supported;
}
fastjet::JetAlgorithm to_JetAlgorithm(std::string const & algo){
using namespace fastjet;
static const std::map<std::string, fastjet::JetAlgorithm> known = {
{"kt", kt_algorithm},
{"cambridge", cambridge_algorithm},
{"antikt", antikt_algorithm},
{"cambridge for passive", cambridge_for_passive_algorithm},
{"plugin", plugin_algorithm}
};
const auto res = known.find(algo);
if(res == known.end()){
throw std::invalid_argument("Unknown jet algorithm \"" + algo + "\"");
}
return res->second;
}
EventTreatment to_EventTreatment(std::string const & name){
static const std::map<std::string, EventTreatment> known = {
{"reweight", EventTreatment::reweight},
{"keep", EventTreatment::keep},
{"discard", EventTreatment::discard}
};
const auto res = known.find(name);
if(res == known.end()){
throw std::invalid_argument("Unknown event treatment \"" + name + "\"");
}
return res->second;
}
WeightType to_weight_type(std::string const & setting){
if(setting == "weighted")
return WeightType::weighted;
if(setting =="resummation")
return WeightType::unweighted_resum;
if(setting =="partial")
return WeightType::partially_unweighted;
throw std::invalid_argument{"Unknown weight type \"" + setting + "\""};
}
} // namespace
namespace detail{
void set_from_yaml(fastjet::JetAlgorithm & setting, YAML::Node const & yaml){
setting = to_JetAlgorithm(yaml.as<std::string>());
}
void set_from_yaml(EventTreatment & setting, YAML::Node const & yaml){
setting = to_EventTreatment(yaml.as<std::string>());
}
void set_from_yaml(ParticleID & setting, YAML::Node const & yaml){
setting = to_ParticleID(yaml.as<std::string>());
}
void set_from_yaml(WeightType & setting, YAML::Node const & yaml){
setting = to_weight_type(yaml.as<std::string>());
}
} // namespace detail
JetParameters get_jet_parameters(
YAML::Node const & node,
std::string const & entry
){
assert(node);
JetParameters result;
fastjet::JetAlgorithm jet_algo = fastjet::antikt_algorithm;
double R = NAN;
set_from_yaml_if_defined(jet_algo, node, entry, "algorithm");
set_from_yaml(R, node, entry, "R");
result.def = fastjet::JetDefinition{jet_algo, R};
set_from_yaml(result.min_pt, node, entry, "min pt");
return result;
}
RNGConfig to_RNGConfig(
YAML::Node const & node,
std::string const & entry
){
assert(node);
RNGConfig result;
set_from_yaml(result.name, node, entry, "name");
set_from_yaml_if_defined(result.seed, node, entry, "seed");
return result;
}
ParticleProperties get_particle_properties(
YAML::Node const & node, std::string const & entry,
std::string const & boson
){
ParticleProperties result{};
set_from_yaml(result.mass, node, entry, boson, "mass");
set_from_yaml(result.width, node, entry, boson, "width");
return result;
}
EWConstants get_ew_parameters(YAML::Node const & node){
EWConstants result;
double vev = NAN;
set_from_yaml(vev, node, "vev");
result.set_vevWZH(vev,
get_particle_properties(node, "particle properties", "W"),
get_particle_properties(node, "particle properties", "Z"),
get_particle_properties(node, "particle properties", "Higgs")
);
return result;
}
HiggsCouplingSettings get_Higgs_coupling(
YAML::Node const & node,
std::string const & entry
){
assert(node);
static constexpr double mt_max = 2e4;
#ifndef HEJ_BUILD_WITH_QCDLOOP
if(node[entry].IsDefined()){
throw std::invalid_argument{
"Higgs coupling settings require building HEJ 2 "
"with QCDloop support"
};
}
#endif
HiggsCouplingSettings settings;
set_from_yaml_if_defined(settings.mt, node, entry, "mt");
set_from_yaml_if_defined(settings.mb, node, entry, "mb");
set_from_yaml_if_defined(settings.include_bottom, node, entry, "include bottom");
set_from_yaml_if_defined(settings.use_impact_factors, node, entry, "use impact factors");
if(settings.use_impact_factors){
if(settings.mt != std::numeric_limits<double>::infinity()){
throw std::invalid_argument{
"Conflicting settings: "
"impact factors may only be used in the infinite top mass limit"
};
}
}
else{
// huge values of the top mass are numerically unstable
settings.mt = std::min(settings.mt, mt_max);
}
return settings;
}
FileFormat to_FileFormat(std::string const & name){
static const std::map<std::string, FileFormat> known = {
{"Les Houches", FileFormat::Les_Houches},
{"HepMC", FileFormat::HepMC},
{"HepMC2", FileFormat::HepMC2},
{"HepMC3", FileFormat::HepMC3},
{"HDF5", FileFormat::HDF5}
};
const auto res = known.find(name);
if(res == known.end()){
throw std::invalid_argument("Unknown file format \"" + name + "\"");
}
return res->second;
}
std::string extract_suffix(std::string const & filename){
size_t separator = filename.rfind('.');
if(separator == std::string::npos) return {};
return filename.substr(separator + 1);
}
FileFormat format_from_suffix(std::string const & filename){
const std::string suffix = extract_suffix(filename);
if(suffix == "lhe") return FileFormat::Les_Houches;
if(suffix == "hepmc") return FileFormat::HepMC;
if(suffix == "hepmc3") return FileFormat::HepMC3;
if(suffix == "hepmc2") return FileFormat::HepMC2;
if(suffix == "hdf5") return FileFormat::HDF5;
throw std::invalid_argument{
"Can't determine format for output file \"" + filename + "\""
};
}
void assert_all_options_known(
YAML::Node const & conf, YAML::Node const & supported
){
if(!conf.IsMap()) return;
if(!supported.IsMap()) throw invalid_type{"must not have sub-entries"};
for(auto const & entry: conf){
const auto name = entry.first.as<std::string>();
if(! supported[name]) throw unknown_option{name};
/* check sub-options, e.g. 'resummation jets: min pt'
* we don't check analyses sub-options
* those depend on the analysis being used and should be checked there
* similar for "import scales"
*/
if(name != "analyses" && name != "analysis" && name != "import scales"){
try{
assert_all_options_known(conf[name], supported[name]);
}
catch(unknown_option const & ex){
throw unknown_option{name + ": " + ex.what()};
}
catch(invalid_type const & ex){
throw invalid_type{name + ": " + ex.what()};
}
}
}
}
} // namespace HEJ
namespace YAML {
Node convert<HEJ::OutputFile>::encode(HEJ::OutputFile const & outfile) {
Node node;
node[to_string(outfile.format)] = outfile.name;
return node;
}
bool convert<HEJ::OutputFile>::decode(Node const & node, HEJ::OutputFile & out) {
switch(node.Type()){
case NodeType::Map: {
YAML::const_iterator it = node.begin();
out.format = HEJ::to_FileFormat(it->first.as<std::string>());
out.name = it->second.as<std::string>();
return true;
}
case NodeType::Scalar:
out.name = node.as<std::string>();
out.format = HEJ::format_from_suffix(out.name);
return true;
default:
return false;
}
}
} // namespace YAML
namespace HEJ {
namespace detail{
void set_from_yaml(OutputFile & setting, YAML::Node const & yaml){
setting = yaml.as<OutputFile>();
}
}
namespace {
void update_fixed_order_jet_parameters(
JetParameters & fixed_order_jets, YAML::Node const & yaml
){
if(!yaml["fixed order jets"]) return;
set_from_yaml_if_defined(
fixed_order_jets.min_pt, yaml, "fixed order jets", "min pt"
);
fastjet::JetAlgorithm algo = fixed_order_jets.def.jet_algorithm();
set_from_yaml_if_defined(algo, yaml, "fixed order jets", "algorithm");
double R = fixed_order_jets.def.R();
set_from_yaml_if_defined(R, yaml, "fixed order jets", "R");
fixed_order_jets.def = fastjet::JetDefinition{algo, R};
}
// like std::stod, but throw if not the whole string can be converted
double to_double(std::string const & str){
std::size_t pos = 0;
const double result = std::stod(str, &pos);
if(pos < str.size()){
throw std::invalid_argument(str + " is not a valid double value");
}
return result;
}
using EventScale = double (*)(Event const &);
void import_scale_functions(
std::string const & file,
std::vector<std::string> const & scale_names,
std::unordered_map<std::string, EventScale> & known
) {
void * handle = dlopen(file.c_str(), RTLD_NOW);
char * error = dlerror();
if(error != nullptr) throw std::runtime_error{error};
for(auto const & scale: scale_names) {
void * sym = dlsym(handle, scale.c_str());
error = dlerror();
if(error != nullptr) throw std::runtime_error{error};
known.emplace(scale, reinterpret_cast<EventScale>(sym)); // NOLINT
}
}
auto get_scale_map(
YAML::Node const & yaml
) {
std::unordered_map<std::string, EventScale> scale_map;
scale_map.emplace("H_T", H_T);
scale_map.emplace("max jet pperp", max_jet_pt);
scale_map.emplace("jet invariant mass", jet_invariant_mass);
scale_map.emplace("m_j1j2", m_j1j2);
if(yaml["import scales"].IsDefined()) {
if(! yaml["import scales"].IsMap()) {
throw invalid_type{"Entry 'import scales' is not a map"};
}
for(auto const & import: yaml["import scales"]) {
const auto file = import.first.as<std::string>();
const auto scale_names =
import.second.IsSequence()
?import.second.as<std::vector<std::string>>()
:std::vector<std::string>{import.second.as<std::string>()};
import_scale_functions(file, scale_names, scale_map);
}
}
return scale_map;
}
// simple (as in non-composite) scale functions
/**
* An example for a simple scale function would be H_T,
* H_T/2 is then composite (take H_T and then divide by 2)
*/
ScaleFunction parse_simple_ScaleFunction(
std::string const & scale_fun,
std::unordered_map<std::string, EventScale> const & known
) {
assert(
scale_fun.empty() ||
(!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
);
const auto it = known.find(scale_fun);
if(it != end(known)) return {it->first, it->second};
try{
const double scale = to_double(scale_fun);
return {scale_fun, FixedScale{scale}};
} catch(std::invalid_argument const &){}
throw std::invalid_argument{"Unknown scale choice: \"" + scale_fun + "\""};
}
std::string trim_front(std::string const & str){
const auto new_begin = std::find_if(
begin(str), end(str), [](char c){ return std::isspace(c) == 0; }
);
return std::string(new_begin, end(str));
}
std::string trim_back(std::string str){
size_t pos = str.size() - 1;
// use guaranteed wrap-around behaviour to check whether we have
// traversed the whole string
for(; pos < str.size() && std::isspace(str[pos]); --pos) {}
str.resize(pos + 1); // note that pos + 1 can be 0
return str;
}
ScaleFunction parse_ScaleFunction(
std::string const & scale_fun,
std::unordered_map<std::string, EventScale> const & known
){
assert(
scale_fun.empty() ||
(!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
);
// parse from right to left => a/b/c gives (a/b)/c
const size_t delim = scale_fun.find_last_of("*/");
if(delim == std::string::npos){
return parse_simple_ScaleFunction(scale_fun, known);
}
const std::string first = trim_back(std::string{scale_fun, 0, delim});
const std::string second = trim_front(std::string{scale_fun, delim+1});
if(scale_fun[delim] == '/'){
return parse_ScaleFunction(first, known)
/ parse_ScaleFunction(second, known);
}
assert(scale_fun[delim] == '*');
return parse_ScaleFunction(first, known)
* parse_ScaleFunction(second, known);
}
EventTreatMap get_event_treatment(
YAML::Node const & node, std::string const & entry
){
using namespace event_type;
EventTreatMap treat {
- {no_2_jets, EventTreatment::discard},
+ {not_enough_jets, EventTreatment::discard},
{bad_final_state, EventTreatment::discard},
{FKL, EventTreatment::discard},
{unob, EventTreatment::discard},
{unof, EventTreatment::discard},
{qqbar_exb, EventTreatment::discard},
{qqbar_exf, EventTreatment::discard},
{qqbar_mid, EventTreatment::discard},
{non_resummable, EventTreatment::discard}
};
set_from_yaml(treat.at(FKL), node, entry, "FKL");
set_from_yaml(treat.at(unob), node, entry, "unordered");
treat.at(unof) = treat.at(unob);
set_from_yaml(treat.at(qqbar_exb), node, entry, "extremal qqbar");
treat.at(qqbar_exf) = treat.at(qqbar_exb);
set_from_yaml(treat.at(qqbar_mid), node, entry, "central qqbar");
set_from_yaml(treat.at(non_resummable), node, entry, "non-resummable");
if(treat[non_resummable] == EventTreatment::reweight){
throw std::invalid_argument{"Cannot reweight non-resummable events"};
}
return treat;
}
Config to_Config(YAML::Node const & yaml){
try{
assert_all_options_known(yaml, get_supported_options());
}
catch(unknown_option const & ex){
throw unknown_option{std::string{"Unknown option '"} + ex.what() + "'"};
}
Config config;
config.resummation_jets = get_jet_parameters(yaml, "resummation jets");
config.fixed_order_jets = config.resummation_jets;
update_fixed_order_jet_parameters(config.fixed_order_jets, yaml);
set_from_yaml_if_defined(config.min_extparton_pt, yaml, "min extparton pt");
if(config.min_extparton_pt!=0)
std::cerr << "WARNING: \"min extparton pt\" is deprecated."
<< " Please remove this entry or set \"soft pt regulator\" instead.\n";
set_from_yaml_if_defined(
config.max_ext_soft_pt_fraction, yaml, "max ext soft pt fraction"
);
if(config.max_ext_soft_pt_fraction){
std::cerr << "WARNING: \"max ext soft pt fraction\" is deprecated."
<< " Please remove this entry or set \"soft pt regulator\" instead.\n";
config.soft_pt_regulator = *config.max_ext_soft_pt_fraction;
} else {
set_from_yaml_if_defined(
config.soft_pt_regulator, yaml, "soft pt regulator"
);
}
// Sets the standard value, then changes this if defined
config.regulator_lambda=CLAMBDA;
set_from_yaml_if_defined(config.regulator_lambda, yaml, "regulator parameter");
set_from_yaml_if_defined(config.max_events, yaml, "max events");
set_from_yaml(config.trials, yaml, "trials");
config.weight_type = WeightType::weighted;
set_from_yaml_if_defined(config.weight_type, yaml, "unweight", "type");
if(config.weight_type == WeightType::partially_unweighted) {
config.unweight_config = PartialUnweightConfig{};
set_from_yaml(
config.unweight_config->trials, yaml,
"unweight", "trials"
);
set_from_yaml(
config.unweight_config->max_dev, yaml,
"unweight", "max deviation"
);
}
else if(yaml["unweight"].IsDefined()) {
for(auto && opt: {"trials", "max deviation"}) {
if(yaml["unweight"][opt].IsDefined()) {
throw std::invalid_argument{
"'unweight: " + std::string{opt} + "' "
"is only supported if 'unweight: type' is set to 'partial'"
};
}
}
}
set_from_yaml(config.log_correction, yaml, "log correction");
config.treat = get_event_treatment(yaml, "event treatment");
set_from_yaml_if_defined(config.output, yaml, "event output");
config.rng = to_RNGConfig(yaml, "random generator");
set_from_yaml_if_defined(config.analyses_parameters, yaml, "analyses");
if(yaml["analysis"].IsDefined()){
std::cerr <<
"WARNING: Configuration entry 'analysis' is deprecated. "
" Use 'analyses' instead.\n";
set_from_yaml(config.analysis_parameters, yaml, "analysis");
if(!config.analysis_parameters.IsNull()){
config.analyses_parameters.push_back(config.analysis_parameters);
}
}
config.scales = to_ScaleConfig(yaml);
config.ew_parameters = get_ew_parameters(yaml);
config.Higgs_coupling = get_Higgs_coupling(yaml, "Higgs coupling");
return config;
}
} // namespace
ScaleConfig to_ScaleConfig(YAML::Node const & yaml){
ScaleConfig config;
auto scale_funs = get_scale_map(yaml);
std::vector<std::string> scales;
set_from_yaml(scales, yaml, "scales");
config.base.reserve(scales.size());
std::transform(
begin(scales), end(scales), std::back_inserter(config.base),
[scale_funs](auto const & entry){
return parse_ScaleFunction(entry, scale_funs);
}
);
set_from_yaml_if_defined(config.factors, yaml, "scale factors");
config.max_ratio = std::numeric_limits<double>::infinity();
set_from_yaml_if_defined(config.max_ratio, yaml, "max scale ratio");
return config;
}
Config load_config(std::string const & config_file){
try{
return to_Config(YAML::LoadFile(config_file));
}
catch(...){
std::cerr << "Error reading " << config_file << ":\n ";
throw;
}
}
} // namespace HEJ
diff --git a/t/CMakeLists.txt b/t/CMakeLists.txt
index 53cdf2f..5628f91 100644
--- a/t/CMakeLists.txt
+++ b/t/CMakeLists.txt
@@ -1,505 +1,533 @@
set(tst_dir "${CMAKE_CURRENT_SOURCE_DIR}")
set(tst_ME_data_dir "${tst_dir}/ME_data")
# small library for common test functions
add_library(hej_test SHARED hej_test.cc)
target_include_directories(hej_test PUBLIC ${tst_dir})
target_link_libraries(hej_test HEJ)
# test event classification
# test explicit configurations
add_executable(test_classify ${tst_dir}/test_classify.cc)
target_compile_options(test_classify PRIVATE "-O0") # avoid compiler optimisation
target_link_libraries(test_classify HEJ hej_test)
add_test(
NAME classify
COMMAND test_classify
)
# test against reference data
add_executable(test_classify_ref ${tst_dir}/test_classify_ref.cc)
target_link_libraries(test_classify_ref HEJ hej_test)
add_test(
NAME classify_ref
COMMAND test_classify_ref ${tst_dir}/classify_ref ${tst_dir}/classify.lhe.gz
)
add_test(
NAME classify_ref_4j
COMMAND test_classify_ref ${tst_dir}/classify_ref_4j ${tst_dir}/4j.lhe.gz
)
add_test(
NAME classify_ref_W4j
COMMAND test_classify_ref
${tst_dir}/classify_ref_W4j
${tst_dir}/MGemnubar4j_unweighted.lhe.gz
)
add_test(
NAME t_classify_ref_Z4j
COMMAND test_classify_ref
${tst_dir}/classify_ref_Z4j
${tst_dir}/Z_4j.lhe.gz
)
# test for valid W decays
add_executable(test_decay ${tst_dir}/test_decay.cc)
target_link_libraries(test_decay HEJ hej_test)
add_test(
NAME valid_decay
COMMAND test_decay
)
# test valid jet cuts on tagging jets
add_executable(test_jet_cuts ${tst_dir}/test_jet_cuts.cc)
target_link_libraries(test_jet_cuts HEJ hej_test)
add_test(
NAME jet_cuts
COMMAND test_jet_cuts
)
# test phase space point
add_executable(test_psp ${tst_dir}/test_psp.cc)
target_link_libraries(test_psp HEJ hej_test)
add_test(
NAME PhaseSpace
COMMAND test_psp ${tst_dir}/psp_gen.lhe.gz
)
# test importing analyses
file(COPY "${tst_dir}/analysis_config.yml" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
set(test_config "${CMAKE_CURRENT_BINARY_DIR}/analysis_config.yml")
get_target_property(ANALYSIS_PATH AnalysisTemplate_lib BINARY_DIR)
get_target_property(ANALYSIS_LIB AnalysisTemplate_lib OUTPUT_NAME)
set(ANALYSIS_PARAMETERS "")
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - plugin: ${ANALYSIS_PATH}/lib${ANALYSIS_LIB}.so\n ${ANALYSIS_PARAMETERS}\n")
configure_file( ${tst_dir}/analysis_config_single.yml.in
analysis_config_simple.yml @ONLY )
add_test(
NAME analysis_simple
COMMAND $<TARGET_FILE:HEJ_main>
analysis_config_simple.yml
${tst_dir}/2j.lhe.gz
)
get_target_property(ANALYSIS_PATH AnalysisPrint_lib BINARY_DIR)
get_target_property(ANALYSIS_LIB AnalysisPrint_lib OUTPUT_NAME)
set(ANALYSIS_PARAMETERS " output: ana_output")
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - plugin: ${ANALYSIS_PATH}/lib${ANALYSIS_LIB}.so\n ${ANALYSIS_PARAMETERS}\n")
configure_file( ${tst_dir}/analysis_config_single.yml.in
analysis_config_print.yml @ONLY )
add_test(
NAME analysis_print
COMMAND $<TARGET_FILE:HEJ_main>
analysis_config_print.yml
${tst_dir}/2j.lhe.gz
)
if(ROOT_FOUND)
get_target_property(ANALYSIS_PATH AnalysisROOT_lib BINARY_DIR)
get_target_property(ANALYSIS_LIB AnalysisROOT_lib OUTPUT_NAME)
set(ANALYSIS_PARAMETERS "")
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - plugin: ${ANALYSIS_PATH}/lib${ANALYSIS_LIB}.so\n ${ANALYSIS_PARAMETERS}\n")
configure_file( ${tst_dir}/analysis_config_single.yml.in
analysis_config_root.yml @ONLY )
add_test(
NAME analysis_root
COMMAND $<TARGET_FILE:HEJ_main>
analysis_config_root.yml
${tst_dir}/2j.lhe.gz
)
endif()
if(RIVET_FOUND)
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - rivet: MC_XS\n output: ana_rivet\n")
endif()
add_test(
NAME analysis_all
COMMAND $<TARGET_FILE:HEJ_main>
${test_config}
${tst_dir}/2j.lhe.gz
)
# test importing scales (from examples/softestptScale)
add_executable(test_scale_import ${tst_dir}/test_scale_import)
target_link_libraries(test_scale_import HEJ)
get_target_property(SCALE_PATH softestptScale_lib BINARY_DIR)
get_target_property(SCALE_LIB softestptScale_lib OUTPUT_NAME)
set(SCALE_NAME "softest_jet_pt")
configure_file( ${tst_dir}/jet_config_with_import.yml.in
jet_config_with_import.yml @ONLY )
add_test(
NAME scale_import
COMMAND test_scale_import jet_config_with_import.yml
)
# test scale arithmetic (e.g. 2*H_T/4)
add_executable(test_scale_arithmetics ${tst_dir}/test_scale_arithmetics)
target_link_libraries(test_scale_arithmetics HEJ hej_test)
add_test(
NAME scale_arithmetics
COMMAND test_scale_arithmetics ${tst_dir}/jet_config.yml ${tst_dir}/2j.lhe.gz
)
# test "ParameterDescription"
add_executable(test_descriptions ${tst_dir}/test_descriptions)
target_link_libraries(test_descriptions HEJ hej_test)
add_test(
NAME descriptions
COMMAND test_descriptions
)
# test "EventParameters*Weight"
add_executable(test_parameters ${tst_dir}/test_parameters)
target_link_libraries(test_parameters HEJ hej_test)
add_test(
NAME parameters
COMMAND test_parameters
)
# test Particle IDs
add_executable(test_pid ${tst_dir}/test_pid)
target_link_libraries(test_pid HEJ hej_test)
add_test(
NAME pid
COMMAND test_pid
)
# test EW constants
add_executable(test_EWConstants ${tst_dir}/test_EWConstants)
target_link_libraries(test_EWConstants HEJ hej_test)
add_test(
NAME EWConstants
COMMAND test_EWConstants
)
# test unweighting
add_executable(test_unweighter ${tst_dir}/test_unweighter)
target_link_libraries(test_unweighter HEJ hej_test)
add_test(
NAME unweighter
COMMAND test_unweighter ${tst_dir}/4j.lhe.gz
)
# test colour generation
add_executable(test_colours ${tst_dir}/test_colours)
target_link_libraries(test_colours HEJ hej_test)
add_test(
NAME colour_flow
COMMAND test_colours
)
add_executable(test_colours2 ${tst_dir}/test_colours2)
target_link_libraries(test_colours2 HEJ hej_test)
add_test(
NAME colour_flow2
COMMAND test_colours2
)
# test matrix elements
add_executable(test_ME_generic ${tst_dir}/test_ME_generic.cc)
target_link_libraries(test_ME_generic HEJ hej_test)
add_test(
NAME ME_j
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml
${tst_ME_data_dir}/ME_jets_tree.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz
)
add_test(
NAME ME_j_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml
${tst_ME_data_dir}/ME_jets_tree_virt.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz
)
add_test(
NAME ME_h
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml
${tst_ME_data_dir}/ME_h_mtinf_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
)
add_test(
+ NAME ME_hj
+ COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml
+ ${tst_ME_data_dir}/ME_hj_mtinf_tree.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz
+ )
+add_test(
NAME ME_h_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml
${tst_ME_data_dir}/ME_h_mtinf_virt.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
)
+add_test(
+ NAME ME_hj_virt
+ COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml
+ ${tst_ME_data_dir}/ME_hj_mtinf_virt.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz
+ )
if(QCDloop_FOUND)
add_test(
NAME ME_h_mt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mt.yml
${tst_ME_data_dir}/ME_h_mt_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
)
add_test(
NAME ME_h_mtmb
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtmb.yml
${tst_ME_data_dir}/ME_h_mtmb_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
)
+ add_test(
+ NAME ME_hj_mt
+ COMMAND test_ME_generic ${tst_ME_data_dir}/config_mt.yml
+ ${tst_ME_data_dir}/ME_hj_mt_tree.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz
+ )
+ add_test(
+ NAME ME_hj_mtmb
+ COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtmb.yml
+ ${tst_ME_data_dir}/ME_hj_mtmb_tree.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz
+ )
endif()
add_test(
NAME ME_j_subl
COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml
${tst_ME_data_dir}/ME_jets_subl_tree.dat ${tst_ME_data_dir}/PSP_jets_subl.lhe.gz
)
add_test(
NAME ME_j_subl_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml
${tst_ME_data_dir}/ME_jets_subl_tree_virt.dat ${tst_ME_data_dir}/PSP_jets_subl.lhe.gz
)
add_test(
NAME ME_j_subl_4j
COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml
${tst_ME_data_dir}/ME_jets_subl_tree_new.dat ${tst_dir}/4j.lhe.gz
)
add_test(
NAME ME_j_subl_4j_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml
${tst_ME_data_dir}/ME_jets_subl_tree_new_virt.dat ${tst_dir}/4j.lhe.gz
)
add_test(
NAME ME_w_FKL
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml
${tst_ME_data_dir}/ME_w_FKL_tree.dat ${tst_ME_data_dir}/PSP_w_FKL.lhe.gz
)
add_test(
NAME ME_w_FKL_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml
${tst_ME_data_dir}/ME_w_FKL_virt.dat ${tst_ME_data_dir}/PSP_w_FKL.lhe.gz
)
add_test(
NAME ME_Wp
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml
${tst_ME_data_dir}/ME_Wp.dat ${tst_ME_data_dir}/PSP_Wp.lhe.gz
)
add_test(
NAME ME_Wp_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml
${tst_ME_data_dir}/ME_Wp_virt.dat ${tst_ME_data_dir}/PSP_Wp.lhe.gz
)
add_test(
NAME ME_Wm
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml
${tst_ME_data_dir}/ME_Wm.dat ${tst_ME_data_dir}/PSP_Wm.lhe.gz
)
add_test(
NAME ME_Wm_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml
${tst_ME_data_dir}/ME_Wm_virt.dat ${tst_ME_data_dir}/PSP_Wm.lhe.gz
)
add_test(
NAME t_ME_Z_FKL
COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml
${tst_ME_data_dir}/ME_Z_FKL_tree.dat ${tst_ME_data_dir}/PSP_Z_FKL.lhe.gz
)
add_test(
NAME t_ME_Z_FKL_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml
${tst_ME_data_dir}/ME_Z_FKL_virt.dat ${tst_ME_data_dir}/PSP_Z_FKL.lhe.gz
)
add_test(
NAME t_ME_Z_uno
COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml
${tst_ME_data_dir}/ME_Z_uno_tree.dat ${tst_ME_data_dir}/PSP_Z_uno.lhe.gz
)
add_test(
NAME t_ME_Z_uno_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml
${tst_ME_data_dir}/ME_Z_uno_virt.dat ${tst_ME_data_dir}/PSP_Z_uno.lhe.gz
)
# test main executable
file(COPY "${tst_dir}/jet_config.yml" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
set(test_config "${CMAKE_CURRENT_BINARY_DIR}/jet_config.yml")
if(HighFive_FOUND)
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - tst.hdf5\n")
endif()
if(HepMC3_FOUND)
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - tst.hepmc\n")
endif()
if(HepMC_FOUND)
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - tst.hepmc2\n")
endif()
if(rivet_FOUND)
file(READ ${test_config} config)
file(WRITE ${test_config} "${config}\nanalysis:\n rivet: MC_XS\n output: tst\n")
endif()
set(test_cmd_main "$<TARGET_FILE:HEJ_main>\\\;${test_config}\\\;${tst_dir}/2j.lhe.gz")
# check that HepMC3 output is correct
if(HepMC3_FOUND)
add_executable(check_hepmc ${tst_dir}/check_hepmc.cc)
target_link_libraries(check_hepmc HEJ ${HEPMC3_LIBRARIES})
target_include_directories(check_hepmc PRIVATE ${HEPMC3_INCLUDE_DIR})
set(test_cmd_hepmc "$<TARGET_FILE:check_hepmc>\\\;tst.hepmc")
else()
set(test_cmd_hepmc "")
endif()
# check that LHEF output is correct
add_executable(check_lhe ${tst_dir}/check_lhe.cc)
target_link_libraries(check_lhe HEJ hej_test)
set(test_cmd_lhe "$<TARGET_FILE:check_lhe>\\\;tst.lhe")
# check that rivet interface is consistent with naive rivet
if(rivet_FOUND)
# this assumes "rivet" and "yodadiff" are found in PATH
if(rivet_USE_HEPMC3)
set(hepmc_file "tst.hepmc")
else()
set(hepmc_file "tst.hepmc2")
endif()
if(rivet_USE_HEPMC3 OR (rivet_VERSION VERSION_LESS 3))
set(histo_exclude "")
else()
# rivet 3 with HepMC 2 is inconsistent in order of weights
# -> interface != direct call (by permutation)
# REQUIRES Yoda 1.7.5
set(histo_exclude "-M\\\;\\\\d")
endif()
set(test_cmd_rivet "rivet\\\;-a\\\;MC_XS\\\;${hepmc_file}\\\;-o\\\;tst_direct.yoda\
\;yodadiff\\\;${histo_exclude}\\\;tst.yoda\\\;tst_direct.yoda")
else()
set(test_cmd_rivet "")
endif()
# Run dependent tests in one command to ensure correct execution order
# Note: The commands are concatenated with "\;" to escape CMake lists.
# Thus arguments have to be escaped twice "\\\;".
# e.g. "cmd1\;cmd2\\\;arg1\\\;arg2" is executed like "cmd1 && cmd2 arg1 arg2"
add_test(
NAME main
COMMAND ${CMAKE_COMMAND}
-DCMDS=${test_cmd_main}\;${test_cmd_hepmc}\;${test_cmd_lhe}\;${test_cmd_rivet}
-P ${PROJECT_SOURCE_DIR}/cmake/run_multiple_tests.cmake
)
add_test(
NAME main_example
COMMAND $<TARGET_FILE:HEJ_main> ${PROJECT_SOURCE_DIR}/config.yml ${tst_dir}/h_3j.lhe.gz
)
# check that Sherpas LHE input can be read
add_executable(check_lhe_sherpa ${tst_dir}/check_lhe_sherpa.cc)
target_link_libraries(check_lhe_sherpa HEJ hej_test)
add_test(
NAME sherpa_reader
COMMAND check_lhe_sherpa ${tst_dir}/SherpaLHE.lhe 1.62624e+08
)
# check HDF5 reader & writer
if(HighFive_FOUND)
add_executable(test_hdf5 ${tst_dir}/test_hdf5.cc)
target_link_libraries(test_hdf5 HEJ)
add_test(
NAME hdf5_read
COMMAND test_hdf5 ${tst_dir}/Wm9-g4-repack.hdf5
)
add_executable(test_hdf5_write ${tst_dir}/test_hdf5_write.cc)
target_link_libraries(test_hdf5_write HEJ hej_test)
add_test(
NAME hdf5_write
COMMAND test_hdf5_write ${tst_dir}/Wm9-g4-repack.hdf5 output.hdf5
)
endif()
# check rivet interface
if(RIVET_FOUND)
add_executable(check_rivet ${tst_dir}/check_rivet.cc)
target_link_libraries(check_rivet HEJ rivet::rivet)
add_test(
NAME rivet
COMMAND check_rivet
)
endif()
# test boson reconstruction
add_executable(cmp_events ${tst_dir}/cmp_events.cc)
target_link_libraries(cmp_events HEJ)
add_test(
NAME reconstruct_W
COMMAND cmp_events ${tst_dir}/epnu2jLOFKL_unweight.lhe.tar.gz
${tst_dir}/epnu2jLOFKL_unweight_noW.lhe.gz
)
# test resummed result
add_executable(check_res ${tst_dir}/check_res.cc)
target_link_libraries(check_res HEJ hej_test)
+add_test(
+ NAME xs_h_1j
+ COMMAND check_res ${tst_dir}/h_1j.lhe.gz 4.11093 0.0221722
+ )
if(TEST_ALL) # deactivate long tests by default
add_test(
NAME xs_2j
COMMAND check_res ${tst_dir}/2j.lhe.gz 3.49391e+07 419684
)
add_test(
NAME xs_3j
COMMAND check_res ${tst_dir}/3j.lhe.gz 2.37902e+06 25746.6
)
add_test(
NAME xs_3j_unof
COMMAND check_res ${tst_dir}/3j.lhe.gz 133399 4688.83 unof
)
add_test(
NAME xs_3j_unob
COMMAND check_res ${tst_dir}/3j.lhe.gz 105247 3449.45 unob
)
add_test(
NAME xs_3j_splitf
COMMAND check_res ${tst_dir}/3j.lhe.gz 97659.9 2748.65 splitf
)
add_test(
NAME xs_3j_splitb
COMMAND check_res ${tst_dir}/3j.lhe.gz 107150 2799.8 splitb
)
add_test(
NAME xs_4j
COMMAND check_res ${tst_dir}/4j.lhe.gz 603713 72822.6
)
add_test(
NAME xs_4j_qqbar_mid
COMMAND check_res ${tst_dir}/4j.lhe.gz 21866.7 1716.96 qqbar_mid
)
add_test(
+ NAME xs_h_1j_long
+ COMMAND check_res ${tst_dir}/h_1j_large.lhe.gz 3.87829 0.00278302
+ )
+ add_test(
NAME xs_h_3j
- COMMAND check_res ${tst_dir}/h_3j.lhe.gz 0.821622 0.0220334
+ COMMAND check_res ${tst_dir}/h_3j.lhe.gz 0.667678 0.0126859
)
add_test(
NAME xs_h_3j_unof
- COMMAND check_res ${tst_dir}/h_3j_uno.lhe.gz 0.0127362 0.000271555 unof
+ COMMAND check_res ${tst_dir}/h_3j_uno.lhe.gz 0.0110041 0.000274214 unof
)
add_test(
NAME xs_h_3j_unob
- COMMAND check_res ${tst_dir}/h_3j_uno.lhe.gz 0.0130615 0.000224793 unob
+ COMMAND check_res ${tst_dir}/h_3j_uno.lhe.gz 0.0116516 0.000376737 unob
)
add_test(
NAME xs_epnu_2j
COMMAND check_res ${tst_dir}/epnu2jLOFKL_unweight.lhe.tar.gz 262.7 3
)
add_test(
NAME xs_epnu_3j
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.lhe.gz 38.9512 1
)
add_test(
NAME xs_emnubar_3j
COMMAND check_res ${tst_dir}/MGemnubar3j_unweighted.lhe.gz 24.1575 1
)
add_test(
NAME xs_epnu_3j_unof
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.lhe.gz 9.63702 0.128355 unof
)
add_test(
NAME xs_epnu_3j_unob
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.lhe.gz 9.70119 0.108436 unob
)
add_test(
NAME xs_epnu_3j_splitf
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.lhe.gz 2.91995 0.0463182 splitf
)
add_test(
NAME xs_epnu_3j_splitb
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.lhe.gz 3.40708 0.0550975 splitb
)
add_test(
NAME xs_epnu_4j
COMMAND check_res ${tst_dir}/MGepnu4j_unweighted.lhe.gz 10.2542 0.135106
)
add_test(
NAME xs_emnubar_4j
COMMAND check_res ${tst_dir}/MGemnubar4j_unweighted.lhe.gz 5.73282 0.0583738
)
add_test(
NAME xs_epnu_4j_qqbar_mid
COMMAND check_res ${tst_dir}/MGepnu4j_unweighted.lhe.gz 0.802603 0.0126908 qqbar_mid
)
endif()
diff --git a/t/ME_data/ME_h_mt_tree.dat b/t/ME_data/ME_h_mt_tree.dat
index 2df83f3..67ddde6 100644
--- a/t/ME_data/ME_h_mt_tree.dat
+++ b/t/ME_data/ME_h_mt_tree.dat
@@ -1,807 +1,807 @@
3.992094874e-08
-4.185821773e-05
+8.196772518e-06
3.886272139e-05
1.677832055e-02
4.050725953e-06
-4.055999567e-07
+1.220816977e-06
6.400462689e-07
-7.808091068e-07
+3.742983509e-07
6.053699559e-07
-2.319585446e-05
+1.177750296e-05
4.729758692e-05
1.621148815e-06
-5.231361193e-04
+7.380225302e-04
1.533703249e-05
9.573732998e-06
3.385087104e-02
8.137786341e-07
6.075300603e+02
5.951445813e-06
-1.348604339e-02
+3.873726373e-03
1.928186046e+00
5.710179361e-04
7.986990576e-04
-3.294994143e-05
-7.238377879e-04
+4.277256679e-05
+6.685370603e-05
7.024748657e-04
3.785614363e-02
-1.030019421e-06
+5.468590073e-07
2.008211091e+00
8.826462516e-08
4.627520004e-02
1.062169630e-01
9.340895791e-07
-7.480214167e-03
+8.346764403e-03
2.268339315e-02
3.600279122e-05
6.713118017e-07
-5.887169405e-03
+5.230478971e-05
7.567735364e-05
-5.345132291e-03
+5.347713887e-03
6.078088479e-04
8.320774902e-03
-3.346589526e-03
-3.866215769e-05
+4.545712675e-03
+3.196266076e-05
1.512660797e-04
5.522082262e-03
-3.877123396e-02
+1.127268419e-01
2.308611056e-07
5.469487827e-05
8.465334170e+00
-1.859344209e-04
-7.070711820e-06
+1.665315530e-04
+4.568237154e-06
5.082189599e-06
-1.433966763e-04
-2.108127322e-01
+1.142032421e-04
+1.619932721e-01
2.385636219e-02
4.438425107e+00
-2.701708040e-04
+1.641045471e-04
1.264773773e+00
5.041102815e-03
-2.763710407e-06
-6.964145214e-02
+3.716226630e-07
+1.877482245e-01
2.802069699e-03
-7.001209819e+00
+2.456172743e+01
7.203729133e-08
-4.770672076e-06
-1.891164022e-05
+1.189573607e-06
+1.692451519e-05
1.519941271e-05
1.114780681e-06
9.522309887e-04
9.263417548e-07
2.281568524e+00
1.328903015e-03
1.582906949e-03
2.692415322e+04
-1.205472913e-06
+7.173623704e-07
6.882327922e-04
1.063345487e-07
1.965024170e-02
-1.948146595e-06
+9.296820071e-07
4.393282876e-05
2.557397536e-02
4.961734615e+04
5.373795656e-06
1.069130607e-06
-2.803644104e-06
+1.895419629e-06
1.064996211e-04
-2.235242597e-04
+2.055296832e-04
7.837271762e-08
-2.699241349e-03
-5.812480053e-04
+1.893197963e-03
+8.035893840e-04
7.537519714e-02
-1.327685553e-03
-6.402315259e-05
+1.448194489e-03
+1.037014872e-04
1.147351214e-01
1.830765877e-01
1.136708763e-04
-1.828136154e-05
-2.655898063e-02
+1.953958263e-05
+1.662078365e-02
1.074103594e-03
5.057074674e-06
-1.092011261e-01
-9.236810553e-05
-9.185737640e+01
+9.202540796e-03
+1.462240721e-04
+4.352395882e+01
1.941656711e-02
8.942285136e-05
-3.601711816e-06
-3.259191724e-04
+2.063754311e-06
+5.671138604e-04
1.297220016e-04
1.168241824e-06
1.325832643e-04
3.029510688e+03
1.376379474e+00
-8.648106025e-02
-3.613453340e+01
+1.306553530e-01
+6.994240967e+01
1.782427563e-06
-1.016584963e-05
+8.185184700e-06
1.612906427e-03
-1.229884842e+00
+3.757235844e-01
3.636108827e-04
-2.703392541e-06
+2.122773977e-06
4.711472902e-06
1.707180334e-03
3.177104373e-01
-9.400835278e-04
-9.106525885e-02
+1.047618895e-03
+2.867034352e-02
2.624330979e-01
2.743869739e-02
-3.024143211e-06
-2.792768205e-03
+1.341583741e-06
+2.608840668e-03
1.890057728e-06
-1.770224622e-06
+8.891415599e-07
2.287175741e-05
-1.313886754e-05
+1.202819067e-05
2.859899271e-02
-1.518969937e-04
+1.985310427e-05
5.981959910e+00
4.271356353e+08
2.903377608e-04
1.798370637e+02
1.147588563e+00
-4.865983903e-06
+5.841886640e-06
2.932938348e-02
-1.238851181e+01
+3.775212750e+00
5.857377557e-04
1.233660800e-06
-5.854387384e-05
+4.663209870e-05
7.215231888e-01
-3.632504266e-04
+3.549866116e-05
1.098584101e-07
7.556062318e-04
3.450815469e-06
1.899482017e-03
-1.763070185e+00
+1.313953616e+00
6.624702819e-04
-4.349779721e+02
+1.310751166e+03
1.465647177e-05
-3.885460673e-03
+1.870096574e-03
5.365838158e-03
-9.878213852e-06
-2.629911519e-03
+5.541309490e-06
+7.981517449e-04
4.238909442e-02
1.808140555e-05
-8.517809026e-04
-1.965513473e+00
-2.184291473e-06
+1.492996452e-03
+1.719902537e+00
+1.615821605e-06
1.937148606e-04
6.421521178e-05
4.354545939e+02
8.570152334e-05
3.166251700e-03
-3.139728923e-07
+1.074557759e-07
1.068967309e-01
1.132391851e-07
5.424886276e-06
6.669088071e-06
-2.897766828e-03
-4.934832650e-03
+6.880701584e-04
+1.239602610e-02
2.417562879e-05
3.776703888e-08
5.135619353e-06
-1.042254650e-04
-1.363662187e+04
+1.850898062e-04
+1.422432137e+04
1.169042834e+02
-3.869061515e+02
-2.268279738e-01
+4.144268522e+02
+2.053103247e-01
2.331313778e-06
-1.020465182e-04
+7.553585245e-05
4.678573801e-03
4.271243283e-01
-1.084748834e-04
+7.683190450e-05
1.982331822e-06
2.248892692e-07
2.940369951e-05
-3.575535659e-01
-8.032884075e-06
+1.914503157e-01
+1.991493821e-06
4.885213404e-03
5.315825514e-04
-1.058261576e-07
+1.740468263e-08
1.116237563e-05
2.199703410e-06
-4.835456896e-06
-7.387759362e-03
+2.090107678e-06
+7.766119722e-03
5.758980869e-05
1.895971551e-06
-2.287620980e-03
+1.561753804e-03
7.491129176e-03
-9.445787374e-02
-7.659990515e-02
-1.380427275e-03
-1.315056721e-04
+9.228582973e-02
+6.077480078e-02
+7.658687799e-04
+1.543956032e-04
3.120838079e-07
-6.665033847e-07
+2.009776042e-07
2.243972471e-07
1.392182883e-07
3.111525022e-04
3.119219908e-03
3.190913642e-07
5.136773321e-04
-1.193962463e+00
-1.712479583e-05
+1.050626471e+00
+8.732441420e-06
2.523382412e-05
-4.021133825e-06
+2.113099081e-06
4.475792015e-07
3.590719160e-05
6.502851811e-07
2.670456447e-03
1.697306266e-01
-1.508902869e-02
-2.470827689e-05
-1.031014784e-03
-2.053297095e-04
+1.126961557e-02
+5.886943530e-05
+1.136180254e-03
+3.084117152e-04
3.063400862e-06
1.174532311e+03
-9.361653347e-06
+4.890087057e-06
7.091644248e-07
4.533040396e-05
3.947065691e-06
3.265370023e-03
1.286330059e-02
1.755757132e-02
-1.038603024e-04
-8.572677272e-02
+1.162775248e-04
+1.056069318e-01
7.479933532e-07
3.028129925e-02
2.521276297e-07
1.073442658e-06
5.899456289e-04
-3.973301390e-06
-6.759815353e+01
-8.904777259e-06
-3.989890077e-05
-3.390793260e-06
-1.175480487e-01
+2.589323889e-06
+6.406026551e+01
+1.213285060e-05
+5.256105286e-05
+2.599598125e-06
+4.713042233e-02
1.360433647e-07
7.177289496e-03
3.373827012e-06
1.333420649e-08
8.081973985e-04
8.003311035e-08
5.465880989e-07
9.880715609e-07
1.095536228e-04
4.997618552e-03
1.326013609e-02
3.701464255e-10
1.770693543e-09
6.184290168e-10
-1.372839961e-08
-1.149320956e-05
+5.408231587e-08
+5.805267572e-07
1.085732929e-10
7.599253295e-06
1.628454581e-06
7.182423584e-08
8.292324554e-09
2.257110951e-08
-3.069783839e-07
+2.231223523e-07
7.666821934e-08
1.173780382e-07
6.007280547e-04
1.464744990e-05
1.348042340e-07
-3.843469421e-07
-7.753772161e-07
+2.463453284e-07
+6.711080076e-06
1.703489267e-02
1.789180400e-04
3.066687326e-06
2.222684120e+04
6.717770841e-02
-1.144741442e+00
-7.090400404e-07
+1.200378785e+00
+8.004688513e-06
8.686008641e-04
3.450945082e-01
1.636463113e-03
6.817527667e-07
1.028383115e+02
1.721842018e-06
-6.431190489e-03
+2.754127764e-03
2.918858849e-04
6.129798687e-03
-3.008832924e-07
-1.065045579e-05
+2.486666846e-07
+5.748231156e-05
5.809373613e-07
2.927954692e-03
1.388370713e-08
1.356586223e-06
2.813984721e-02
1.297746410e-09
7.786568980e+01
3.264184500e-06
2.836681306e-07
-4.398094311e-07
+3.571706779e-07
3.598802506e-04
1.868220397e-06
2.849410612e-07
2.596087476e-02
4.592205330e-04
-1.459850163e-03
-2.484254753e-08
+1.405730589e-04
+8.560787383e-08
2.391190808e-11
4.240951797e-07
1.387291457e-05
8.034780869e-07
2.124451168e-07
8.390942376e-07
2.361998231e-06
6.247996695e-02
-1.828058984e-07
+8.222945802e-06
2.162487170e-08
6.312203852e-10
1.337381780e-07
-4.874341409e-06
+6.062997927e-07
1.702327829e-05
1.011609745e-04
1.533468085e-02
1.667951887e+00
5.030267420e-10
1.139451323e-05
3.183032762e-07
-3.235639818e-10
+2.237240595e-09
2.430181002e-04
1.381401338e-06
4.979010339e-01
9.020006681e-05
2.759486784e-02
1.339412310e-02
7.515614514e-07
2.253136074e-04
3.711042475e-04
-1.854708579e-08
+1.652099502e-08
5.705200359e-07
2.473009659e-09
1.514970229e-04
2.322274317e-11
-1.726476060e-05
+8.221380799e-05
7.341296496e-09
-9.197227698e-06
+5.411694965e-06
5.279672173e-04
2.475544869e-02
6.201410725e-06
1.711624401e-08
7.902721792e-09
9.324230363e-03
4.075955349e-07
4.688015189e-03
6.749004939e-10
2.999224438e-03
6.019268002e-05
8.787361497e-08
6.945252864e-08
9.595782277e-08
-1.625437720e-05
+1.772129641e-04
5.133881400e-07
8.769140427e-08
1.022666334e-08
3.132242163e-07
4.193068850e+01
4.631926277e-03
-1.144469109e-05
-5.664388534e-08
+4.767675174e-05
+1.189850982e-07
3.375398402e-06
2.598800453e-07
-2.337574645e-03
+1.899099964e-03
1.274531455e-05
6.215715396e-02
-1.775364321e-08
+5.474814301e-08
2.374516724e-07
9.753985675e-05
3.869868336e-01
4.390578321e-07
-3.000736624e-08
+1.594728547e-06
3.867882672e-05
-1.050104466e-05
+6.739472512e-06
1.399824935e-06
4.687501738e-06
2.378767375e-07
2.412995792e-06
2.704096959e-04
1.381808608e-02
-1.707843925e-07
+5.432177431e-06
1.214986888e+00
1.767481603e+02
3.854751270e-02
7.420331844e-05
2.259667315e-04
2.942925975e-03
8.757517651e-03
5.344369331e-08
3.593653536e+02
6.467206229e-07
2.745454045e-07
8.574175060e-08
4.255704047e-07
2.002284348e-05
5.493924956e-08
1.802539443e-03
1.601027440e+01
7.907947992e+00
5.027886303e-12
1.274815065e-06
-3.367942241e-03
+2.075658551e-03
1.740566241e-05
-1.774837005e-06
-2.208876407e-04
+1.341515010e-06
+9.951321628e-06
9.243270257e-05
8.524429842e-05
2.419623547e-06
1.230884542e-04
-8.907205979e-09
+9.127531649e-08
2.566123942e-07
8.539518312e-04
-3.043047889e-01
+1.363117323e-01
6.429865611e-04
1.201072347e-07
4.750256525e-07
2.576400162e+02
2.763586288e-09
1.267891193e-11
1.458368254e-09
3.481231126e+01
8.491610679e-05
-4.663481890e-06
+3.230663368e-06
1.904436262e-05
3.709893359e-07
1.885579069e-08
-2.676142195e-02
-1.523362214e+01
+1.790087427e-02
+3.076988474e+01
2.868038539e-10
1.357926076e-06
9.510763538e-07
3.078854471e-04
9.821307420e-04
1.300034923e-05
4.615435789e-03
1.691264974e-02
9.625087635e-07
8.484139033e-06
8.754745805e-06
1.274545153e-03
6.656659217e-07
-5.641878480e-11
+3.575691156e-10
2.383536690e-01
1.621172643e-07
2.434094753e-04
2.309462437e-03
-7.523563623e-09
+4.808733345e-08
7.235599966e-12
2.156490604e-02
6.454117346e-09
7.417210735e-08
6.106701982e-04
2.258166597e-07
8.795188382e-07
1.685348984e-07
-3.386721515e-06
+2.258177232e-06
5.471138589e-08
4.593203864e-04
3.358979136e-10
8.951701347e-09
1.343141523e-01
2.488084203e-06
9.204318421e-06
7.372957808e-06
3.592101975e+00
-8.031445428e-06
+2.131554796e-05
4.722279636e-07
2.188554117e-07
2.191013639e-06
3.125129233e-07
1.431464700e-05
-2.604187492e-04
+7.955273814e-04
2.318813104e+01
-1.775352611e-08
+4.338597574e-09
4.153948605e-06
1.759323469e-03
4.247828764e-09
3.314663642e+06
9.546118067e-04
3.628713279e-02
5.151960839e-01
-4.787966943e-03
+6.567777665e-03
2.306063053e-06
5.992993419e-02
4.335225445e-04
2.006054641e-08
1.805085571e-04
3.245279608e-04
-6.198119690e-07
+4.393002963e-07
2.877595699e-08
-4.213932767e-02
+4.623803927e-02
8.509180682e-07
1.898404662e+01
3.391894018e-04
1.572894562e-07
4.829147344e-04
4.124974312e-07
5.920628259e-09
1.133085150e-02
5.866745018e-05
1.477890940e-08
3.373201885e-01
1.783285709e-06
1.019277350e-07
1.077236434e-08
-1.229835899e-08
+6.876864321e-09
2.972773815e-03
4.579972943e-06
6.660223604e-11
-3.255274106e-06
+1.308476750e-05
6.049147519e-02
4.838831696e-09
-1.103007279e-06
-3.877771858e-04
-6.589496231e-04
+1.759810298e-05
+4.511754771e-04
+9.914683060e-04
2.252402531e-04
4.286469542e-06
1.183819823e-07
1.041053006e-03
8.023777540e-06
1.752202725e-10
6.760656342e-08
5.978357995e+02
1.570112402e-07
4.259084825e-02
2.734813579e-08
5.126265230e-04
1.262174839e-10
2.604124552e-07
1.853779761e-06
1.073157373e-10
1.186846920e-07
3.373467406e-02
6.462294348e-04
3.617927133e-09
1.235675676e-05
1.014307383e-05
9.670573618e-06
2.734079755e-04
9.022790348e-09
-7.773060762e-07
+1.723330398e-07
3.192976198e-05
1.605410097e-11
3.347506568e-03
6.096357632e-08
3.761983860e-04
2.002368022e-04
3.663856060e-11
9.014051583e-09
2.039080244e-08
2.382698390e-08
4.826461958e-09
-3.679235457e-11
+3.736318011e-12
1.064541901e-07
2.647936408e-07
-3.642977680e-11
+3.674583713e-11
2.472948608e-02
3.511106044e-05
3.074534950e-09
-1.016903387e-09
+2.532378050e-08
2.865192597e-10
8.729591282e-06
5.263810095e-09
3.162734995e-11
1.553836336e-03
-6.724165748e-07
-2.487746874e-09
+6.088023357e-08
+2.772123876e-09
7.601811027e-10
1.002426515e-02
1.099404522e-06
-3.911025646e-06
+1.509270489e-06
3.707210974e-09
6.845537328e-09
1.288663850e-09
6.213720922e-12
3.370298227e-06
-4.073205483e-09
+1.033815084e-08
7.619743854e-05
6.153142911e-05
1.627750340e-06
7.071597014e-09
4.073669344e-10
2.323555275e+05
8.054141816e-03
8.651093356e-10
2.242451061e-10
3.216554842e-08
1.393140866e-06
2.192548352e-08
1.589958782e-08
4.319282434e-05
5.033873119e-04
1.969565661e-03
3.026962238e-05
5.847143807e-04
7.159197474e-06
6.852087190e-06
3.993958708e-06
5.152611742e-03
2.371431793e-09
9.761043438e-06
1.179390494e-08
1.500987015e-08
3.198124316e-11
3.669563179e-01
1.279595204e-09
4.407960907e-04
-1.201825090e-07
+1.541770012e-08
8.758634293e-07
7.197319124e-11
1.456265421e-06
2.118209999e-02
1.166460184e-02
3.975708970e-09
8.585133916e-09
1.431700406e-08
8.083628402e-10
7.710293690e-04
2.486389630e-12
2.209639132e-06
-3.015485921e-01
-1.011048497e-05
+4.505230938e-01
+9.794173060e-06
2.717537412e-09
3.117310948e-06
-1.196435320e-06
-4.481379516e-09
+2.149222999e-06
+1.586976182e-09
2.669049021e-08
3.465183725e-09
5.746377675e-06
6.827640940e-05
2.205905568e-07
8.277136503e-08
5.233327912e-07
6.831993026e-11
1.722970086e-06
9.209494681e-07
-1.853861729e-04
+5.200766419e-04
2.597674405e-03
6.127253802e-11
1.815659011e-04
7.719959906e-14
1.355959480e-08
1.068097702e-06
4.571150240e-07
7.835485051e-07
2.443967251e+00
7.521608515e-11
-3.772716632e-06
+2.823325161e-05
1.492486651e-07
3.947354347e-09
8.108470196e-09
1.226200398e-04
2.265314247e-11
1.841207960e-03
1.113595985e-02
-2.535644631e-06
+1.060453671e-06
4.652540757e-11
4.191956716e-10
4.620562396e-05
4.971924276e-04
7.584566548e-09
4.136067428e-13
2.639942371e-03
2.560094895e-08
6.494205457e-08
3.813228849e-11
2.394276536e-01
9.383928172e-08
2.354446386e-03
1.169788005e-11
1.635056993e-09
8.927013480e-08
3.401987129e-10
-6.359659489e-07
+1.675967327e-06
8.846280299e-07
8.063601622e-13
-1.272867559e-07
+8.804357796e-08
5.056101098e-08
3.717053057e-05
1.584125694e-06
4.622564202e-08
3.862253555e-05
2.369045122e-04
-8.076951359e-08
+3.404567890e-08
2.028201866e-10
1.490632954e-05
2.809039801e-06
4.286284920e-10
1.225531203e-09
9.651458117e-10
5.073720873e-06
1.168279305e-03
-3.125393506e-07
+2.920249868e-07
2.924547371e-06
3.901702794e-06
-1.812373580e-08
+7.720671548e-09
9.208991156e-06
4.592993319e-03
1.243474714e-11
1.620460995e-06
4.067811815e-04
6.212555249e-02
2.225663359e-12
1.546065372e-10
2.095252325e-01
2.734979770e-02
-1.919282224e-12
+3.915460176e-11
1.583212739e-03
-1.842092784e+00
+1.944138853e+00
8.594625100e-01
9.586561470e-02
5.893601451e-11
9.940877292e-12
5.380308774e-02
1.865793667e-04
6.607021968e-08
3.838609063e-07
9.049824655e-07
3.888723805e-04
2.777900492e-11
2.684360703e-04
5.913695711e-06
5.737197844e-04
4.110113744e-09
-5.107891323e-08
+6.926669070e-08
3.390290129e-09
8.095451133e-12
4.321661893e-08
4.873283944e-07
1.274003933e-11
9.104409500e-12
7.179607836e-07
3.906896479e-11
1.948313091e-08
1.164976881e-01
1.112886046e-06
-1.022484093e-06
+7.213080269e-07
2.591738179e-07
1.275159404e-04
4.499451474e-04
-5.923928986e-10
+8.404305175e-10
9.029183686e-06
1.165979189e-08
4.397445726e-07
1.101331326e-15
7.092692390e-08
6.766025857e-05
2.582987643e-06
-2.626015584e-07
+3.321391882e-06
2.252897510e-10
1.582238936e-05
-1.110207514e-04
+1.652518543e-04
1.437364367e-09
3.309200992e-03
4.409409406e-05
3.202533864e-09
7.209532734e-10
3.001628290e-04
4.616089749e-05
8.022866888e-10
6.706777161e-12
3.828630640e-05
7.926932401e-05
4.488498744e-05
1.348692501e-06
9.161443367e-10
8.678114985e-07
1.926070493e-06
4.765469595e-09
1.893168874e-08
1.549578157e-08
9.229013716e-06
1.035062224e-04
6.357487377e-07
4.034696570e-06
1.504164503e-08
9.700520388e-12
2.293483524e-05
2.338097661e-02
3.059032675e-03
5.427962171e-08
1.401989839e-03
1.579634046e-12
1.072621482e+01
6.864694660e-04
-3.075076448e-07
+3.109092415e-06
4.970636771e-09
-2.187827570e-08
+6.303062215e-08
diff --git a/t/ME_data/ME_h_mtinf_tree.dat b/t/ME_data/ME_h_mtinf_tree.dat
index 0a1434f..ac5b937 100644
--- a/t/ME_data/ME_h_mtinf_tree.dat
+++ b/t/ME_data/ME_h_mtinf_tree.dat
@@ -1,807 +1,807 @@
5.572804568e-08
-2.820771959e-05
+7.733052565e-06
3.888389298e-05
2.042806864e-02
4.680070730e-06
-1.526564425e-07
+1.199611836e-06
6.409292912e-07
-5.895267757e-07
+3.624707578e-07
6.467450370e-07
-1.483353367e-05
+1.121526540e-05
4.871451037e-05
1.941740277e-06
-4.430985498e-04
+7.229521772e-04
1.597702620e-05
1.229649514e-05
3.422004512e-02
8.538221861e-07
5.785658479e+02
6.315861962e-06
-1.308773607e-02
+4.013595931e-03
2.249050403e+00
1.159555900e-03
7.916035504e-04
-3.014257182e-05
-1.601499960e-04
+5.358231482e-05
+8.370449969e-05
9.764963622e-04
3.871461664e-02
-3.207564898e-07
+6.311772268e-07
1.938663548e+00
8.986523335e-08
4.606848096e-02
1.664459283e-01
1.059082305e-06
-4.397799541e-03
+8.223257111e-03
2.194313999e-02
3.746404383e-05
6.881839613e-07
-6.326635550e-03
+4.919765175e-05
2.323756323e-04
-4.620157100e-03
+5.245688183e-03
5.863695633e-04
1.141179377e-02
-2.782529791e-03
-2.283025018e-05
+4.580570661e-03
+3.065133090e-05
1.815046198e-04
9.223059152e-03
-3.244681476e-02
+1.156611582e-01
3.089668561e-07
5.373616917e-05
1.201443762e+01
-1.866292793e-04
-4.281174307e-06
+1.931944033e-04
+8.350132849e-06
9.885414773e-05
-1.131417601e-04
-1.411312700e-01
+1.162808849e-04
+1.555676074e-01
2.370571321e-02
5.430257614e+00
-2.196112759e-04
+1.592021140e-04
1.255259399e+00
5.534475149e-03
-1.490132281e-06
-4.094139359e-02
+3.591615295e-07
+2.106576100e-01
3.105378110e-03
-4.886950565e+00
+2.468183380e+01
9.549405497e-08
-4.289881031e-06
-1.261969556e-05
+1.139757378e-06
+1.666228407e-05
1.504176295e-05
4.024167287e-06
9.287030781e-04
3.575383717e-06
2.205209754e+00
1.345140269e-03
1.944571866e-03
2.590234738e+04
-4.789731617e-07
+7.661844320e-07
1.265615683e-03
2.194569070e-07
2.564179368e-02
-1.735139373e-06
+9.041496323e-07
5.374038239e-05
3.608593751e-02
4.828245194e+04
6.210373583e-06
8.257528074e-06
-2.432389755e-06
+1.940573073e-06
8.192357630e-04
-1.953389911e-04
+2.147295162e-04
8.449199830e-08
-2.494709041e-03
-5.259481531e-04
+1.843012541e-03
+8.134506434e-04
8.386707002e-02
-1.107702869e-03
-1.673540132e-05
+1.481848847e-03
+1.137671545e-04
1.208500717e-01
2.018148288e-01
1.466103051e-04
-1.495761867e-05
-1.793952356e-02
+2.191712369e-05
+1.620358032e-02
1.468013763e-03
6.097640805e-06
-1.145453769e-01
-6.033545136e-05
-8.309124414e+01
+8.831566891e-03
+1.455096615e-04
+4.498297020e+01
1.949243022e-02
1.087303162e-04
-5.946680972e-07
-2.078428330e-04
+2.049386967e-06
+5.509716144e-04
1.537887580e-04
1.356242586e-06
1.974324073e-04
2.963883364e+03
1.431916564e+00
-7.883498059e-02
-3.372884128e+01
+1.355246132e-01
+6.716107491e+01
1.940705323e-06
-8.496241084e-06
+1.253258061e-05
1.668054846e-03
-1.104399324e+00
+4.195267419e-01
4.749137893e-04
-2.250590696e-06
+2.263451815e-06
5.016010297e-06
2.680527032e-03
3.199000005e-01
-6.817976032e-04
-6.150184679e-02
+1.016549548e-03
+2.698314590e-02
3.785330696e-01
3.056569994e-02
-1.281744929e-06
-2.332077392e-03
+1.352492231e-06
+2.860616015e-03
1.183459824e-05
-1.706974631e-06
+8.932434519e-07
2.249345228e-05
-1.297721679e-05
+1.498587652e-05
2.934136148e-02
-1.570407685e-04
+3.282899401e-05
6.389068161e+00
4.837678972e+08
2.910973086e-04
1.716201719e+02
1.631035646e+00
-3.743085237e-06
+6.322851944e-06
3.066208474e-02
-1.304137762e+01
+3.935262689e+00
6.836375721e-04
2.114055578e-06
-2.780369101e-05
+4.485509365e-05
1.195553498e+00
-2.234658305e-04
+3.389669700e-05
1.485581537e-07
7.396640117e-04
6.598939949e-06
2.119548369e-03
-1.561680586e+00
+1.260309398e+00
6.658022304e-04
-4.724282754e+02
+1.694933678e+03
1.430389956e-05
-3.772331655e-03
+2.260617835e-03
5.369080172e-03
-4.438842246e-06
-2.336918233e-03
+2.370008214e-05
+8.514750223e-04
1.690138110e-01
1.829564964e-05
-6.883322589e-04
-1.804051793e+00
-1.736607582e-06
+1.482508088e-03
+1.849532887e+00
+1.778277687e-06
2.255678771e-04
6.524599620e-05
4.372467535e+02
8.387224326e-05
3.343506359e-03
-1.890263288e-07
+2.854101208e-07
1.110841737e-01
2.100158475e-07
6.050673169e-06
6.731118778e-06
-2.104439733e-03
-3.011438923e-03
+6.474610210e-04
+1.231605309e-02
2.674458314e-05
4.144657087e-08
6.897914197e-06
-4.406776189e-05
-1.315696681e+04
+1.790387819e-04
+1.387432121e+04
1.121949844e+02
-4.072498680e+02
-1.944309706e-01
+4.794589429e+02
+2.023359787e-01
3.627260888e-06
-8.933360379e-05
+7.634301399e-05
4.530032022e-03
4.366576508e-01
-9.763726361e-05
+7.607425884e-05
2.773608322e-06
1.698189395e-06
3.062031893e-05
-3.566098292e-01
-4.856826323e-06
+2.002207347e-01
+1.898966670e-06
5.045283380e-03
5.299933444e-04
-2.781944269e-08
+3.017540386e-08
1.275786883e-05
9.664916790e-06
-2.533942575e-06
-6.437171912e-03
+2.077047482e-06
+8.578084914e-03
6.595509942e-05
1.892603441e-06
-1.839316783e-03
+1.511182400e-03
7.097187691e-02
-9.275503249e-02
-8.054671830e-02
-7.827390196e-04
-1.299825904e-04
+9.906404509e-02
+6.741300094e-02
+7.280060014e-04
+1.603955276e-04
6.948078299e-07
-4.624337301e-07
+1.981505848e-07
2.351049919e-07
1.218637919e-06
3.374685455e-04
3.125835543e-03
6.317642047e-07
5.304174029e-04
-1.037834687e+00
-1.574520165e-05
+9.993233020e-01
+8.479197598e-06
4.025622878e-05
-2.138630832e-06
+3.579791076e-06
4.624321565e-07
3.557996624e-05
7.632352346e-07
4.087274884e-03
1.707433480e-01
-9.388651019e-03
-1.084988719e-05
-9.918063878e-04
-1.280830068e-04
+1.094536785e-02
+5.812909858e-05
+1.136971585e-03
+3.254729254e-04
3.013380422e-06
1.140558348e+03
-6.138041700e-06
+4.746179921e-06
5.936317197e-06
4.476488634e-05
4.866820693e-06
3.364268242e-03
1.345732182e-02
1.691848296e-02
-8.648323648e-05
-7.719194047e-02
+1.305004426e-04
+1.061215338e-01
2.261298664e-06
3.032245343e-02
6.391553476e-07
2.699173814e-06
6.756168369e-04
-2.416507126e-06
-6.467006973e+01
-8.329641063e-06
-3.183693467e-05
-1.709549257e-06
-9.650189020e-02
+2.755355122e-06
+6.542857280e+01
+1.383795196e-05
+5.065774597e-05
+2.629072903e-06
+5.216417814e-02
1.391403765e-07
7.263556652e-03
4.999370887e-06
1.625061232e-08
8.509561784e-04
1.202205227e-07
7.144871653e-07
9.471851526e-07
1.191493923e-04
5.840966853e-03
1.370040570e-02
5.713297919e-10
3.607906530e-08
7.307412331e-10
-1.451344169e-08
-1.724590008e-05
+5.511244325e-08
+6.212518331e-07
1.522273099e-10
7.303492170e-06
2.394106739e-06
9.439029291e-08
1.197178286e-08
2.852370502e-08
-2.918666188e-07
+2.402523519e-07
1.633081697e-07
4.999725784e-07
4.364098403e-03
1.530966988e-05
5.067352329e-07
-3.099247619e-07
-2.158143194e-06
+2.520162972e-07
+6.700189824e-06
2.052969833e-02
1.958876337e-04
9.931888956e-06
2.504301598e+04
7.117111486e-02
-1.129363603e+00
-8.519028290e-07
+1.221458125e+00
+9.586731023e-06
8.611561913e-04
3.313925797e-01
1.685927042e-03
7.737216703e-07
1.356040671e+02
1.715670931e-06
-1.765374179e-02
+2.618197626e-03
3.045426205e-04
9.039006896e-03
-4.862966762e-07
-9.910844952e-07
+2.394536597e-07
+5.543261305e-05
6.749068743e-07
2.759944309e-03
4.200025166e-07
1.836184773e-06
2.906214889e-02
1.426547480e-09
1.236256079e+02
3.871989502e-06
2.818399887e-07
-2.178107596e-07
+3.469606518e-07
3.622199797e-04
1.953122542e-06
2.920307346e-07
2.735652104e-02
4.826860535e-04
-1.292659386e-03
-4.952619212e-08
+1.445516015e-04
+8.112009732e-08
9.362955197e-11
4.786061319e-07
1.721659726e-05
1.051237231e-06
1.003149697e-06
1.453591818e-06
6.002229724e-06
7.422256382e-02
-4.977610976e-07
+9.815749338e-06
2.615599662e-08
6.718184084e-10
1.459950517e-07
-7.829096020e-06
+7.273135157e-07
2.230570626e-05
1.132328395e-04
1.544043912e-02
1.732457391e+00
1.154545164e-08
1.291848361e-05
3.342745364e-07
-3.485361981e-09
+4.563465563e-09
2.706474718e-04
5.574804238e-06
8.990146655e-01
1.001326662e-04
2.233523312e-02
1.335995585e-02
7.467887166e-07
2.231001789e-04
3.699152099e-04
-1.894965441e-08
+1.607144612e-08
1.654294075e-06
4.086577889e-09
1.755105427e-04
8.416393596e-11
-5.823380307e-04
+5.086290204e-04
7.687882493e-09
-9.965822218e-06
+5.276775857e-06
7.023227535e-04
2.470065095e-02
6.259343015e-06
3.462534698e-08
1.721326261e-08
9.100990839e-03
6.068046546e-07
5.073613628e-03
8.104795790e-10
4.489318495e-03
7.059335059e-05
1.116936224e-07
9.447042548e-08
1.142507724e-07
-2.495452814e-05
+2.371968894e-04
1.102725863e-06
9.170351616e-08
1.116173034e-08
3.160808071e-07
4.719294278e+01
5.609765930e-03
-2.640897278e-05
-3.211672292e-08
+4.974598170e-05
+1.193166957e-07
3.933913946e-06
1.705704126e-06
-2.687621190e-03
+1.957618819e-03
1.353055173e-05
6.037711935e-02
-4.178013966e-08
+1.201565019e-07
2.754380072e-07
1.284315046e-04
4.613545669e-01
8.243835252e-07
-1.031488143e-06
+1.938272446e-06
4.518197192e-05
-2.299612194e-05
+6.428165315e-06
1.469929984e-06
4.854750586e-06
2.231002492e-07
5.180713437e-06
2.793839809e-04
1.366295653e-02
-1.616729204e-06
+6.172873979e-06
1.076928081e+01
1.777645145e+02
4.165016415e-02
7.327803251e-05
2.312992445e-04
3.278010006e-03
1.857660707e-02
4.395091584e-07
8.377603390e+02
7.221567849e-07
7.394039845e-07
9.034821635e-08
6.938495910e-07
1.962974288e-05
7.831554318e-08
2.417915157e-03
1.681184118e+01
8.358803602e+00
2.506211004e-11
1.351591326e-06
-3.909223946e-03
+2.062054738e-03
1.874994001e-05
-1.059999529e-06
-2.518063912e-04
+1.273948784e-06
+9.933080519e-06
2.797398009e-04
8.269820486e-05
2.741694330e-06
1.362989830e-04
-4.102693857e-09
+9.164841907e-08
3.180061341e-07
1.076406164e-03
-2.895143691e-01
+1.355139500e-01
7.799632930e-04
1.245152763e-07
6.645743195e-07
2.622509110e+02
2.169016271e-07
2.388605910e-10
1.819082046e-09
3.475786517e+01
1.057002104e-04
-3.534833550e-06
+3.237208557e-06
1.874181702e-05
4.841351554e-07
2.302607917e-07
-2.925781695e-02
-6.513680610e+01
+2.038562253e-02
+3.495771494e+01
4.055168507e-10
1.438034814e-06
1.064547563e-06
3.082750857e-04
1.073504174e-03
1.300681473e-05
6.459601030e-03
1.895987606e-02
1.060829403e-06
8.238797134e-06
9.317793462e-06
1.278356229e-03
2.279610719e-06
-6.248891603e-10
+1.382921781e-09
2.530038522e-01
1.627768885e-07
3.293036130e-04
2.529327920e-03
-1.911162552e-08
+4.672588444e-08
8.591395213e-12
3.257413794e-02
7.190258956e-09
8.073987581e-08
6.258596186e-04
2.468811944e-07
9.951052105e-07
1.743583334e-07
-4.744668344e-06
+2.328948669e-06
1.326313019e-07
5.072538045e-04
3.985459568e-10
1.104303535e-08
1.692316356e-01
3.763376717e-06
1.038624337e-05
8.048797417e-06
3.622786876e+00
-2.101538644e-05
+2.248990246e-05
5.040009061e-07
2.335240322e-07
2.498424766e-06
4.202295601e-07
4.830236598e-05
-2.774322272e-04
+8.368164583e-04
2.330464677e+01
-2.127545991e-08
+7.120165977e-09
8.724210005e-06
1.781787412e-03
4.502368871e-09
3.186046302e+06
9.687848173e-04
4.668030680e-02
5.164858709e-01
-5.049608334e-03
+7.105465534e-03
2.351688446e-06
7.460050065e-02
6.143272317e-04
3.188169157e-08
2.788262516e-04
3.793487471e-04
-8.181505685e-07
+4.270240864e-07
2.933159250e-08
-1.641859923e-02
+4.573912261e-02
8.517988386e-07
1.843228168e+01
4.363104434e-04
1.649030026e-07
5.022484285e-04
5.146033092e-07
6.127315124e-09
1.194048916e-02
7.296523578e-05
2.261779127e-08
3.550279519e-01
4.665801541e-06
1.133805742e-07
1.077545331e-08
-4.317767277e-09
+7.131867193e-09
3.024651909e-03
4.900211468e-06
8.425164568e-10
-3.260771789e-06
+1.294664863e-05
7.229895794e-02
9.030803015e-09
-2.800132225e-06
-5.852057905e-04
-3.863934208e-04
+2.535846234e-05
+4.518151037e-04
+1.191228239e-03
2.302342216e-04
7.639352281e-06
1.200219161e-07
1.046101258e-03
8.161065404e-06
4.074095042e-10
7.474610092e-08
8.139530652e+02
2.860319094e-07
5.402717193e-02
1.094737399e-07
7.218336860e-04
1.363337213e-10
2.897166555e-07
5.466416822e-06
1.046528666e-09
1.214075429e-07
3.517308930e-02
6.876570099e-04
4.381704653e-09
1.425064448e-05
1.092939333e-05
1.013613284e-05
4.161445140e-04
3.929296641e-08
-1.861345650e-06
+1.994116871e-07
3.350149307e-05
1.942422023e-11
3.921387549e-03
6.092617772e-08
4.006639955e-04
2.193198014e-04
4.588823322e-11
2.247656490e-08
4.235884774e-07
2.699312268e-08
7.118759240e-09
-4.661647359e-11
+3.648990021e-12
1.283410386e-07
3.251622127e-07
-2.281843258e-10
+1.018895416e-10
2.504071095e-02
5.445082047e-05
3.290489223e-09
-1.115318901e-09
+2.473663065e-08
3.484841326e-10
1.191475982e-05
9.490624444e-09
3.852807809e-11
1.668368723e-03
-1.354227113e-06
-3.547185971e-09
+8.130387972e-08
+2.792391782e-09
1.128183821e-09
1.205968563e-02
2.973950143e-06
-7.161620283e-06
+2.998002570e-06
9.571931819e-09
1.477120229e-08
1.360026180e-09
6.536532052e-12
3.756762190e-06
-3.519031871e-09
+1.072436666e-08
7.705635137e-05
6.527963639e-05
1.900806678e-06
9.604137497e-09
4.832543450e-10
2.461535131e+05
8.317793495e-03
1.288549452e-09
2.984905834e-10
3.442753033e-08
1.446019240e-06
2.554651308e-08
1.716746196e-08
4.218315871e-05
6.263553513e-04
2.045309149e-03
4.000660563e-05
5.947272843e-04
1.599749747e-05
1.072982129e-05
4.537764019e-06
5.320579544e-03
3.835647646e-09
1.154139540e-05
1.347260164e-08
1.754674352e-08
3.517542867e-09
3.604393244e-01
1.896710657e-09
4.711292756e-04
-1.566983764e-07
+2.519062555e-08
1.025894195e-06
1.607487456e-10
2.074443931e-06
2.716520917e-02
1.306997660e-02
7.745194101e-09
1.008059614e-08
5.325487074e-08
8.890288216e-10
8.313145689e-04
4.728469346e-12
2.657420217e-06
-3.166893117e-01
-1.834172030e-05
+4.448234848e-01
+1.010572429e-05
3.333556889e-09
4.293987770e-06
-1.491532386e-06
-1.410273888e-08
+2.315368304e-06
+3.563069196e-09
2.890119270e-08
4.758693888e-09
6.648097567e-06
7.550647813e-05
7.063391619e-07
2.802247921e-07
5.253163265e-07
7.788619114e-11
1.927421367e-06
9.100970575e-07
-6.011167546e-04
+1.327864867e-03
3.591861909e-03
7.601695154e-11
3.437030489e-04
2.831401705e-13
1.700113295e-08
1.120067516e-06
5.630141622e-07
8.019872998e-07
2.370711819e+00
9.945530280e-10
-4.398816915e-05
+1.046421293e-04
2.658536988e-07
4.070765645e-09
1.348964882e-08
1.346100783e-04
2.397829940e-11
2.216977235e-03
1.189249860e-02
-2.450245944e-06
+1.118171189e-06
8.735058436e-11
5.128984744e-10
5.483813146e-05
5.291911467e-04
1.678041194e-08
5.087404421e-13
3.470363247e-03
2.618358550e-08
6.675635132e-08
3.972641717e-11
2.395412045e-01
1.018953051e-07
2.618325163e-03
1.491391997e-11
2.263240793e-09
1.092156400e-07
4.240317799e-10
-8.177875085e-07
+1.698707365e-06
9.662018142e-07
1.204063649e-12
-1.737324984e-07
+9.132831222e-08
9.262311981e-08
4.417568826e-05
2.309013645e-06
1.033175136e-07
5.304100308e-05
5.585876907e-04
-1.268736665e-07
+4.154525487e-08
4.226412120e-10
1.496595206e-05
4.128704267e-06
1.069473089e-08
1.288077396e-09
1.976544269e-09
7.208953037e-06
1.198806306e-03
-5.010388968e-07
+4.205581376e-07
2.893094105e-06
3.846974156e-06
-1.917703115e-08
+9.103143357e-09
9.122224995e-06
5.017367317e-03
1.467921358e-11
1.712696979e-06
1.576706134e-03
6.218478551e-02
2.210917575e-11
1.833388455e-10
2.076192027e-01
2.666210155e-02
-3.173840670e-12
+5.527616660e-11
1.736922913e-03
-1.270319507e+00
+1.956019486e+00
1.248995403e+00
1.027514498e-01
1.303631291e-10
9.717345904e-12
5.470246326e-02
2.344214153e-04
8.645766604e-08
4.546502119e-07
9.821436471e-07
4.543371326e-04
2.734115483e-11
2.831850423e-04
1.396680491e-05
6.540453499e-04
6.962926737e-09
-5.502582362e-08
+7.603000319e-08
3.370076910e-09
1.449987618e-11
4.711965187e-08
4.729467396e-07
1.929793020e-11
8.523475458e-11
7.387954245e-07
1.080040278e-10
2.281110242e-08
1.166677915e-01
1.409613611e-06
-1.147187181e-06
+7.465324675e-07
2.672310396e-07
1.255071010e-04
6.229838431e-04
-6.419598350e-10
+8.214274894e-10
1.064850629e-05
1.156380518e-08
4.852815617e-07
6.863856159e-14
7.264596037e-08
8.284444693e-05
3.088627657e-05
-6.018435532e-07
+5.519476722e-06
2.429391340e-10
1.743400033e-05
-7.000642750e-05
+1.652318468e-04
1.477860697e-09
3.426271735e-03
4.850294661e-05
3.693472519e-09
8.188840272e-10
3.134182902e-04
4.963596239e-05
1.459290217e-09
2.466456916e-11
5.230009936e-05
1.211786947e-04
5.437715515e-05
1.641328630e-06
1.042738834e-09
9.306578287e-07
2.233023059e-06
6.994767103e-09
5.103840066e-08
2.180291056e-08
1.054043488e-05
1.337487784e-04
7.502939118e-07
5.169726504e-06
1.781680794e-08
1.074536464e-10
2.730551306e-05
2.550106620e-02
3.354202915e-03
9.945180494e-08
3.884971018e-03
1.801945180e-12
1.090804491e+01
6.883835961e-04
-5.290759535e-07
+3.214869326e-06
7.522574713e-09
-3.280439980e-08
+6.387909440e-08
diff --git a/t/ME_data/ME_h_mtinf_virt.dat b/t/ME_data/ME_h_mtinf_virt.dat
index 6c9d9b3..15b809f 100644
--- a/t/ME_data/ME_h_mtinf_virt.dat
+++ b/t/ME_data/ME_h_mtinf_virt.dat
@@ -1,807 +1,807 @@
1.662434134e-02
-7.179001689e-01
+5.094808515e-02
4.047656957e-02
4.258285649e-04
5.425059975e-03
-2.131431630e-01
+5.398339963e-02
1.935053583e-02
-6.205040683e-01
+1.985342330e-01
1.000735040e-01
-3.419058888e-01
+1.232353959e-02
6.317599788e-04
1.075071246e-01
-3.104929693e-02
+2.890445769e-03
5.546156527e-04
4.290558797e-02
6.743811354e-03
8.867310363e-02
1.009432049e-04
1.774946232e-01
-2.888731980e-02
+2.835060534e-02
1.579852552e-03
1.108657204e-02
9.101156921e-02
-4.445385064e-01
-3.502383374e-01
+1.731232097e-02
+3.854173093e-02
2.442661850e-01
2.987071936e-04
-6.309631317e-01
+3.177985783e-01
2.339375507e-04
1.046709758e-01
2.366621580e-04
2.175004336e-02
5.267296331e-01
-5.935927351e-01
+7.162693561e-03
8.209691120e-04
8.421862974e-02
3.046140179e-02
-2.249239021e-01
+4.533775022e-02
1.611542204e-01
-6.185086449e-02
+3.572091976e-02
1.623488231e-02
2.472192563e-02
-4.131822125e-01
-4.818948365e-01
+7.199516606e-04
+3.402356772e-02
2.838080364e-02
1.725504184e-04
-6.406424077e-03
+5.017443000e-03
3.486267176e-01
5.792798710e-03
2.955242958e-03
-6.504845272e-02
-1.449764000e-01
+6.712455828e-03
+1.901943625e-02
9.498299000e-02
-1.574758418e-01
-4.272544994e-01
+9.472197027e-03
+1.503324628e-04
4.274650836e-03
2.911726242e-04
-1.606533434e-01
+1.698656550e-02
1.408889180e-02
1.428671716e-03
-3.758874066e-01
-2.412059029e-01
+1.994027024e-01
+1.338215399e-02
2.209780599e-04
-2.052478202e-01
+4.426474853e-03
1.546352079e-01
-1.669080655e-01
-3.039886236e-01
+5.513306391e-02
+1.053040629e-01
9.541365334e-02
1.478568963e-01
1.397725796e-03
1.072960511e-02
2.472713471e-03
1.595930736e-03
1.608290600e-03
5.912331181e-05
-3.467767171e-01
+2.687269690e-01
1.376152960e-02
6.029696792e-01
4.869540421e-03
-3.559515345e-01
+7.941180984e-02
3.429371904e-02
7.916499288e-03
4.034951072e-05
1.389880183e-01
1.851541133e-02
-9.685971789e-02
+4.349725922e-02
4.138558845e-02
-2.112585732e-02
+8.933440913e-03
6.079785877e-01
-6.691592442e-02
-1.242388922e-01
+3.975030259e-02
+2.943089481e-04
1.017697497e-02
-1.150165441e-01
-4.757460371e-01
+1.322019738e-03
+9.793136168e-02
1.898779876e-03
1.673489565e-03
4.725329175e-03
-6.632284400e-02
-4.387965748e-01
+2.696809387e-02
+1.608309036e-02
3.717107060e-02
1.529220023e-03
-2.929795689e-02
-5.561341000e-01
-2.550681536e-02
+2.148446904e-02
+7.176925820e-03
+3.747484388e-03
1.516893606e-03
3.616785056e-03
-9.637438736e-01
-4.705742090e-01
+2.809709221e-01
+1.088846779e-02
5.818800779e-02
1.980490615e-01
5.257075136e-02
2.849260669e-05
2.013523423e-03
-2.793346797e-02
-1.286478400e-02
+1.247479922e-03
+1.458193296e-03
9.224129796e-02
-1.655755265e-01
+1.436902558e-02
2.133089414e-03
-4.307483761e-02
+1.038843870e-02
3.904253638e-02
-1.383494338e-01
+1.282565453e-01
8.503009334e-02
1.923850231e-04
1.922184204e-03
-2.752991666e-01
-2.820333776e-01
+4.334328092e-03
+9.363901406e-03
2.977758805e-04
3.178480355e-03
-3.593690812e-01
-1.023852419e-01
+2.795544294e-01
+4.286972306e-02
3.868514220e-01
-1.375480981e-01
+1.030554798e-01
8.196974805e-03
-1.699166028e-01
+9.020573187e-02
1.141797028e-02
-5.355620996e-02
+1.498878980e-02
7.469041444e-03
3.482547619e-05
1.922575361e-02
3.997662889e-04
2.430022988e-03
-8.388910742e-02
+2.537707998e-02
1.542591393e-03
-6.466218835e-03
+8.216289169e-04
4.360360577e-02
2.639980287e-01
-6.976705056e-01
+4.194379792e-02
2.445817664e-04
-4.985256463e-01
+2.736751505e-02
6.123171489e-01
5.214181065e-04
1.797783192e-01
4.763232790e-03
-1.254447362e-01
+2.987625662e-02
3.406351353e-02
-1.545232336e-02
+9.318213341e-04
7.170262090e-02
-1.478486185e-02
+6.634604337e-03
2.166474880e-04
-8.057168178e-01
-2.021759239e-01
+2.704620275e-03
+1.226852547e-01
1.217796493e-03
5.522586186e-04
-1.168431672e-01
-1.769803536e-02
-8.715824941e-02
+2.062659176e-02
+4.986017381e-03
+5.442651492e-02
9.065006160e-04
7.777267158e-02
4.362541932e-03
3.193981557e-02
7.985428220e-03
-2.673105795e-01
+2.193500661e-01
3.081776622e-05
7.124810363e-01
2.276144578e-02
1.453381751e-02
-5.462736385e-01
-3.137173986e-01
+1.479389888e-02
+2.488684688e-02
2.403359478e-02
9.432341629e-01
1.164091088e-01
-6.377777246e-01
-7.432896682e-03
+4.409425721e-03
+2.183298095e-03
6.406616198e-04
-2.228262290e-03
-6.914282213e-02
+1.348240343e-03
+2.730775338e-02
6.563846996e-02
-1.457776778e-01
+4.611484278e-03
6.710999568e-03
4.747693247e-04
-7.454026318e-02
+2.788190186e-03
4.040004254e-02
5.353037028e-01
1.489246287e-03
-4.812923223e-03
-6.616056685e-01
+5.677416249e-04
+1.299247746e-01
2.000243406e-03
2.168409472e-02
-7.190623906e-01
+4.994090747e-01
2.041516624e-02
5.764901820e-02
-9.582378175e-01
-8.574017198e-02
+1.083222132e-01
+1.778403334e-02
1.475952836e-01
2.706760046e-02
-3.948608926e-01
+1.753716873e-03
6.184248381e-02
-1.198790379e-02
-2.927898557e-02
-6.302401225e-01
-2.990972263e-02
+4.916075105e-03
+1.402646854e-02
+4.955500832e-03
+4.405969646e-04
3.153495592e-01
-3.790112331e-01
+2.856209721e-01
4.833412149e-01
9.792567062e-01
1.380454768e-02
4.950955418e-03
2.415531168e-01
7.405146937e-05
-7.297029393e-03
-1.180961543e-01
+3.499524824e-04
+5.472610522e-02
4.594530257e-04
-8.456272826e-01
+3.017333290e-02
5.519880329e-02
3.346307876e-02
1.696729309e-01
3.626388978e-04
4.279781398e-03
-7.725437944e-01
-6.344602462e-01
-1.744206506e-02
-1.995964494e-01
+3.440124036e-04
+5.122935764e-02
+9.478357284e-03
+5.099522018e-02
1.904959469e-01
9.978631993e-05
-8.064741515e-01
+5.056319751e-02
4.686487455e-03
7.780870502e-03
1.697444115e-02
8.903400434e-04
1.016659849e-02
5.345577770e-03
-9.323969260e-02
-6.854107785e-02
+4.534476427e-02
+1.583695461e-03
1.238468734e-01
2.733561451e-03
4.776707616e-03
3.424964841e-02
1.847470254e-02
-3.746716490e-01
-4.232343574e-03
-1.948348938e-02
-1.883200179e-01
-3.510525172e-01
-2.978681231e-01
+2.460546841e-02
+3.766803779e-04
+1.699471874e-02
+3.688197512e-02
+1.562444421e-01
+5.484706446e-03
8.860377516e-03
9.794958374e-04
4.579022969e-03
7.907947246e-02
1.732720476e-04
1.662571510e-03
6.397885031e-02
4.139767188e-04
1.569915946e-03
1.262721752e-03
4.715127079e-05
7.300127451e-05
3.750162158e-01
1.609615894e-01
-9.388845166e-02
-8.496015731e-02
+3.402326985e-02
+5.289014144e-02
2.440082263e-02
3.865766974e-03
4.588895181e-03
8.922905707e-03
1.435473885e-01
3.129173765e-04
-1.031668826e-01
+1.540618556e-02
3.546180940e-03
2.824149080e-02
2.734099419e-03
2.401911574e-02
4.070680353e-03
-1.978157319e-01
-3.675801759e-03
+4.688710365e-02
+2.965124851e-03
9.828397496e-04
2.082536237e-03
1.297062007e-04
7.604274803e-05
1.254935753e-02
-7.493431516e-02
-2.785103593e-01
+1.222464432e-03
+1.747654656e-01
4.724543628e-03
2.868421366e-04
2.130119508e-03
2.666435530e-02
1.202544120e-04
3.755804814e-04
-1.612228807e-02
+1.880045539e-03
2.249928765e-02
2.857726966e-02
-2.712333552e-02
-9.530028900e-03
+1.051680383e-02
+1.327115032e-03
7.159465984e-04
2.315950653e-04
6.843092104e-02
1.605973149e-04
3.810087733e-04
6.942607321e-02
7.022608395e-02
5.897558290e-03
4.348479355e-04
-1.055977044e-01
+2.405536534e-02
3.182152803e-03
5.043804569e-04
1.151170603e-03
3.623570705e-05
1.531825217e-04
-2.221916741e-02
-6.318564649e-01
+2.420674926e-03
+1.917368194e-02
7.375309280e-01
1.858449733e-02
1.011822529e-02
8.282015437e-04
1.849249390e-02
4.099815695e-03
1.657148851e-03
2.055013352e-03
-3.345175543e-01
+9.341496606e-03
5.038823484e-03
3.305900619e-01
2.618444599e-01
-3.235484984e-02
+4.254386052e-03
5.750448500e-03
1.207241511e-02
1.944498271e-02
1.128432458e-03
1.145803530e-02
3.221366185e-03
3.700258890e-02
-9.862719127e-01
+3.321430469e-02
1.297665139e-02
6.972757114e-02
1.105185658e-03
2.404730886e-05
1.127528807e-05
1.053432798e-04
1.021238928e-02
1.040564122e-03
1.157619411e-03
-4.619523167e-01
+2.399009531e-01
5.373022340e-03
2.255674674e-01
3.913467938e-04
1.498837318e-02
-2.841407679e-01
+2.103074416e-03
1.628480065e-03
-2.637858282e-01
+6.895423276e-03
1.581537808e-04
5.316496151e-04
2.827646304e-02
7.840835924e-02
3.802476842e-02
1.169523762e-03
1.472988643e-03
1.567068288e-03
7.788469446e-01
5.293213363e-04
3.617100391e-01
2.497724876e-02
4.498337160e-03
2.523710280e-02
-2.190801240e-02
+1.328892997e-02
1.509021590e-01
1.827836358e-02
9.839386242e-02
2.790677338e-04
4.535503747e-04
1.795417855e-02
-9.891511483e-03
-2.025449002e-01
+8.547466736e-03
+1.075563874e-01
1.650548963e-03
6.466716979e-04
-7.798591624e-03
+1.037204853e-03
1.399544318e-01
4.358483901e-05
-3.518734048e-02
+1.211060469e-02
9.925955900e-02
4.196046439e-03
5.740642150e-04
1.385585035e-01
-9.726045511e-01
+3.065927901e-03
4.711886641e-04
-2.120674696e-02
+1.318592010e-03
2.744896126e-04
2.733755078e-02
8.886521659e-04
2.573475004e-02
5.177200640e-03
1.325380956e-03
-2.224279000e-01
+5.830237783e-04
2.541221083e-05
2.234868643e-04
2.980094645e-03
1.085417483e-04
2.507421970e-02
5.557187841e-03
1.337517782e-04
6.048457270e-01
1.628400435e-03
1.960703811e-03
8.853583057e-02
2.400504214e-01
3.893588292e-03
1.067030752e-03
2.587486305e-01
1.021079152e-01
1.568823857e-04
1.232537413e-04
3.344933587e-01
6.391243589e-02
-5.493786631e-02
+7.685330484e-03
7.668901925e-04
-1.831019857e-01
-3.264190974e-01
+9.428709497e-03
+1.595015137e-01
1.821006486e-02
9.862857859e-03
9.247421843e-03
4.001284410e-03
-1.282729585e-01
+7.458514203e-02
2.559792170e-02
1.377360771e-03
-2.021404313e-02
+7.235253509e-03
4.915884552e-04
6.280309444e-03
3.739034133e-02
2.336495032e-03
9.862448357e-02
4.374356376e-04
1.522931694e-03
9.926315542e-04
5.912839518e-02
-3.328358881e-02
+1.140101312e-02
5.314503463e-04
6.066121274e-03
4.885794392e-04
-1.778552165e-02
-4.411282075e-03
+1.617881896e-04
+1.771936970e-03
9.882057680e-02
9.729080864e-03
8.224878130e-02
6.529525098e-04
1.000583457e-03
1.255082254e-03
1.565280913e-03
4.412219315e-04
1.868727611e-02
2.355505526e-03
4.585964050e-04
2.807981351e-03
1.379690186e-01
-7.548897273e-01
+7.320412882e-03
2.172144174e-03
4.146132284e-02
2.416044385e-04
5.492820394e-05
-7.254353535e-01
+7.099674996e-03
7.227046121e-03
1.212496579e-04
4.932499798e-01
4.072325551e-01
6.070046021e-03
7.603198964e-03
1.023817101e-02
4.684971694e-03
-9.603036790e-03
+5.659062453e-03
7.897219074e-04
8.646854292e-04
1.303911975e-02
1.173291393e-02
9.463395508e-04
6.406806121e-03
1.045590023e-02
1.477670437e-03
4.659680958e-04
-2.284200248e-01
+4.942136817e-02
1.627265716e-02
2.358607556e-03
1.041835449e-02
7.605665203e-03
8.295297276e-03
-9.011152387e-02
+6.281877723e-02
1.579648534e-04
-3.452192249e-02
+2.436798903e-02
2.258745587e-03
1.339614977e-03
6.268145402e-02
2.287427586e-04
6.670205183e-04
6.295945427e-04
1.047076716e-03
-7.862129702e-03
+3.855642279e-03
1.627037464e-03
1.085642139e-03
2.450576186e-04
4.325909623e-03
9.887935475e-04
1.120014728e-03
-2.299102575e-01
+2.589558898e-02
7.798056920e-02
-9.313587733e-04
+2.894863797e-04
1.607891099e-02
1.461741141e-04
3.285469885e-03
1.923714268e-04
7.825726617e-04
7.844056580e-02
1.063621464e-01
1.835956497e-03
7.012371335e-03
7.733193546e-02
4.751473890e-04
1.445122469e-03
1.790609649e-01
1.104322850e-01
-6.971452481e-01
+3.731945505e-01
2.283139583e-01
4.105267608e-03
2.030571555e-02
-8.379750836e-02
+6.680721508e-02
6.662905023e-04
9.339295832e-03
-5.982429994e-03
-1.566551104e-02
-6.001459464e-03
+1.031780169e-03
+5.491676565e-03
+1.306271249e-03
2.544421692e-03
1.599062038e-01
9.149373265e-03
4.314134536e-04
5.541644114e-02
3.367313015e-02
3.709605034e-02
1.282720396e-04
5.696033980e-03
1.137165113e-04
2.823374393e-04
1.019789435e-02
2.347228181e-01
9.696148743e-05
2.771961442e-04
1.552084835e-02
1.503179616e-03
2.432302343e-03
2.982754839e-05
1.151577771e-03
1.254294922e-04
7.836601643e-04
3.348416742e-04
2.464638218e-05
3.197152304e-02
-1.074535067e-02
+2.380579247e-03
7.736052385e-05
1.592110793e-02
5.490777825e-04
6.703585044e-03
1.727924499e-04
1.741575849e-04
5.452982555e-02
5.831692799e-04
1.229952442e-05
3.539469847e-03
2.607273237e-04
-1.155064850e-01
+6.726510564e-03
5.560200161e-03
7.868848508e-03
-2.839605674e-02
+8.607832503e-03
9.286277490e-04
6.722928183e-04
7.479941370e-03
-4.624492020e-02
+1.037835517e-02
1.763557921e-03
3.859415223e-03
5.376937753e-03
7.573258544e-02
9.966446732e-04
-2.074748973e-02
-2.470811114e-02
+1.372415147e-02
+3.618653413e-03
4.816987613e-04
6.172620056e-03
5.145999410e-04
-9.955639047e-03
+7.645173902e-03
1.870918895e-03
5.094807535e-03
1.522245621e-03
3.905821945e-02
2.291404811e-03
-1.997836326e-02
+9.615492432e-03
1.040190519e-04
7.933156157e-05
2.861476976e-04
3.092530664e-05
1.009959121e-04
4.798974528e-05
1.520447973e-04
4.293922371e-04
1.495813760e-02
2.067872354e-02
8.001478215e-04
5.922758669e-02
7.003930234e-03
9.811017307e-04
8.714286890e-04
7.030946920e-04
2.783539812e-03
3.356779523e-04
1.872068978e-03
1.791636322e-03
9.610612235e-04
2.720559686e-03
1.381430586e-02
1.987094067e-03
1.535495013e-03
6.225685945e-05
4.433970578e-02
6.204235315e-04
2.523318570e-04
2.693081300e-04
-1.152759369e-02
+9.806847286e-03
1.115446730e-04
1.913927645e-03
3.812673725e-03
7.992870192e-04
4.819914195e-04
1.326334606e-02
9.150214882e-03
1.034923254e-03
2.347420876e-02
1.434995974e-04
1.618551910e-01
1.138096890e-02
-4.841132315e-03
-6.356781164e-03
+1.362829834e-03
+5.920844312e-04
4.181369809e-04
1.055011334e-03
-4.345832279e-02
-9.427869339e-03
+3.763325257e-02
+4.328453615e-03
8.692281125e-04
6.404647105e-03
1.440468332e-03
6.533070573e-04
3.067013257e-03
6.119505082e-05
4.871597119e-03
1.167597899e-02
5.286978607e-03
1.168304721e-03
-3.195194363e-03
+2.522114150e-04
4.692840229e-03
3.244356462e-02
1.771613526e-04
2.417265143e-02
4.526476236e-03
3.609663100e-02
3.201253089e-03
1.422131247e-04
4.107992628e-04
3.640091047e-04
-4.052632976e-02
+4.205926535e-03
1.727094259e-03
2.931243298e-03
9.528080981e-03
8.693893929e-05
1.052636987e-02
8.635645831e-06
1.028852028e-04
-2.752513702e-02
+8.376589251e-03
1.926992609e-01
5.295740367e-03
9.496124624e-05
2.658753395e-04
4.600035093e-05
1.451066601e-01
1.287738200e-03
1.316052550e-04
2.314882542e-03
3.039318518e-03
1.612809171e-05
2.475950491e-03
5.011890845e-05
2.103581465e-03
2.631043318e-01
5.905271134e-04
1.190444890e-03
-3.450493161e-03
+2.331892332e-05
1.735567184e-03
8.522507949e-02
-6.485287653e-02
+2.022844484e-03
6.009262732e-03
1.073098231e-04
1.233283828e-02
6.967474866e-04
1.337538219e-04
9.460554120e-05
-6.966340638e-02
+2.329675422e-02
5.414308727e-04
8.353409363e-04
7.030802856e-05
4.649538434e-03
2.481942715e-03
5.198360343e-04
3.813525743e-05
5.541009041e-04
-1.164648000e-03
+1.138085574e-04
2.108421633e-03
3.072143688e-03
-4.096663968e-03
+2.478250133e-03
2.142925594e-04
8.282696553e-04
2.141595960e-01
1.257814795e-04
2.479992306e-04
6.612276130e-05
1.030099210e-01
8.378285098e-04
1.717800833e-04
1.121693081e-04
-7.059167817e-01
+3.219168307e-01
3.183689592e-05
-1.136012383e-02
+2.973388087e-03
1.389159215e-04
1.213668521e-03
1.951618357e-02
7.273993708e-04
8.289325503e-04
5.201497164e-05
6.417142536e-03
5.989693465e-04
3.521172593e-03
1.543364684e-04
3.027365071e-03
3.633571410e-03
2.694407012e-02
1.596312599e-03
7.388525320e-03
-7.270074311e-03
+6.914299659e-03
1.153674200e-03
8.050028829e-04
6.310288562e-05
1.820969893e-04
1.788876040e-02
2.815731475e-02
6.876553655e-03
1.769950662e-03
4.868440995e-04
2.029503564e-04
2.348604422e-04
-1.768732060e-02
+1.511629275e-02
4.002865616e-05
9.006700615e-05
1.874263398e-04
-1.151513191e-01
+4.841893603e-02
8.768519164e-04
1.969842086e-02
9.049122110e-04
3.171339370e-03
1.571292573e-02
2.434681979e-05
2.073516830e-04
-9.260435540e-02
+2.632748098e-02
1.430061521e-03
8.010243139e-04
-5.001021857e-02
+8.996415531e-03
4.820875890e-03
8.675277648e-04
1.168299161e-05
3.996242653e-04
3.247712141e-04
1.248197243e-03
1.402060723e-03
8.461155321e-03
5.525286920e-03
2.916254992e-04
9.455326671e-04
2.424023635e-03
2.268929854e-02
2.603439368e-02
7.525254743e-04
1.091868444e-04
1.225143925e-02
5.940794641e-03
2.381508909e-02
1.629011570e-04
1.976777177e-03
1.078398636e-03
1.742649129e-03
3.639814812e-03
2.077161633e-01
7.741577089e-05
1.740198496e-03
4.600610458e-03
1.285713314e-04
8.803561357e-05
3.512651140e-02
2.464097081e-04
1.504942292e-02
-4.573814804e-02
+8.511577233e-04
8.764887373e-04
-2.763484081e-02
+1.328903612e-02
diff --git a/t/ME_data/ME_h_mtmb_tree.dat b/t/ME_data/ME_h_mtmb_tree.dat
index 0ba3603..e7ecddd 100644
--- a/t/ME_data/ME_h_mtmb_tree.dat
+++ b/t/ME_data/ME_h_mtmb_tree.dat
@@ -1,807 +1,807 @@
4.036423148e-08
-3.940695462e-05
+7.736848255e-06
3.971238751e-05
1.704916390e-02
4.126163153e-06
-4.120221319e-07
+1.244041497e-06
6.515738458e-07
-7.794000157e-07
+3.772873174e-07
6.202166544e-07
-2.273189686e-05
+1.155213750e-05
4.920813253e-05
1.645597849e-06
-5.308682891e-04
+7.506762262e-04
1.548455272e-05
9.714753846e-06
3.502266406e-02
8.370742698e-07
6.069969581e+02
6.064159817e-06
-1.379402693e-02
+3.997354744e-03
1.960086246e+00
5.767474795e-04
8.255987630e-04
-3.390595917e-05
-7.438763677e-04
+4.405908649e-05
+6.886558057e-05
7.109077582e-04
3.938946000e-02
-1.058566813e-06
+5.645949929e-07
1.999418757e+00
9.091732441e-08
4.795920875e-02
1.076748080e-01
9.486837249e-07
-7.638363821e-03
+8.516572195e-03
2.337001022e-02
3.677679730e-05
6.849081872e-07
-5.390885072e-03
+4.798561314e-05
7.633470907e-05
-5.345400607e-03
+5.443857683e-03
6.189558681e-04
8.432994191e-03
-3.442253987e-03
-3.843951823e-05
+4.672976133e-03
+3.181209897e-05
1.543375743e-04
5.581577133e-03
-3.950854564e-02
+1.162158738e-01
2.346338154e-07
5.658368514e-05
8.586756438e+00
-1.916769456e-04
-7.218548577e-06
+1.719104149e-04
+4.667893099e-06
5.110672307e-06
-1.477663167e-04
-2.103313165e-01
+1.176205927e-04
+1.615939616e-01
2.423820202e-02
4.531340391e+00
-2.719470313e-04
+1.656996369e-04
1.312005381e+00
5.118439829e-03
-2.732686015e-06
-7.187306762e-02
+3.738025342e-07
+1.939569545e-01
2.872395003e-03
-7.193746078e+00
+2.523364268e+01
7.307477806e-08
-4.677914766e-06
-1.913225677e-05
+1.182185461e-06
+1.726278033e-05
1.558401995e-05
1.125457825e-06
9.938467298e-04
9.305719108e-07
2.351577836e+00
1.351848038e-03
1.604570791e-03
2.725148428e+04
-1.234759714e-06
+7.412335698e-07
6.959827491e-04
1.069546678e-07
2.002109665e-02
-1.958000049e-06
+9.407629686e-07
4.452818467e-05
2.597028907e-02
5.063411137e+04
5.471108411e-06
1.074665005e-06
-2.864245369e-06
+1.953754359e-06
1.070605830e-04
-2.289704455e-04
+2.122044377e-04
8.007807626e-08
-2.693200621e-03
-5.984302131e-04
+1.917291689e-03
+8.268370687e-04
7.711293504e-02
-1.369089840e-03
-6.589295759e-05
+1.492536307e-03
+1.071633305e-04
1.177180255e-01
1.871326492e-01
1.153295778e-04
-1.879598427e-05
-2.690894990e-02
+2.018590409e-05
+1.685105258e-02
1.085933997e-03
5.144887011e-06
-1.054704620e-01
-9.467940750e-05
-9.451233173e+01
+9.170297842e-03
+1.498081308e-04
+4.490357270e+01
2.029765471e-02
9.076488466e-05
-3.660807690e-06
-3.293606172e-04
+2.112793665e-06
+5.733726407e-04
1.320311226e-04
1.191386384e-06
1.341747592e-04
3.090047756e+03
1.403839816e+00
-8.913504370e-02
-3.586958366e+01
+1.348365292e-01
+6.976034882e+01
1.822509069e-06
-1.040930061e-05
+8.389617599e-06
1.663315754e-03
-1.266898109e+00
+3.881812041e-01
3.675662279e-04
-2.785066676e-06
+2.193350704e-06
4.832687364e-06
1.726784601e-03
3.288072256e-01
-9.498002614e-04
-8.414617436e-02
+1.058019447e-03
+2.649402107e-02
2.659712131e-01
2.787024900e-02
-3.083583490e-06
-2.873679676e-03
+1.379286015e-06
+2.695898486e-03
1.905511571e-06
-1.790088684e-06
+9.134022595e-07
2.337835933e-05
-1.351489964e-05
+1.239190539e-05
2.913100451e-02
-1.547540316e-04
+2.031913258e-05
6.089047514e+00
4.379840484e+08
3.001194264e-04
1.817496329e+02
1.164476362e+00
-5.011329237e-06
+6.037065388e-06
2.985758357e-02
-1.276801201e+01
+3.897328667e+00
5.979372364e-04
1.243000641e-06
-5.844423344e-05
+4.662882332e-05
7.282185572e-01
-3.584110205e-04
+3.504619995e-05
1.111648768e-07
7.823789154e-04
3.486592726e-06
1.934888323e-03
-1.738847775e+00
+1.308230506e+00
6.783546728e-04
-4.470619232e+02
+1.348969537e+03
1.500005936e-05
-3.990822914e-03
+1.928319674e-03
5.562357380e-03
-1.002281688e-05
-2.692339517e-03
+5.621101723e-06
+8.246921080e-04
4.261028205e-02
1.835360553e-05
-8.668223263e-04
-2.014791060e+00
-2.248997227e-06
+1.528438303e-03
+1.777310709e+00
+1.669709876e-06
1.986324999e-04
6.578850492e-05
4.502179572e+02
8.855059478e-05
3.237727416e-03
-3.182235485e-07
+1.093420259e-07
1.106011705e-01
1.143715836e-07
5.522698510e-06
6.890923645e-06
-2.672771798e-03
-5.045078327e-03
+6.344507843e-04
+1.269294480e-02
2.462746837e-05
3.856346551e-08
5.216536125e-06
-1.050167951e-04
-1.367775165e+04
+1.863505340e-04
+1.442680698e+04
1.186670853e+02
-3.979706551e+02
-2.281946477e-01
+4.278422020e+02
+2.095186222e-01
2.351156237e-06
-1.048852232e-04
+7.769821656e-05
4.845925968e-03
4.408732612e-01
-1.112548897e-04
+7.856962492e-05
2.011543913e-06
2.266763426e-07
3.059571023e-05
-3.689019494e-01
-7.844255620e-06
+1.976840415e-01
+1.959921970e-06
5.025542164e-03
5.486520955e-04
-1.075092826e-07
+1.779895054e-08
1.132860013e-05
2.213263103e-06
-4.938232858e-06
-7.616499860e-03
+2.140323057e-06
+8.024798285e-03
5.859877168e-05
1.934315184e-06
-2.304443733e-03
+1.572922025e-03
7.553653114e-03
-9.696050391e-02
-7.884528318e-02
-1.348357805e-03
-1.357842010e-04
+9.536373201e-02
+6.279598035e-02
+7.474807797e-04
+1.593545482e-04
3.141317968e-07
-6.709252930e-07
+2.051394799e-07
2.303965173e-07
1.399944656e-07
3.172292798e-04
3.244924593e-03
3.215239406e-07
5.351823628e-04
-1.165409009e+00
-1.698720114e-05
+1.027309294e+00
+8.824530406e-06
2.551101888e-05
-4.114120001e-06
+2.161795380e-06
4.567066262e-07
3.716863062e-05
6.613977572e-07
2.708492813e-03
1.754571252e-01
-1.525562358e-02
-2.519367322e-05
-1.040323131e-03
-2.111103983e-04
+1.139082627e-02
+6.013044846e-05
+1.166014558e-03
+3.185757265e-04
3.163729413e-06
1.195048391e+03
-9.442817960e-06
+4.939698613e-06
7.139106015e-07
4.701054611e-05
4.016940958e-06
3.392971071e-03
1.324572094e-02
1.809116765e-02
-1.068491608e-04
-8.801093474e-02
+1.201224212e-04
+1.084951107e-01
7.543629353e-07
3.144888884e-02
2.541618224e-07
1.081287052e-06
6.019085856e-04
-4.102207206e-06
-6.950122208e+01
-9.158826406e-06
-3.969242776e-05
-3.461103196e-06
-1.215029690e-01
+2.675294230e-06
+6.600651889e+01
+1.252990382e-05
+5.269572134e-05
+2.674339279e-06
+4.869941044e-02
1.388249177e-07
7.461768963e-03
3.402909074e-06
1.353552111e-08
8.196497731e-04
8.070767847e-08
5.530827384e-07
9.776453894e-07
1.114655452e-04
5.077992189e-03
1.369512011e-02
3.740658941e-10
1.781418456e-09
6.274192504e-10
-1.401209043e-08
-1.183617756e-05
+5.570736650e-08
+5.998642355e-07
1.097744907e-10
7.681004360e-06
1.642521973e-06
7.268695991e-08
8.422665758e-09
2.289208384e-08
-3.164564910e-07
+2.305737007e-07
7.734269324e-08
1.182053682e-07
6.038027033e-04
1.493672352e-05
1.355625923e-07
-3.951040786e-07
-7.931076516e-07
+2.538809292e-07
+6.882712050e-06
1.730384601e-02
1.844042121e-04
3.085693244e-06
2.260606209e+04
6.813153964e-02
-1.179740446e+00
-7.181881004e-07
+1.236180907e+00
+8.256080589e-06
8.815710180e-04
3.504735286e-01
1.700680109e-03
6.910992987e-07
1.043157794e+02
1.814172816e-06
-6.263269091e-03
+2.688688739e-03
2.976015172e-04
6.200943181e-03
-2.965807565e-07
-1.073076862e-05
+2.490212037e-07
+5.767096764e-05
5.990564946e-07
2.921459438e-03
1.391998767e-08
1.376391218e-06
2.868305907e-02
1.321869635e-09
7.854832125e+01
3.317601049e-06
2.896302554e-07
-4.433606537e-07
+3.610728411e-07
3.755558047e-04
1.885141400e-06
2.979456575e-07
2.644454811e-02
4.727532404e-04
-1.505876650e-03
-2.507321344e-08
+1.449586679e-04
+8.265261395e-08
2.401908115e-11
4.336051545e-07
1.411161765e-05
8.172635648e-07
2.133943837e-07
8.472465938e-07
2.378645368e-06
6.373870068e-02
-1.839733051e-07
+8.481958393e-06
2.196405434e-08
6.488703749e-10
1.367098502e-07
-5.025676102e-06
+6.253120021e-07
1.726155379e-05
1.028043800e-04
1.581189528e-02
1.714873385e+00
5.042793140e-10
1.167632099e-05
3.269051929e-07
-3.251831260e-10
+2.282660620e-09
2.489763266e-04
1.392964403e-06
5.023658342e-01
9.167250740e-05
2.647450934e-02
1.348673997e-02
7.683645278e-07
2.341732570e-04
3.779103872e-04
-1.907922842e-08
+1.672150123e-08
5.731777278e-07
2.491851220e-09
1.535566443e-04
2.338525694e-11
-1.730607356e-05
+8.326519940e-05
7.427438437e-09
-9.321434871e-06
+5.487384543e-06
5.356705978e-04
2.577249280e-02
6.339805093e-06
1.722225805e-08
7.949601147e-09
9.467943594e-03
4.124552284e-07
4.752378199e-03
6.855892451e-10
3.030134010e-03
6.111501060e-05
8.896968839e-08
7.036626305e-08
9.767086779e-08
-1.641504920e-05
+1.822106154e-04
5.167665362e-07
8.929765297e-08
1.041787025e-08
3.214441781e-07
4.278749951e+01
4.713220366e-03
-1.171095095e-05
-5.812379355e-08
+4.922173640e-05
+1.221758281e-07
3.435883898e-06
2.608975632e-07
-2.404695727e-03
+1.958829721e-03
1.308690410e-05
6.442728868e-02
-1.785133042e-08
+5.581195389e-08
2.426793708e-07
9.869946867e-05
3.931244362e-01
4.427447162e-07
-3.012213417e-08
+1.644106634e-06
3.937011867e-05
-1.030781975e-05
+6.637002401e-06
1.477893935e-06
4.793521076e-06
2.274482489e-07
2.426949341e-06
2.790263661e-04
1.411695733e-02
-1.718655950e-07
+5.610418560e-06
1.222952974e+00
1.841651984e+02
3.962193099e-02
7.575329958e-05
2.302985029e-04
2.986165595e-03
8.808106987e-03
5.367867416e-08
3.629488229e+02
6.565633407e-07
2.763279312e-07
8.792666186e-08
4.312444225e-07
2.084090097e-05
5.553313339e-08
1.824845466e-03
1.628190320e+01
8.032792019e+00
5.045965101e-12
1.309316910e-06
-3.447366362e-03
+2.125762884e-03
1.771992742e-05
-1.732654970e-06
-2.253917357e-04
+1.305278849e-06
+1.020519720e-05
9.285755927e-05
8.707117109e-05
2.458948201e-06
1.264146894e-04
-9.259005878e-09
+9.375340255e-08
2.612269543e-07
8.656036107e-04
-3.092116235e-01
+1.396060738e-01
6.541188422e-04
1.248762684e-07
4.828081916e-07
2.666096671e+02
2.779624128e-09
1.275654743e-11
1.622124438e-09
3.535882708e+01
8.637645168e-05
-4.779015648e-06
+3.316676713e-06
1.985078302e-05
3.769679004e-07
1.893519630e-08
-2.764248045e-02
-1.569774109e+01
+1.848731557e-02
+3.177966912e+01
2.898043591e-10
1.381188536e-06
9.778652394e-07
3.129079728e-04
1.006792969e-03
1.324187996e-05
4.670316575e-03
1.714481366e-02
9.746261540e-07
8.754150483e-06
8.871860946e-06
1.302177141e-03
6.687989253e-07
-5.658176860e-11
+3.629112534e-10
2.428070629e-01
1.652839606e-07
2.464020929e-04
2.376283608e-03
-7.577069770e-09
+4.862459470e-08
7.369154255e-12
2.187410343e-02
6.583332200e-09
7.586000565e-08
6.230704627e-04
2.301894399e-07
8.933274543e-07
1.742752087e-07
-3.464376873e-06
+2.329319180e-06
5.505250354e-08
4.664050600e-04
3.406810468e-10
9.055849938e-09
1.358011703e-01
2.511809081e-06
9.330572939e-06
7.547511867e-06
3.643813774e+00
-8.070569932e-06
+2.201783885e-05
4.812451470e-07
2.258393748e-07
2.233315236e-06
3.159599249e-07
1.438419527e-05
-2.656523503e-04
+8.216411210e-04
2.401748292e+01
-1.813967533e-08
+4.441039608e-09
4.182507375e-06
1.817768494e-03
4.358306112e-09
3.366166577e+06
9.748286443e-04
3.665246802e-02
5.257456411e-01
-4.936459997e-03
+6.787190103e-03
2.345660154e-06
6.085901852e-02
4.397967866e-04
2.027126088e-08
1.824801845e-04
3.284634641e-04
-6.255318133e-07
+4.443519448e-07
2.940093142e-08
-4.307129122e-02
+4.726548742e-02
8.679944530e-07
1.929082941e+01
3.427794650e-04
1.620709084e-07
4.976512597e-04
4.199111596e-07
6.038191476e-09
1.165738541e-02
5.973500915e-05
1.493338629e-08
3.492347166e-01
1.795227293e-06
1.037966149e-07
1.116776921e-08
-1.263951412e-08
+7.096793504e-09
3.063922251e-03
4.659880760e-06
6.685144842e-11
-3.344874212e-06
+1.337688011e-05
6.174930345e-02
4.874739894e-09
-1.108852165e-06
-3.950363917e-04
-6.789868863e-04
+1.806147160e-05
+4.631036657e-04
+1.022513411e-03
2.342719974e-04
4.323244263e-06
1.217044592e-07
1.076613707e-03
8.266921906e-06
1.764292648e-10
6.887713583e-08
6.045824798e+02
1.581575863e-07
4.321419033e-02
2.747231122e-08
5.176464067e-04
1.283947898e-10
2.635146077e-07
1.866099754e-06
1.077625828e-10
1.227034128e-07
3.462488088e-02
6.572734893e-04
3.682533741e-09
1.258102652e-05
1.039023360e-05
9.860921117e-06
2.764566092e-04
9.083830083e-09
-8.019616684e-07
+1.779107470e-07
3.309101491e-05
1.630414134e-11
3.408138743e-03
6.234054635e-08
3.798460345e-04
2.056820068e-04
3.723185048e-11
9.116442122e-09
2.047558303e-08
2.432333844e-08
4.876844945e-09
-3.729175624e-11
+3.792916630e-12
1.086734095e-07
2.678246345e-07
-3.699977967e-11
+3.737761942e-11
2.518544572e-02
3.543478653e-05
3.144209706e-09
-1.038332373e-09
+2.571078481e-08
2.905763262e-10
8.845631144e-06
5.299197118e-09
3.212858955e-11
1.574326626e-03
-6.902833399e-07
-2.553781901e-09
+6.260075096e-08
+2.849518253e-09
7.677924584e-10
1.019360586e-02
1.103600437e-06
-3.940498178e-06
+1.540425721e-06
3.727582277e-09
6.887332609e-09
1.302011294e-09
6.527101708e-12
3.443844857e-06
-4.187145645e-09
+1.066905832e-08
7.948118615e-05
6.284425219e-05
1.649790491e-06
7.173724647e-09
4.153972683e-10
2.405566428e+05
8.355925992e-03
8.745341043e-10
2.269492014e-10
3.309506110e-08
1.413945418e-06
2.232475177e-08
1.631049240e-08
4.510105717e-05
5.086183012e-04
1.988765291e-03
3.062340138e-05
5.993816281e-04
7.223618099e-06
6.919829161e-06
4.084309097e-06
5.317909021e-03
2.390820360e-09
9.926494617e-06
1.203124209e-08
1.587085982e-08
3.209965319e-11
3.730564190e-01
1.294323217e-09
4.525994100e-04
-1.229663713e-07
+1.578300749e-08
8.883022051e-07
7.242134641e-11
1.469712006e-06
2.146381110e-02
1.190600444e-02
4.002908719e-09
8.716239815e-09
1.439376814e-08
8.214348516e-10
7.841363574e-04
2.502302822e-12
2.237540399e-06
-3.060990927e-01
-1.042379315e-05
+4.601576463e-01
+1.010314456e-05
2.747503032e-09
3.152499662e-06
-1.213038341e-06
-4.561045660e-09
+2.220972872e-06
+1.617414124e-09
2.785775036e-08
3.505026909e-09
5.852871676e-06
6.930894599e-05
2.218608906e-07
8.336025248e-08
5.321324864e-07
6.957006774e-11
1.756920847e-06
9.201475866e-07
-1.862585228e-04
+5.293876717e-04
2.623905961e-03
6.200680271e-11
1.830818882e-04
7.754292544e-14
1.375087808e-08
1.089787443e-06
4.669668495e-07
7.929650811e-07
2.541277492e+00
7.548645527e-11
-3.792553481e-06
+2.866196441e-05
1.507840761e-07
3.976718923e-09
8.170369827e-09
1.244907359e-04
2.305047052e-11
1.868748852e-03
1.151371320e-02
-2.616767864e-06
+1.095371751e-06
4.685416671e-11
4.257552002e-10
4.676237105e-05
5.067525573e-04
7.631196519e-09
4.186397884e-13
2.672149954e-03
2.649317492e-08
6.788068043e-08
3.881131771e-11
2.442520598e-01
9.611315772e-08
2.532528157e-03
1.187572603e-11
1.653186265e-09
9.024678356e-08
3.482565421e-10
-6.545561410e-07
+1.724845600e-06
9.067490575e-07
8.135923216e-13
-1.312975615e-07
+9.086122702e-08
5.089372500e-08
3.779620535e-05
1.597856376e-06
4.649833682e-08
3.899419379e-05
2.385486151e-04
-8.272888822e-08
+3.509627138e-08
2.048011836e-10
1.598484276e-05
2.842204256e-06
4.300810814e-10
1.236712825e-09
9.724480523e-10
5.137729447e-06
1.206863564e-03
-3.205098174e-07
+2.997179873e-07
2.968956835e-06
3.892655757e-06
-1.871135757e-08
+7.966608049e-09
9.315475683e-06
4.685745597e-03
1.264393372e-11
1.651517618e-06
4.093555503e-04
6.291217780e-02
2.232241817e-12
1.581588279e-10
2.176076635e-01
2.778841978e-02
-1.933575772e-12
+4.020486964e-11
1.606840276e-03
-1.889515674e+00
+1.997885092e+00
8.696453002e-01
9.849266934e-02
5.923627073e-11
1.000520546e-11
5.484410290e-02
1.900079973e-04
6.710428134e-08
4.023506025e-07
9.262433958e-07
3.971033910e-04
2.798384077e-11
2.733321071e-04
5.949377984e-06
5.804131920e-04
4.149708488e-09
-5.189626516e-08
+7.157829015e-08
3.459693749e-09
8.152801222e-12
4.442083122e-08
4.885241039e-07
1.286023795e-11
9.146948664e-12
7.438541958e-07
3.933356062e-11
1.992948079e-08
1.233914164e-01
1.179935767e-06
-1.052253323e-06
+7.442591418e-07
2.614263483e-07
1.305318834e-04
4.563775945e-04
-6.061435715e-10
+8.536151068e-10
9.124754450e-06
1.181449830e-08
4.457412126e-07
1.105658535e-15
7.403561460e-08
6.857923072e-05
2.595980444e-06
-2.642703583e-07
+3.399059969e-06
2.275429709e-10
1.608232344e-05
-1.139157860e-04
+1.695525590e-04
1.471558450e-09
3.413025936e-03
4.519315643e-05
3.265308485e-09
7.421214523e-10
3.097172719e-04
4.702159026e-05
8.124970186e-10
6.737184939e-12
3.875912321e-05
8.002679747e-05
4.570485914e-05
1.372447479e-06
9.295972807e-10
9.091336789e-07
2.002021098e-06
4.844911625e-09
1.902794787e-08
1.566263784e-08
9.357485889e-06
1.048780982e-04
6.452709776e-07
4.085398049e-06
1.535693061e-08
9.742658204e-12
2.622006774e-05
2.375471653e-02
3.141422539e-03
5.474762658e-08
1.414376429e-03
1.609237488e-12
1.107110125e+01
7.034088451e-04
-3.105924621e-07
+3.207731210e-06
5.029108582e-09
-2.207617143e-08
+6.486744021e-08
diff --git a/t/ME_data/ME_hj_mt_tree.dat b/t/ME_data/ME_hj_mt_tree.dat
new file mode 100644
index 0000000..2ac4b39
--- /dev/null
+++ b/t/ME_data/ME_hj_mt_tree.dat
@@ -0,0 +1,1687 @@
+2.661319236e-05
+8.940615551e-04
+6.004167546e-01
+4.962078017e-05
+5.597200365e-03
+1.009948618e-02
+2.315139002e-01
+2.325999319e-06
+1.340132604e-04
+4.028562733e-03
+1.183898016e-01
+4.988972034e+00
+1.445162196e-01
+5.194905156e-01
+1.049933682e-04
+8.066756561e-03
+5.503611068e-04
+1.205014557e-05
+5.822520959e-02
+5.203461807e-04
+4.196592764e-01
+1.457185124e+00
+2.917142000e-02
+2.241517792e-03
+2.426777728e-04
+1.333737413e-04
+2.520947202e-03
+3.139586002e-05
+4.288770804e-03
+1.630311237e+02
+3.949132370e+01
+3.164214927e-02
+4.772686947e-05
+6.698816594e-05
+3.443310617e-04
+8.223003601e-04
+1.080208957e-02
+9.476943064e-05
+9.571932460e-05
+3.519276992e-04
+2.923775392e-03
+2.402237113e-03
+5.461786041e-02
+4.746279647e+01
+2.004481588e-04
+1.494813068e+00
+1.208613519e-02
+3.836976907e-01
+3.446570716e-03
+1.515333279e-01
+2.738202817e-01
+9.040698382e-05
+1.381054373e-02
+1.170911575e-04
+1.993100787e+01
+2.942037446e-04
+7.686560533e-04
+2.024388560e-01
+5.384562568e-05
+2.989072173e-03
+5.072893295e-03
+4.462889935e-03
+8.249756103e-01
+3.382968006e-02
+8.396168342e-04
+1.548373919e-04
+2.219626944e-04
+5.592157661e-04
+1.206401035e-04
+1.374143772e-04
+1.430183761e-04
+1.412597960e-03
+1.641416376e-04
+9.698220633e-04
+1.564987277e-04
+1.446058195e-04
+1.589217192e-04
+1.778440393e-02
+1.022192791e-01
+4.538538154e-02
+5.121606009e-05
+6.105528663e-03
+9.690901429e-05
+4.090287069e-05
+2.759644259e-02
+5.988336036e+02
+9.660400714e-03
+1.387909079e-01
+1.497790376e+03
+1.767900998e-04
+2.621313835e-05
+1.617763381e-04
+1.490044295e+01
+3.202244573e-04
+9.943546493e-05
+2.017568424e-04
+5.767995651e-05
+8.677184928e-05
+2.990817149e-05
+1.730479494e-04
+8.772930668e-05
+1.887845198e-02
+1.850895033e-02
+9.942594469e-05
+7.159966725e-04
+1.139635388e-04
+9.246189271e-05
+1.755589844e-03
+5.169547338e-05
+2.970053934e-03
+1.006489076e-03
+5.123611438e-01
+1.267179468e+00
+2.727911899e-01
+3.188942660e-03
+1.496988630e-04
+4.769274343e-01
+1.761678402e-03
+4.114643761e-05
+1.064098887e-04
+1.390233160e-01
+3.622119452e-02
+1.287634004e-02
+2.513203095e-03
+3.301387068e-03
+7.202887739e-04
+1.035836117e-03
+8.016682415e-05
+4.272859618e-04
+9.216592222e-05
+7.440784150e-03
+7.803818007e-02
+1.262378336e-01
+4.730584679e-04
+2.137941674e-02
+1.143200638e-04
+1.572528347e-04
+3.332583136e-04
+7.234187919e-03
+4.657478874e-04
+2.335000440e-04
+2.381263234e+00
+4.694991218e-05
+1.155601519e-04
+1.020744023e-04
+1.872001204e-02
+2.041429181e-03
+1.520362247e+01
+6.733425930e-01
+3.019947372e-05
+2.854568877e-04
+2.000525467e-03
+1.062546944e-04
+9.891749862e-04
+9.899289420e-03
+1.164133193e-04
+7.444377505e+01
+1.338229149e-04
+2.796443497e+03
+1.050171239e-03
+3.484247673e-05
+9.833177734e-05
+1.132268350e-02
+8.849300471e-05
+5.748723048e-06
+3.302543046e-04
+3.818378835e-05
+1.230606689e+01
+1.101824581e-03
+6.491576028e-04
+1.237898705e-04
+5.707908311e-05
+3.299964933e-05
+1.078701945e-04
+3.305449858e-02
+4.937719727e-02
+6.922541846e-02
+1.728325986e-04
+1.689022139e-03
+4.180232517e-05
+6.566173481e-04
+3.999200411e-05
+2.025673510e-04
+1.106325896e-04
+4.446047487e-05
+2.319202528e-04
+2.512992106e-04
+3.915958059e-04
+1.004311668e-03
+1.098788538e-02
+6.821741192e-04
+1.430816279e-02
+2.764400923e-04
+2.221336800e-04
+1.566187042e-04
+1.071433776e-04
+4.634569040e-05
+2.005068736e-03
+4.770661465e-03
+7.473726765e-04
+1.252337859e-04
+2.888605261e-03
+9.834925257e-03
+1.327905915e-01
+9.187986571e-03
+3.406744994e-03
+2.595512463e-03
+1.480789523e-03
+3.191225802e-02
+3.253135189e-05
+1.244794103e-04
+7.012125857e-03
+5.896288617e-02
+1.947236374e-04
+7.062868388e-01
+1.642829540e-01
+1.540627835e-03
+1.194994587e-02
+1.535686465e-02
+2.075933296e-02
+6.313540078e+00
+3.696290843e-04
+1.223725917e-04
+3.542531577e-03
+2.979195146e-05
+2.836390469e-06
+2.289671170e-03
+9.800275134e-03
+1.320112458e+00
+2.773809982e-04
+2.538157590e-03
+9.379551416e+01
+5.409254184e-03
+4.570693438e-03
+6.032333298e-05
+1.170658961e-02
+1.094801313e-03
+1.763693184e-02
+1.361396945e-03
+2.639008628e-01
+2.208141941e-04
+3.155546137e-03
+5.217712316e-05
+3.887083341e-02
+1.159375299e-03
+5.882303487e-05
+2.539251111e-04
+1.569527444e-02
+5.984963907e-04
+8.953471820e-05
+5.357985766e-02
+3.039919090e-04
+1.662384318e+00
+3.651008957e-05
+1.039696920e-03
+5.128188792e-01
+3.654439163e-03
+1.931664389e-04
+1.407062200e-04
+1.258726258e-03
+2.161174731e-04
+6.072121822e-04
+8.829947155e-04
+7.400718644e-04
+2.855920531e-05
+4.017185454e-04
+2.676511272e-03
+1.990710525e+00
+9.420677722e+00
+8.767874780e-01
+1.130170619e+00
+3.725437377e+01
+7.341849401e-05
+2.057619303e-01
+2.285735829e-04
+8.367194384e+02
+1.033878637e-04
+1.303613823e+00
+2.863353845e+00
+4.399662540e-04
+7.267686559e-04
+1.382911064e-04
+3.666573095e-03
+1.136592423e-02
+7.923789789e-05
+2.616992185e-02
+9.854429345e-05
+1.745498750e-01
+7.982865114e-03
+9.918732990e-05
+1.504984189e-04
+2.122380394e+01
+8.982051354e-02
+3.889901846e-03
+3.458347822e-08
+2.017176286e-04
+6.216509387e-01
+3.787288650e-03
+1.929294075e-02
+2.136195639e-04
+1.564115002e-03
+5.877152472e-03
+2.064191790e-04
+5.986965864e-02
+6.851185923e-01
+2.291240876e-04
+1.039761832e-01
+5.633437047e-05
+1.715240495e-04
+1.069047049e+00
+1.206180350e+01
+3.431448640e-04
+2.412636548e-04
+6.224619602e-06
+5.883555935e-04
+9.936412198e-03
+5.788656528e-03
+2.142335403e-02
+6.627341233e-05
+9.493955711e-03
+1.041101113e-03
+3.781107030e-01
+2.851648403e-02
+1.092473624e-02
+1.649167840e-01
+6.435885390e-05
+1.892813917e-04
+2.612286531e-04
+1.434880133e-04
+1.169872994e-01
+1.461184810e-04
+8.791272977e-04
+4.076097478e-03
+8.229101896e-03
+1.713900213e-04
+1.705242825e+00
+9.171959893e-04
+3.668967862e-03
+3.167536385e-02
+9.465259576e-03
+4.132589376e-03
+5.375426094e-01
+6.715413780e-05
+1.473625745e+00
+5.172272163e-05
+3.146332010e-03
+2.459035526e-04
+6.608755497e-03
+6.583699335e-02
+3.689932494e+00
+5.006373416e-05
+3.772854517e-04
+1.464300163e-04
+2.141827081e-03
+3.537345710e-03
+6.317434788e-02
+2.063089923e-02
+5.625693488e-05
+5.941467954e-04
+8.042533700e-04
+1.226636649e-02
+1.792591234e-04
+9.157865036e-01
+9.648738450e-01
+2.001556411e-02
+5.635506841e-04
+6.321256405e-04
+2.311950780e-02
+2.329663337e-01
+2.721037027e-04
+1.677477194e-03
+4.626005226e-03
+3.520712912e-05
+8.390982327e-02
+9.307163291e-05
+3.224184348e-04
+1.204872098e-04
+2.193368861e+04
+1.185274805e-03
+2.041883362e-04
+3.293327934e-05
+1.005486812e-02
+1.127959089e+00
+3.809470459e-04
+5.638572557e-02
+2.460146271e-02
+8.952441667e-05
+8.118018485e-02
+4.806888890e-04
+1.181390615e-04
+3.899642009e-04
+7.905169502e-04
+7.810697274e-05
+5.415544441e-03
+4.898403891e-03
+4.185276616e+00
+1.867982471e-01
+5.147865820e-01
+6.627953649e-01
+1.425116985e-04
+2.203884623e-04
+1.786376560e-03
+5.035471215e-05
+1.902085412e-02
+1.194449294e+00
+2.359963373e-05
+3.196746213e-03
+4.929014391e-02
+2.326484359e-05
+9.491948768e+02
+1.187419651e-04
+3.354621567e-04
+2.434912402e-03
+1.054668949e-04
+6.987605519e-04
+8.606250218e-05
+2.610424509e-05
+3.465094436e-05
+8.169434684e-04
+3.576380081e-04
+2.542199918e-05
+8.735783212e-03
+6.572673721e-03
+1.754108288e-03
+2.771488973e-06
+2.702271771e-05
+1.494519315e-02
+9.367667237e-05
+1.580270646e-01
+1.271272049e-01
+6.719076775e-05
+4.074498532e-04
+4.636001460e-04
+4.213958673e-02
+1.161753231e-04
+1.346056957e-04
+1.290069541e-04
+2.298263217e-02
+6.672240265e-05
+9.811948988e-02
+4.190257284e-05
+5.615452059e-03
+3.329493669e-01
+1.481991298e-04
+2.530425232e-02
+3.244262680e-05
+9.746550506e+02
+1.087376882e-02
+5.005250501e-05
+1.027817576e-05
+2.803078684e-04
+1.501196219e-04
+6.546908672e-05
+5.091917664e-02
+3.595532363e-04
+2.603204900e-01
+5.418962101e-05
+5.595939274e-04
+2.478801044e-05
+1.778180575e+01
+1.779987718e-02
+7.278908655e-05
+1.064041144e-03
+5.620075997e-03
+2.054758163e-04
+6.197819470e-02
+3.808481803e-02
+5.962621512e-03
+1.079297929e-04
+5.967715702e-05
+1.193322682e-03
+2.017049443e-04
+3.232429956e-05
+6.297601458e-04
+9.033388182e-05
+1.428570230e-04
+1.123647346e-04
+4.283248046e+05
+1.656848554e-03
+5.754566596e-04
+5.757389295e-04
+2.794557381e+00
+3.877786637e-04
+5.393386765e-03
+1.103587566e-04
+3.641623493e-05
+9.071912391e-05
+2.336195827e-03
+2.160268289e-03
+1.305639212e-04
+3.062055860e-04
+1.352604491e-04
+4.307863820e-03
+2.427256886e-04
+5.168404375e-06
+5.901072756e-04
+8.145297444e-03
+3.395358941e-01
+3.460346788e-04
+2.277447227e-01
+6.957760947e-01
+1.608121182e-03
+1.128810268e-04
+1.877839474e-01
+1.329860363e-02
+2.920225723e-04
+1.026950669e-03
+1.780620334e+01
+8.670922211e-03
+6.092735415e-04
+8.130774661e-02
+3.028231603e-04
+1.903810063e-04
+1.316114062e-04
+8.751736734e-05
+5.324899731e-04
+2.257165816e-02
+1.126581063e-01
+2.429873016e-05
+1.192025563e-04
+9.035971026e-04
+1.202799087e-04
+1.086936789e-03
+8.090525352e-04
+3.716642326e-01
+4.198488297e-03
+6.081505783e-04
+1.812362768e-04
+1.868143803e-04
+2.211132532e-03
+2.559822971e-02
+9.429915044e-04
+9.682323493e-05
+3.051833722e-05
+1.240958850e-04
+2.157971853e-02
+1.848599570e-04
+1.914879104e-04
+5.284164122e+00
+1.071389391e-02
+1.078062464e-04
+1.707221969e-01
+8.990987692e-02
+6.246747128e-01
+3.946780743e-04
+6.152273535e-04
+1.325911213e-04
+1.039220458e-03
+8.800047066e-04
+5.777294556e-05
+5.666763796e-02
+1.723874019e-03
+5.033996435e-04
+4.612608906e-04
+1.117058316e-02
+2.831152978e-04
+7.436537858e-05
+2.636540682e-02
+2.098348514e-04
+1.236411640e-04
+6.700797958e-05
+2.305440420e-02
+3.581738796e-04
+6.121483687e-02
+1.823684024e+01
+5.637843362e-03
+2.886486946e-05
+4.521791642e-04
+5.413542183e-03
+6.882562773e-03
+3.226228067e-03
+5.887166536e-02
+1.857383456e-04
+1.016005018e-02
+1.403339475e-03
+4.307017693e-05
+2.009856921e-01
+2.108613757e-04
+1.364438595e-04
+3.028396108e-04
+5.668877139e-02
+1.110469799e-03
+5.550242297e-01
+1.162658925e-02
+1.443858018e+02
+3.298590647e-01
+2.409652886e-03
+6.149813660e-05
+7.337678974e-01
+5.585267214e-04
+8.262716016e-05
+4.247737922e-02
+2.278196391e-05
+3.831891378e-03
+6.518166522e+02
+1.977457258e-04
+1.053921097e-01
+1.297727493e-04
+1.288254848e-03
+1.995143307e-01
+1.418092547e-01
+2.571280277e-02
+3.594993800e-03
+3.923230717e-02
+1.538973481e+01
+7.421099570e-04
+2.305454762e-02
+9.120093055e-05
+2.649427236e-04
+8.465260401e-03
+3.462780405e-03
+3.976713970e-04
+5.309524538e-02
+7.410099488e-04
+8.918050173e-03
+2.161592226e-04
+1.180292954e-04
+5.066939297e+00
+2.427099254e-04
+2.067585192e-04
+1.814006744e-03
+2.612907887e-04
+1.558178564e-04
+1.896899784e-03
+4.703744258e-03
+3.208097396e-02
+5.594684941e-03
+9.167990797e-05
+8.425617636e-05
+6.693678705e-02
+3.646091829e-05
+5.952662510e-01
+5.278262423e-05
+1.056258831e-04
+4.842385989e-04
+1.101834183e-04
+6.652811518e-03
+2.656195165e-04
+8.554424270e-01
+1.422189121e-04
+8.978476844e-05
+1.796483363e+02
+1.038138392e-04
+2.195514782e-02
+7.391281319e-05
+3.847421730e-02
+3.261019857e-03
+9.936798875e-03
+1.795495714e-04
+1.337933520e-03
+5.165519561e-04
+9.845578558e-02
+2.321586820e-04
+1.698366719e-02
+8.486593695e-03
+1.255501295e-04
+9.575862777e+02
+4.317233094e-01
+1.973475993e-03
+3.570871865e-03
+4.252113805e-05
+3.419014326e-04
+2.067766995e-04
+1.125374956e-01
+1.338473402e-04
+1.692497813e-05
+2.348453459e-02
+4.884105234e-04
+7.249768924e-05
+1.115209594e-03
+6.282966673e-02
+6.398356692e-02
+1.126137343e-04
+1.988956053e-04
+1.133676981e-04
+4.745781009e-05
+2.236671874e-01
+4.250663811e-06
+8.845659876e-06
+4.422585695e-04
+1.097078839e-04
+8.107299969e-02
+3.369983554e-04
+1.933728262e-06
+3.626222368e-03
+1.841904927e-01
+2.432071408e-03
+1.727869838e-04
+2.489288621e-05
+1.201153233e+01
+1.053412657e-04
+4.432241081e-05
+3.670737111e-04
+9.248004661e-05
+2.861126888e-04
+9.626101921e-05
+1.251144352e-04
+4.580260899e-06
+1.830272152e-03
+2.462713367e-02
+7.108661946e-04
+3.078583681e-04
+1.016242923e-04
+1.675279023e-04
+3.800616970e-03
+9.085431787e-05
+1.186134236e-04
+2.684684274e-02
+1.430149419e-02
+2.779106174e-05
+7.340754621e-04
+1.844010689e-02
+4.969047547e-05
+3.941865906e-04
+5.458287762e-05
+4.322657702e-04
+8.999592831e-04
+2.610331303e-03
+2.831408321e-04
+4.889400950e-05
+1.352704140e-04
+2.276286207e-05
+1.321459967e-04
+3.236482777e-03
+3.327171522e-02
+1.553886580e-03
+1.662666859e-04
+2.123734108e+01
+1.312466218e+01
+3.106515859e-02
+9.539559284e-04
+3.067801754e+00
+1.232082015e-03
+1.026959488e-04
+9.417997823e-03
+6.878335476e-01
+2.723242987e-05
+4.828541639e-03
+3.873501736e-05
+2.408801778e-04
+1.063614242e-04
+5.897239914e-01
+3.708363481e-05
+6.655116692e-04
+7.220734886e-03
+3.600091450e-01
+1.443564571e-04
+1.261891229e-02
+2.199834323e-04
+3.312843277e-03
+1.116488405e-04
+9.267143110e-04
+4.801407467e-05
+4.901042440e-05
+1.119882616e-04
+2.629345647e-04
+6.195849842e-04
+2.219917588e-04
+1.203383046e-01
+4.342611381e-03
+2.022635171e-02
+1.934031836e-04
+3.135956240e-04
+3.085037505e-04
+6.311297657e-04
+1.422738700e-04
+2.086081697e-01
+8.135856781e-04
+1.103637211e-03
+4.285006153e-04
+1.877914966e-02
+3.127013051e-03
+1.220899025e-05
+3.513491548e-05
+1.916890255e-03
+2.614667625e-03
+2.569041728e-04
+5.996081143e-05
+1.443015276e-03
+4.457065331e+00
+1.142543424e-04
+1.453117003e-04
+2.077357478e-04
+7.706619346e-07
+2.288061254e-04
+3.016530755e-05
+6.719547674e-04
+5.191979126e-06
+8.080124756e-03
+1.983321042e-02
+3.985812284e-03
+1.806653914e-04
+1.448354342e-04
+2.754455341e-05
+1.475916225e-04
+9.673078740e-05
+1.454410271e-02
+6.760693302e+00
+8.845015769e-05
+9.028110504e-02
+9.567452677e-04
+3.609380827e-04
+1.127676511e-01
+7.026084032e-01
+1.460566853e-03
+4.441580720e-02
+4.572987876e-05
+1.024203287e-03
+2.790732253e-04
+1.526331415e-04
+1.050795909e+01
+7.870212691e-02
+3.811986194e-04
+3.204731362e-04
+8.280570466e-05
+1.293039399e+01
+1.338527905e-04
+2.610109553e-05
+3.402968408e+02
+4.161175834e-04
+2.260302602e-05
+1.527296328e-04
+2.046817423e-02
+4.973311749e-04
+9.536418950e-05
+1.019013740e-04
+6.032991432e+01
+3.415346955e-04
+1.167862364e-04
+3.502022880e-04
+9.363055479e-06
+8.133221945e-03
+2.653729797e+00
+4.568260461e-02
+1.663446335e-04
+3.708951334e-02
+7.905614549e-04
+3.072353657e-04
+7.693511860e+00
+1.402273387e-02
+1.313456434e-04
+5.169923015e-02
+7.324359205e-03
+3.279106496e-04
+1.753903418e-03
+3.563072695e-04
+1.107564999e-04
+9.001403684e-05
+2.160684931e-05
+4.417014691e+04
+6.061032301e-06
+4.832706566e-04
+9.491169297e-05
+2.468143653e-04
+1.755928128e-03
+1.061484901e-03
+2.479948328e-04
+3.260006486e-02
+1.284393643e+00
+1.175452321e-01
+1.068877767e+01
+6.613378674e+00
+1.102681796e-04
+1.500012154e-04
+1.252573187e-04
+4.945154820e-02
+5.535486961e-05
+3.163967114e-05
+1.019497878e-01
+1.601811603e-04
+1.622256634e-01
+9.837396716e-05
+1.260199772e-04
+1.050955735e-03
+1.424471872e-02
+2.187951822e-01
+2.107121854e+02
+2.556034992e-04
+6.047813429e-01
+1.370892412e-01
+1.051281427e-04
+2.163897949e-02
+1.316514319e-02
+2.690122559e-03
+8.115542286e-04
+1.304791044e-02
+8.904809455e-04
+1.639509161e-02
+9.914415513e+00
+1.178755528e-04
+1.919529383e-04
+2.911308984e-04
+1.214662985e-02
+1.519557743e-02
+4.385178763e-02
+1.137576270e-03
+3.092498206e+00
+5.456742958e+05
+1.257216158e-04
+1.645822079e-02
+5.582328754e+01
+8.416967287e-04
+1.993098091e-03
+3.467336822e-04
+5.753196090e-03
+6.967536842e-03
+1.815047317e-01
+4.622054999e-03
+1.240791987e-04
+9.681082516e-05
+2.444195250e-03
+6.204760006e-03
+9.796775252e-05
+3.199467184e-04
+5.064848936e-04
+3.174393204e-05
+8.569575864e-04
+7.751538104e-03
+4.611774194e-02
+6.552346737e-04
+2.380511335e-03
+1.067462701e+01
+2.350741365e-03
+1.262278378e-04
+4.278434726e-04
+8.076135636e+00
+1.197862650e-04
+1.219920520e-04
+6.990054017e-04
+8.575363631e-03
+8.317359097e-05
+1.264686691e-04
+9.967953119e-05
+2.954889490e-05
+2.604074284e-03
+1.111154426e-04
+1.080206144e-04
+3.936678829e-02
+3.580270397e+01
+5.789259451e-03
+1.429765906e-02
+1.283811759e-01
+2.406401354e-05
+1.109074367e-04
+4.586415637e-05
+2.875190578e-04
+4.184381253e+01
+3.149111869e-03
+1.205689423e-04
+5.944026444e+02
+1.090530767e-05
+3.162457185e-05
+2.889084682e-01
+3.372331588e-04
+1.822838665e-03
+4.569865461e-05
+3.403294860e-03
+1.037002802e-04
+9.342423252e-05
+9.194945490e-03
+5.794224579e-05
+1.211220694e-02
+5.351779301e-03
+4.735005280e-04
+5.297818639e-05
+2.793608783e-03
+2.111454356e-04
+1.052493637e-04
+1.001022281e-04
+1.022291999e-02
+2.124345307e-04
+2.147548384e-02
+3.591431113e-02
+8.545559192e-05
+5.394494559e-04
+3.654334717e-03
+1.533277678e-04
+4.841290358e-04
+1.102927303e+01
+9.189233874e-04
+8.759710659e-05
+3.084494464e+00
+9.196579824e-05
+8.615138947e-04
+2.279674837e-03
+5.636966215e-05
+1.504146965e-03
+9.440498178e-06
+1.593879975e-02
+6.843450104e+02
+3.645507576e-04
+6.197922067e-01
+7.160839579e-06
+2.438970269e-01
+1.855638940e-04
+3.492995711e-04
+9.159020921e-05
+9.215050208e-05
+8.836736283e-01
+1.094969626e-04
+7.121325033e-04
+3.358423167e-05
+1.990975464e-04
+4.059284100e-02
+3.023331418e-05
+5.632274332e+01
+1.370680176e-03
+1.663634041e-04
+7.331440029e-03
+5.606021962e-05
+7.492930718e-03
+3.952832961e-03
+6.611787759e-04
+3.964085006e-03
+1.108191715e-01
+8.372452172e+02
+3.331156639e-04
+5.812814370e-03
+2.905752714e-03
+5.122997073e+00
+2.227425090e-04
+1.993174329e-04
+5.009051638e-05
+4.396041333e-05
+5.624732172e-04
+2.147982770e-03
+1.088264958e-04
+3.162793628e-03
+8.264410083e-05
+7.002437991e-05
+1.821302934e-02
+2.420847429e-05
+9.300965996e-05
+3.316678232e-03
+2.015995530e-04
+4.638817698e-03
+5.589742405e-04
+6.253579113e-05
+3.989014426e-05
+4.083722510e-02
+1.286046205e-01
+4.103380654e+01
+4.469280515e-02
+2.242320499e-04
+2.574949089e-03
+9.695475416e-03
+2.693375956e-01
+3.874416812e-04
+3.403625969e+00
+2.340701579e-04
+4.351172445e-04
+3.683938849e-05
+2.292802575e-04
+2.092055144e-04
+9.691816955e-03
+3.922663167e-05
+1.507853299e-04
+4.084453610e-05
+1.214499766e-04
+1.322515300e-04
+4.799256400e-04
+3.978661240e-03
+2.408033643e-03
+7.981269812e-01
+5.247777671e-04
+6.802070347e-04
+4.685251235e-03
+2.230147511e-04
+1.975391315e-01
+6.764331068e-04
+8.944263509e-04
+1.424095254e-04
+1.569605692e-03
+3.024134706e-04
+1.168621200e-02
+2.404807692e-05
+4.774934227e-05
+2.409133530e-01
+3.106341520e-05
+5.158441771e-02
+1.806913059e-04
+2.466835028e-01
+3.221654294e-04
+1.862517855e-03
+1.068448622e-04
+3.582903541e-05
+1.378403074e+01
+1.696496493e-02
+7.330490036e-02
+1.201779818e-04
+2.497387359e-03
+9.926517210e-03
+3.097095879e-04
+7.374121444e-05
+9.186748181e-05
+7.063310893e-04
+3.299894103e-03
+2.217834849e-05
+1.753370352e+00
+6.820392351e-04
+4.574623617e-04
+9.467015272e-01
+1.513306867e-04
+7.912637320e-01
+7.266432911e-04
+9.177460213e-05
+8.595967140e-03
+7.211584172e-05
+4.706942545e-04
+1.376640212e-04
+2.440553877e-04
+1.771777774e+00
+2.993816429e-02
+1.063513774e-04
+9.605898058e-03
+4.997616777e-01
+7.018079451e-05
+6.820531667e-05
+4.324455253e-03
+3.188534907e-05
+1.181540195e-02
+7.890335328e-02
+1.558341845e-03
+8.648418494e-05
+5.093650822e-01
+1.257068196e-01
+2.877907780e-05
+9.710601791e-03
+1.895899508e+00
+1.747842782e-04
+1.643767346e+01
+1.503327720e-02
+7.998717224e-02
+1.961941091e-04
+1.197966084e-04
+8.432538822e-03
+1.564417650e-04
+1.104165076e-04
+3.492593824e-02
+5.268810374e-05
+4.208877910e-04
+2.753150323e-01
+7.671867331e-04
+1.007171302e-04
+7.232281006e-05
+8.054407233e-05
+4.622835124e-05
+1.124397369e-02
+8.329750339e-03
+3.939835424e-04
+1.339338845e-01
+2.718788725e-04
+2.087915231e-01
+1.311113939e-04
+3.703057225e-03
+8.472190889e-01
+3.973184926e-03
+4.259858807e-04
+4.955991684e-01
+1.613745262e-03
+7.449278824e-02
+9.155411459e-05
+3.669975421e+01
+1.391712736e-04
+1.217904345e-03
+1.225018228e-04
+4.973374152e-01
+8.910047246e-02
+4.281740220e+00
+1.009490044e-04
+1.126056020e-04
+1.745391728e-02
+4.031078840e-05
+9.422534851e+01
+2.499957530e-03
+3.347956077e-04
+1.330672854e-04
+2.364409491e-03
+1.729886479e+00
+1.153862115e-04
+9.115301066e-02
+1.447338333e-03
+1.483838983e-04
+2.395076744e-05
+6.199050078e-02
+7.192475367e-01
+2.284966205e-03
+9.580048208e+00
+1.444134335e-03
+9.357761980e-06
+2.682270997e-04
+9.194777227e-04
+1.492731445e-04
+9.728002189e-05
+5.817027051e-01
+4.465026659e-05
+1.554788121e-04
+9.487234600e-05
+2.658559415e-04
+8.819347125e-05
+2.981097834e-01
+1.357400704e-04
+2.304597983e-03
+1.657394712e-04
+8.376224356e-05
+2.858580657e-05
+9.199637996e-05
+1.679369248e-04
+6.479335731e-03
+6.748826145e-03
+9.674690976e-05
+3.769921073e-02
+2.910426679e-03
+1.128340361e-01
+1.148516911e-02
+2.779645451e-05
+2.857840772e-04
+9.364485617e-05
+6.854112805e-05
+1.014902766e-04
+2.136167326e-02
+1.837677591e-04
+7.365451542e-02
+2.221820531e-04
+7.092449200e-04
+1.348641464e-03
+2.083932909e-04
+3.108287570e-05
+1.306047713e-04
+1.091973460e-01
+9.942652268e-05
+1.054487950e+01
+3.147546101e-05
+3.242447220e-04
+3.865735649e-04
+1.112740643e+01
+2.140845812e-04
+6.978807002e-04
+2.527825602e+01
+1.047252618e-04
+2.967538438e-03
+2.388445112e-04
+7.039057270e-02
+4.101092200e-02
+1.184780344e-04
+3.601076905e-04
+1.328732549e-04
+2.610549275e-05
+9.448532713e-04
+1.136454418e+01
+4.886463466e-03
+3.004767189e-03
+7.746790944e-03
+1.380143055e-04
+3.897556644e-04
+2.828249674e-05
+5.472704139e-05
+7.005022215e-05
+1.478557825e-03
+2.385116251e-04
+4.160712230e-04
+1.960994143e-04
+1.619663209e-02
+1.764157856e-02
+9.648968755e-02
+1.559444010e-01
+1.134858798e-04
+6.573178825e-02
+3.696724374e-01
+2.055494870e-04
+4.229822313e-04
+2.014166417e+03
+1.014908151e-04
+3.033721716e-04
+7.578413896e+00
+6.744505457e-04
+1.345283911e-03
+8.586628367e-05
+2.523126583e-04
+2.064733756e-04
+9.624989810e-05
+9.167097981e-06
+4.462010068e-05
+1.219392083e-04
+3.027940006e-04
+1.797127066e-04
+1.507081081e-03
+1.120017338e-03
+1.165407195e-03
+2.487129887e-05
+3.009503760e-05
+1.789049583e-01
+1.725555670e-04
+1.138533877e-04
+8.316585784e-04
+3.476398312e-04
+7.697746581e-04
+1.597763678e-03
+3.792148663e-04
+6.765935458e-05
+2.381645311e-05
+9.628254541e-04
+1.348445414e-04
+4.561070351e+01
+1.184704374e-01
+5.937669809e-03
+5.457772782e-03
+1.646243934e-04
+4.017204340e-04
+6.409337383e-05
+1.389799447e-04
+7.301908760e-03
+1.168523280e-02
+7.149171403e-03
+1.332748628e-05
+4.685808471e-05
+5.208380633e+02
+6.563333300e-04
+8.126825646e-02
+1.317696261e+00
+9.857203656e-05
+1.075250831e-04
+1.810977598e-02
+3.587036355e-05
+1.082083064e-03
+2.223131316e-02
+2.515639127e-05
+1.398015803e-04
+1.181976743e-04
+1.889791068e-04
+2.240267616e-02
+1.727266043e-04
+2.040947328e-01
+3.202388512e-04
+2.291553900e-04
+1.537168655e-04
+2.123852861e-02
+1.690160719e-04
+4.566105254e-01
+5.906280558e-04
+3.864983803e-02
+2.684952065e-06
+2.426588460e-04
+2.347466848e-04
+1.200221477e-04
+2.188775822e-04
+1.640713607e-02
+1.190353970e-06
+1.210678673e-04
+3.836294150e-01
+1.013130741e-02
+8.626748390e-05
+1.057036249e-04
+1.113607142e-04
+1.455773011e-02
+7.904216140e-02
+4.126161926e-05
+3.863644119e-05
+1.177606185e-03
+6.276488790e-05
+2.301082374e-04
+1.918475270e-01
+1.403799563e-04
+9.204458719e+01
+8.735283457e-05
+3.504971858e-05
+3.983875756e-05
+3.887056580e-04
+1.059731878e-04
+2.019453884e-02
+4.077046396e-02
+1.858923477e-01
+1.026401108e-03
+9.774550447e-05
+2.856320129e-04
+1.393976246e-04
+1.571118601e-02
+3.414997006e-04
+7.873287028e-02
+5.471571060e-05
+9.044726739e-05
+1.627383137e+01
+9.011842931e-05
+1.193983134e-01
+9.372020282e-04
+2.010166427e-03
+5.475254119e-04
+1.305637443e+00
+5.659765140e-04
+1.729343878e-04
+3.523285947e-04
+1.365365067e-04
+4.962580091e-02
+6.272132890e+00
+4.874269623e-05
+9.711254609e-03
+1.186838401e-04
+1.320285302e-04
+1.168278206e-04
+1.713761696e-02
+2.006425261e+00
+1.175630987e-03
+4.905582593e-01
+3.711985830e-04
+3.654885862e-04
+2.104361761e-04
+2.905861019e-05
+1.164371319e+00
+1.807165668e-04
+4.562666087e-01
+5.783971056e+02
+1.028493380e-01
+5.656582442e+00
+2.799445354e-04
+8.912654299e-05
+1.952692568e-04
+3.185389237e-04
+6.833819420e-04
+4.889944909e-03
+2.459937652e-03
+8.486259641e-04
+2.497852261e-02
+1.323109949e-04
+9.365138301e-04
+5.251416782e-05
+1.492280481e-03
+1.208002598e-04
+3.674093872e-03
+8.763305343e+02
+1.128669536e-04
+8.573299851e-05
+1.654856222e-03
+8.526234513e-01
+5.788808569e-04
+8.424841779e-03
+1.531465346e-02
+3.853384704e-02
+1.904171842e-04
+1.165465552e-04
+2.673657719e-04
+1.260432544e-03
+1.234890832e+01
+7.605918747e-04
+2.879892831e+00
+2.447458150e-05
+8.747098540e-04
+5.737757205e-05
+1.570662378e+02
+6.840137839e-04
+2.197806597e-05
+1.183878359e-04
+1.861971421e-04
+1.224115431e-04
+1.638766387e-01
+1.280196915e-04
+1.975347420e-02
+3.958007211e-05
+2.069532215e-02
+7.197465343e+00
+3.528763654e-04
+2.436021109e-04
+4.377793479e-02
+3.389799602e+02
+2.512827062e-03
+8.747720953e-06
+8.952288628e-04
+2.450213765e-02
+1.372504642e-04
+1.332560123e-04
+6.026818174e-04
+5.283921018e-04
+2.546464603e-02
+1.739089575e-04
+7.860559172e-04
+3.733095695e-01
+6.086045754e-03
+3.425584617e-05
+1.932608206e-03
+9.333124046e-05
+1.337715003e+01
+9.662334604e-05
+4.752631315e-04
+1.974566821e-03
+2.433578458e-03
+9.909672297e-05
+4.241325859e-04
+4.032114663e-02
+2.564974214e-03
+7.203384985e-05
+8.724776670e-04
+3.535662513e-04
+3.280086212e-02
+2.555542014e-02
+4.757904784e-04
+5.367416626e-04
+3.009836770e-03
+2.969419669e-02
+3.227756790e-02
+1.619825811e-01
+4.425280375e-05
+3.485467654e-04
+2.288792345e-04
+2.183435260e-03
+2.400336392e-04
+6.928608160e-03
+1.787711221e-01
+7.547679647e-04
+1.118937371e-03
+6.720865808e-06
+4.388652132e-04
+3.657571493e-05
+5.818823587e-04
+4.061133241e-01
+8.184400453e-03
+1.068223258e-01
+6.614819248e-05
+4.178082252e-04
+5.809030842e-05
+6.048434254e-03
+8.273683285e-05
+2.198042408e-04
+8.303704518e-03
+8.937504304e-05
+1.131969431e-03
+1.578958076e-04
+8.360599724e-03
+2.311652105e-02
+5.720746867e+00
+1.315722061e+01
+1.219376964e-04
+1.495910147e-03
+1.938938018e-01
+5.705720746e-03
+6.777316699e-04
+2.403169849e-05
+6.433086907e-05
+5.372253714e-02
+4.586835872e-04
+1.954162659e-02
+3.043899550e-04
+3.020217854e-04
+5.481912482e-05
+8.773343978e-05
+1.410949925e-04
+4.381318155e-05
+2.415321194e-03
+5.806870029e-02
+1.177242534e+02
+4.551026254e-01
+1.080746190e-02
+2.782108612e-04
+4.457609141e-03
+1.078515122e-04
+1.117569091e-03
+1.551246811e-05
+8.277719307e-04
+5.111759612e-02
+9.273791301e-05
+1.384760598e-04
+9.758233323e-04
+2.573766259e-03
+1.149129604e-03
+3.535248525e-04
+2.650786679e-04
+3.302490991e+00
+1.092584812e-04
+2.166505436e+02
+1.362831234e-04
+7.672726236e-04
+3.680708220e-02
+1.324954741e-04
+9.932984883e-04
+2.381058177e-04
+1.513300025e+00
+3.414154052e+00
+2.214112599e-04
+1.376942619e-04
+3.772136354e-05
+1.551767736e-03
+3.734834880e-04
+2.576634307e-03
+4.898182833e-01
+1.128912697e-04
+2.887406537e+05
+1.127078549e-03
+2.306733545e-04
+8.539681392e-02
+6.237634011e-02
+2.903281039e-04
+1.262430312e-03
+6.655443780e-05
+2.354820029e-03
+2.976202888e-03
+9.662931551e-05
+1.362826036e-04
+1.333129466e-04
+1.415746286e-03
+1.719227603e-01
+3.953878818e-04
+6.006726527e-02
+2.037725815e-02
+1.803387945e-04
+1.908215999e-01
+9.081510552e-05
+8.936469122e+01
+1.109940588e-04
+4.736166519e-05
+1.160199102e+00
+4.331810459e-02
+1.204969792e+02
+2.240092847e+00
+9.675154622e-04
+6.380640958e-06
+3.008405535e-04
+4.122478287e-03
+3.350770389e-02
+1.233796507e-03
+2.731096961e-03
+3.467842068e-04
+4.189652234e-03
+2.222337522e+00
+1.342272675e-04
+2.167947253e-04
+1.922750316e+00
+1.360418353e+00
+4.361644415e-02
+4.546491916e-04
+5.698557824e-04
+1.180822224e-03
+2.718283353e-03
+2.511513860e-02
+4.272071893e-01
+8.297304776e-03
+1.680620543e-03
+3.875303807e-04
+1.414994442e-04
+5.015683975e+00
+9.328116284e-03
+1.074747344e-01
+9.646929457e-03
+1.100373749e-04
+1.798215831e-02
+1.929543254e+00
+3.168529997e-02
+1.174966995e-02
+1.468769880e-03
+3.422975556e-01
+7.625528039e+02
+5.514052938e-01
+7.344799521e-05
+7.878350296e-05
+1.948107079e-04
+1.160554440e-04
+1.328218764e-04
+4.726767436e-05
+6.532976171e-03
+1.480314514e-04
+4.270215880e-05
+2.992432197e-03
+1.787451217e-04
+5.847170327e-05
+1.034872264e-03
+8.427765199e-04
+1.713423908e-04
+2.186659055e-03
+9.298278806e-05
+1.345378910e-02
+5.309233659e-02
+6.719450842e-04
+6.246156319e+00
+1.021988724e-02
+1.506317698e+01
+1.507864474e-03
+1.568644945e-03
+1.288777111e-04
+1.046182036e-04
+8.440438885e-02
+8.380922465e+00
+4.428699551e-04
+1.242086201e-02
+2.799184349e-04
+5.309072786e-05
+3.036501685e-01
+3.290245021e-03
+3.975564077e-05
+3.397049732e-03
+7.354813478e+02
diff --git a/t/ME_data/ME_hj_mtinf_tree.dat b/t/ME_data/ME_hj_mtinf_tree.dat
new file mode 100644
index 0000000..1128daa
--- /dev/null
+++ b/t/ME_data/ME_hj_mtinf_tree.dat
@@ -0,0 +1,1687 @@
+2.871621040e-05
+8.482408231e-04
+5.846238075e-01
+5.988623570e-05
+7.014683226e-03
+9.783630051e-03
+2.220322616e-01
+2.361116907e-06
+1.334030960e-04
+3.842070935e-03
+1.144631395e-01
+4.783887356e+00
+1.375918212e-01
+3.161790492e+00
+1.007619707e-04
+7.759859742e-03
+6.605786721e-04
+1.160709230e-05
+7.953919200e-02
+5.011391735e-04
+4.004933637e-01
+1.400218724e+00
+3.212439991e-02
+2.206789573e-03
+2.347264952e-04
+1.305283685e-04
+2.714827552e-03
+3.022266876e-05
+4.103877053e-03
+1.797507474e+02
+3.889663185e+01
+3.151837501e-02
+4.646924820e-05
+6.515542072e-05
+3.432251747e-04
+1.217115903e-03
+1.049805445e-02
+9.380590075e-05
+9.663822340e-05
+3.413360992e-04
+2.935776467e-03
+2.309784522e-03
+5.209299245e-02
+4.761972895e+01
+1.913397959e-04
+1.819047239e+00
+1.164239965e-02
+3.657921184e-01
+3.688356464e-03
+1.501002030e-01
+3.919888467e-01
+9.052947966e-05
+1.350030498e-02
+1.136000130e-04
+1.902060332e+01
+3.170821325e-04
+7.299153197e-04
+1.946450289e-01
+5.479200105e-05
+3.039287027e-03
+4.890222275e-03
+4.965725526e-03
+7.847110848e-01
+3.263716732e-02
+9.278555688e-04
+2.180372682e-04
+2.124625358e-04
+5.734270248e-04
+1.297810376e-04
+1.394811377e-04
+1.917531823e-04
+1.385879097e-03
+1.700787508e-04
+9.576708692e-04
+1.502555720e-04
+1.746151284e-04
+5.892393268e-04
+1.692838298e-02
+1.044658601e-01
+4.616175226e-02
+4.902133595e-05
+2.863429459e-02
+9.552114790e-05
+4.401274997e-05
+2.907851767e-02
+8.101461920e+02
+1.096836900e-02
+1.378566749e-01
+1.461426923e+03
+1.876159987e-04
+2.714073765e-05
+1.557931548e-04
+1.441659515e+01
+3.771116715e-04
+9.839084423e-05
+1.968729945e-04
+5.793249343e-05
+8.601260902e-05
+2.888357058e-05
+1.927159961e-04
+1.802526169e-04
+2.014986100e-02
+1.757708284e-02
+1.027836599e-04
+6.814214678e-04
+1.225325087e-04
+9.717915665e-05
+1.739331196e-03
+5.393795209e-05
+2.832080793e-03
+9.941810795e-04
+4.888030249e-01
+1.266339619e+00
+2.597834417e-01
+3.194351186e-03
+1.456261381e-04
+4.549094931e-01
+1.696311727e-03
+4.378514713e-05
+1.040920177e-04
+1.349020372e-01
+3.482573286e-02
+1.521613202e-02
+2.452542675e-03
+4.464221451e-03
+6.876725809e-04
+9.867422579e-04
+7.722410541e-05
+4.337347790e-04
+9.871609144e-05
+7.572718976e-03
+7.542365830e-02
+1.235225550e-01
+7.919446129e-04
+2.051909619e-02
+1.109827264e-04
+1.507178654e-04
+3.306119738e-04
+7.001504061e-03
+8.473900624e-04
+2.307042167e-04
+2.342978463e+00
+5.505701496e-05
+1.234375421e-04
+9.765107993e-05
+1.780959600e-02
+1.939612463e-03
+1.493360697e+01
+6.368261151e-01
+3.297089198e-05
+2.736355553e-04
+1.928222140e-03
+1.038945515e-04
+9.469907317e-04
+1.002215204e-02
+2.706103208e-04
+8.352600098e+01
+1.290905962e-04
+2.651777350e+03
+1.003095022e-03
+3.341114654e-05
+9.667039166e-05
+1.203184457e-02
+8.873279099e-05
+7.432487545e-06
+4.201719529e-04
+3.786742225e-05
+1.177513356e+01
+1.055497515e-03
+8.586239565e-04
+1.376075171e-04
+5.900956196e-05
+3.304188772e-05
+1.050272127e-04
+5.763393059e-02
+4.681629612e-02
+6.712866542e-02
+1.657812293e-04
+1.728793055e-03
+4.005356031e-05
+1.479487238e-03
+4.817816160e-05
+2.101410030e-04
+1.072215176e-04
+5.482689102e-05
+2.231706393e-04
+2.515293033e-04
+4.914222198e-04
+1.034856519e-03
+1.124050542e-02
+7.421883311e-04
+2.919319876e-02
+3.246703871e-04
+2.783613990e-03
+2.115618964e-04
+1.216662663e-04
+4.525415188e-05
+1.902297367e-03
+4.554684564e-03
+8.099000781e-04
+1.196743259e-04
+3.004580589e-03
+9.553216330e-03
+1.724521051e-01
+8.869850898e-03
+3.692618107e-03
+2.459522349e-03
+1.580477081e-03
+3.505919039e-02
+3.170181064e-05
+1.259242657e-04
+6.776648362e-03
+6.187117019e-02
+1.879957822e-04
+6.727464819e-01
+1.608863055e-01
+1.544718909e-03
+4.493014166e-02
+1.482432841e-02
+2.148927010e-02
+5.986639961e+00
+5.339502147e-04
+1.232359181e-04
+3.433103978e-03
+2.979382847e-05
+2.740034631e-06
+2.246998964e-03
+9.597159142e-03
+1.944167731e+00
+1.229674568e-03
+2.577705993e-03
+1.111966572e+02
+5.136773930e-03
+4.885700167e-03
+5.756036963e-05
+5.221778765e-02
+1.108375479e-03
+4.040311450e-02
+1.874692760e-03
+2.588199721e-01
+2.626953532e-04
+5.312533538e-03
+5.036208285e-05
+4.040166584e-02
+1.166592334e-03
+5.644166932e-05
+3.328635288e-04
+1.543232966e-02
+6.222533975e-04
+8.939017244e-05
+5.108426530e-02
+1.103007744e-03
+2.183731990e+00
+3.641419834e-05
+1.045490671e-03
+5.116683973e-01
+3.521098226e-03
+1.862302741e-04
+2.905283845e-04
+1.205702805e-03
+2.067519902e-04
+5.829791562e-04
+8.446833667e-04
+8.235707448e-04
+2.956949293e-05
+3.867207478e-04
+3.053371645e-03
+1.923238131e+00
+9.469954280e+00
+8.859260855e-01
+1.089902859e+00
+9.803171060e+02
+7.151818346e-05
+2.041010172e-01
+2.782398916e-04
+7.949830859e+02
+1.058104006e-04
+1.253106906e+00
+2.764775107e+00
+4.208502361e-04
+6.936094730e-04
+2.737991525e-04
+3.496899910e-03
+1.116340003e-02
+8.550902474e-05
+2.524829940e-02
+9.726814715e-05
+1.131920779e+00
+9.370423514e-03
+1.446426723e-04
+1.591930536e-04
+2.600663846e+01
+8.602533850e-02
+3.720873183e-03
+3.355267543e-08
+2.018686886e-04
+6.004792326e-01
+3.689224984e-03
+1.908483386e-02
+2.611738866e-04
+1.535816131e-03
+6.373760508e-03
+1.977717393e-04
+5.806371076e-02
+8.207469956e-01
+2.380320027e-04
+1.001560086e-01
+6.536817951e-05
+1.668340691e-04
+1.016798326e+01
+1.146379405e+01
+6.355386528e-04
+4.498508259e-04
+9.029659661e-06
+7.449343680e-04
+1.233063424e-02
+5.566619728e-03
+3.535727524e-02
+6.815641127e-05
+9.223464887e-03
+9.878961729e-04
+3.644894378e-01
+2.765439774e-02
+1.301667780e-02
+1.571418602e-01
+6.232970275e-05
+1.881428423e-04
+6.272730742e-04
+1.423938413e-04
+1.219911220e-01
+1.584904132e-04
+8.946637422e-04
+4.157511979e-03
+1.019538910e-02
+2.101190202e-04
+1.702191735e+00
+8.905552576e-04
+3.581973671e-03
+3.327079623e-02
+9.000958181e-03
+3.990804428e-03
+5.417088623e-01
+6.437551097e-05
+1.435000287e+00
+6.579567819e-05
+1.112393714e-02
+4.855437902e-04
+6.294519117e-03
+8.947245709e-02
+3.690838130e+00
+1.059022762e-04
+3.657007907e-04
+1.718543474e-04
+3.513509992e-03
+4.226360533e-03
+6.851009387e-02
+1.978115476e-02
+6.097660895e-05
+5.679697897e-04
+7.641055953e-04
+2.841296010e-02
+1.790049300e-04
+8.768074100e-01
+9.526538364e-01
+1.933893198e-02
+5.542762512e-04
+6.345006245e-04
+2.200252186e-02
+2.331313011e-01
+2.631971077e-04
+1.658017381e-03
+4.403155586e-03
+3.533254016e-05
+8.024784206e-02
+9.148157105e-05
+3.741139365e-04
+1.171603196e-04
+2.224415050e+04
+1.173750747e-03
+1.963644915e-04
+3.179547270e-05
+1.315807006e-02
+1.087033272e+00
+4.143379301e-04
+5.377037092e-02
+2.416197264e-02
+8.943591274e-05
+7.696142965e-02
+1.138683610e-03
+1.188792530e-04
+7.755760501e-04
+2.881016346e-03
+8.045940781e-05
+5.281199466e-03
+4.971375302e-03
+4.140029648e+00
+1.791036690e-01
+5.779100902e-01
+6.402048820e-01
+1.419900800e-04
+2.713089085e-04
+1.707029605e-03
+5.053366118e-05
+1.870291582e-02
+1.135111200e+00
+4.026937550e-05
+3.118212152e-03
+4.669560508e-02
+2.352443866e-05
+9.276080551e+02
+1.336982087e-04
+3.228200101e-04
+2.316165102e-03
+2.292160958e-04
+6.669587495e-04
+8.367454825e-05
+2.547175457e-05
+3.453386366e-05
+1.816099897e-03
+3.500016670e-04
+2.567346064e-05
+2.458856896e-02
+6.427892550e-03
+1.686158150e-03
+2.836974102e-06
+2.616569963e-05
+1.445419008e-02
+9.485213549e-05
+1.596280284e-01
+1.245274971e-01
+7.988411072e-05
+4.303221527e-04
+4.933341078e-04
+5.216222128e-02
+1.134928927e-04
+1.330103721e-04
+2.307216630e-04
+2.473293538e-02
+6.542994242e-05
+1.036991002e-01
+4.175692348e-05
+5.755198815e-03
+3.152429795e-01
+1.455139863e-04
+6.840438795e-02
+3.202570061e-05
+9.336878590e+02
+1.223843577e-02
+6.208854430e-05
+1.353353341e-05
+7.649460685e-04
+1.917789315e-04
+8.490924347e-05
+5.602795032e-02
+1.496703330e-03
+2.521458969e-01
+5.176095505e-05
+5.886185913e-04
+2.439926475e-05
+1.680800925e+01
+1.711237046e-02
+1.194902425e-04
+1.007485262e-03
+5.500865886e-03
+2.119606052e-04
+8.914436799e-02
+3.652943192e-02
+5.703056887e-03
+1.057173298e-04
+7.823616238e-05
+1.267278149e-03
+1.929756192e-04
+3.166595110e-05
+6.225502140e-04
+9.012630657e-05
+2.341330415e-04
+1.092838301e-04
+4.094508416e+05
+1.912472942e-03
+5.495923061e-04
+5.498501786e-04
+4.784766978e+00
+6.102727938e-04
+5.152849142e-03
+1.166974491e-04
+3.514669206e-05
+8.869475237e-05
+2.258292101e-03
+2.177036550e-03
+1.404087239e-04
+8.772305840e-04
+1.319691825e-04
+4.115231584e-03
+2.707169941e-04
+5.686891424e-06
+6.218721056e-04
+8.286804080e-03
+3.247837111e-01
+3.412238220e-04
+2.278520098e-01
+6.628649037e-01
+1.553168849e-03
+1.121006795e-04
+1.882511943e-01
+1.284783626e-02
+3.125848034e-04
+9.919746150e-04
+2.410035966e+01
+1.035488378e-02
+5.814988234e-04
+7.849522937e-02
+2.942937664e-04
+2.211932389e-04
+1.317148437e-04
+8.853379631e-05
+1.698626184e-03
+2.141321086e-02
+1.091874754e-01
+2.374410203e-05
+1.156768617e-04
+1.345628080e-03
+1.351791830e-04
+1.048692002e-03
+7.659984144e-04
+3.553305017e-01
+3.990180365e-03
+5.811965001e-04
+1.949543385e-04
+2.487570187e-04
+2.173457617e-03
+1.998119461e-01
+8.962259803e-04
+1.249095297e-04
+3.048158426e-05
+1.358866081e-04
+2.170187812e-02
+1.982695526e-04
+1.860292569e-04
+5.021524957e+00
+1.130111618e-02
+2.026047785e-04
+2.289825031e-01
+9.033258846e-02
+5.926377080e-01
+4.109211591e-04
+6.714548738e-04
+1.326690907e-04
+1.031654115e-03
+9.427710638e-04
+5.771859021e-05
+5.911064105e-02
+1.669111905e-03
+5.306384330e-04
+4.641347883e-04
+1.071530974e-02
+3.585231072e-04
+1.010859098e-04
+2.569313920e-02
+2.047013208e-04
+1.196029848e-04
+1.130078533e-04
+2.181121646e-02
+5.462924040e-04
+6.587633728e-02
+1.733860216e+01
+7.674648592e-03
+2.861325223e-05
+4.796145119e-04
+6.817902507e-03
+9.331736321e-03
+3.105489269e-03
+5.711304170e-02
+2.218007689e-04
+9.764189030e-03
+1.409540098e-03
+4.122424817e-05
+1.953220833e-01
+3.002934658e-04
+1.576701104e-04
+2.964544045e-04
+8.278459048e-02
+1.082051028e-03
+5.395325322e-01
+1.604957529e-02
+1.535098430e+02
+3.296149554e-01
+3.270375437e-03
+5.985706382e-05
+1.026847845e+00
+2.862351014e-03
+7.919553910e-05
+4.049900495e-02
+2.869433527e-05
+4.510098401e-03
+6.189769829e+02
+2.042106089e-04
+1.270838036e-01
+1.304682329e-04
+1.272381905e-03
+1.923776589e-01
+1.355099900e-01
+2.512758955e-02
+3.442773958e-03
+4.112446359e-02
+1.459364811e+01
+7.428580152e-04
+2.196312559e-02
+9.105385295e-05
+3.196550800e-04
+8.083245636e-03
+3.383875629e-03
+3.887054972e-04
+5.413630645e-02
+7.264413158e-04
+8.866822356e-03
+2.389381890e-04
+1.145087663e-04
+6.891563721e+00
+2.344741339e-04
+1.998781400e-04
+2.662263915e-03
+2.497410143e-04
+7.865518238e-04
+1.818306253e-03
+4.543940224e-03
+3.051452523e-02
+5.820780618e-03
+9.131317435e-05
+9.346455075e-05
+6.464107824e-02
+4.234930999e-05
+8.181437576e-01
+5.104899637e-05
+1.031686219e-04
+4.654809655e-04
+1.538111920e-04
+6.510364855e-03
+5.683088536e-04
+1.478985853e+00
+1.368665343e-04
+1.327708143e-04
+1.951624847e+02
+1.016227822e-04
+2.093912937e-02
+7.307508218e-05
+4.494030417e-02
+3.153164639e-03
+1.122171130e-02
+2.314086783e-04
+1.302514948e-03
+5.082906567e-04
+1.025084023e-01
+2.429151940e-04
+1.713630185e-02
+1.264720922e-02
+1.443909390e-04
+9.064245161e+02
+4.422146552e-01
+1.967070025e-03
+3.581265453e-03
+4.082949409e-05
+3.325070512e-04
+1.980349940e-04
+1.134886339e-01
+3.107474757e-04
+1.636172778e-05
+2.428851195e-02
+4.850016384e-04
+1.333120106e-04
+1.084252329e-03
+6.247614236e-02
+7.554038445e-02
+1.270852312e-04
+2.363608534e-04
+1.081187931e-04
+5.866428338e-05
+2.171492179e-01
+4.179984558e-06
+9.981449116e-06
+4.239882478e-04
+1.107651578e-04
+7.905073740e-02
+3.312004292e-04
+2.156379988e-06
+3.848264728e-03
+1.746611611e-01
+2.641679656e-03
+1.659422981e-04
+2.574609938e-05
+1.201459062e+01
+1.028823285e-04
+4.251506937e-05
+3.584679392e-04
+9.198070248e-05
+4.757957034e-04
+9.944297030e-05
+1.233041524e-04
+4.409146610e-06
+1.792428620e-03
+2.490685334e-02
+6.841996524e-04
+8.689492733e-04
+1.727230304e-04
+1.603005891e-04
+4.189013541e-03
+9.471483797e-05
+1.325691700e-04
+2.608969755e-02
+1.391776254e-02
+2.717944127e-05
+1.922170820e-03
+1.890448389e-02
+4.817361202e-05
+5.597543563e-04
+5.366165893e-05
+4.632967058e-04
+8.528760092e-04
+2.505664044e-03
+3.008247068e-04
+5.391035472e-05
+1.302288887e-04
+2.216628194e-05
+1.319354316e-04
+3.166257907e-03
+3.199295076e-02
+1.494842120e-03
+1.593662014e-04
+2.069242990e+01
+1.262043143e+01
+3.222022229e-02
+1.206233775e-03
+3.225092367e+00
+2.350265160e-03
+1.106338670e-04
+9.228687453e-03
+6.859527130e-01
+2.813297748e-05
+5.720327812e-03
+4.438349045e-05
+3.511888524e-04
+1.038017069e-04
+5.655616467e-01
+4.047400869e-05
+7.213189813e-04
+6.860719410e-03
+3.574795777e-01
+1.556031343e-04
+1.358058173e-02
+2.104797085e-04
+3.283774555e-03
+1.106890700e-04
+1.023043041e-03
+5.373465517e-05
+5.531040757e-05
+1.201016909e-04
+2.677576910e-04
+2.520796301e-03
+2.199549814e-04
+1.164021173e-01
+4.136377234e-03
+2.118703492e-02
+1.940927696e-04
+3.003327096e-04
+5.048927857e-04
+5.989765438e-04
+1.361352249e-04
+1.986766459e-01
+7.791222955e-04
+1.862044196e-03
+4.140341139e-04
+2.589913228e-02
+3.012386329e-03
+1.267588949e-05
+3.486823546e-05
+1.834751424e-03
+2.485781756e-03
+5.532431568e-04
+5.730896738e-05
+2.485613048e-03
+4.242278650e+00
+1.138212266e-04
+1.902086234e-04
+8.423434364e-04
+7.501294127e-07
+2.679695387e-04
+3.152383817e-05
+6.501731542e-04
+5.037215464e-06
+2.216972183e-02
+2.601286503e-02
+3.924094654e-03
+1.744759920e-04
+1.424992887e-04
+2.699062923e-05
+1.434003696e-04
+1.045161675e-04
+1.396551777e-02
+6.408078722e+00
+9.075391337e-05
+1.044170826e-01
+9.561453144e-04
+3.974321284e-04
+1.076990211e-01
+7.624488530e-01
+1.580106193e-03
+1.396154765e-01
+5.808781233e-05
+9.906060242e-04
+2.676244222e-04
+1.515269251e-04
+1.153964521e+01
+8.379271694e-02
+9.718844799e-04
+3.189248664e-04
+8.138172006e-05
+1.247302821e+01
+1.625049606e-04
+2.563102833e-05
+3.251854281e+02
+9.427956565e-04
+2.195925180e-05
+1.922535030e-04
+2.002403342e-02
+4.758650505e-04
+1.029789005e-04
+1.130907480e-04
+6.274699539e+01
+3.783596417e-04
+1.140234316e-04
+3.662430916e-04
+9.803718163e-06
+8.198453728e-03
+3.014299376e+00
+4.419093638e-02
+1.637034568e-04
+3.534178819e-02
+8.377220735e-04
+2.980425735e-04
+7.485358913e+00
+1.360939085e-02
+1.257388725e-04
+5.088024336e-02
+7.335760447e-03
+3.242040864e-04
+1.745443939e-03
+3.441649445e-04
+1.082261010e-04
+8.976760558e-05
+2.185970683e-05
+5.199705025e+04
+6.076884136e-06
+4.658128863e-04
+9.058420494e-05
+2.731067905e-04
+1.696006045e-03
+2.389963331e-03
+2.374201560e-04
+3.303100692e-02
+1.230147393e+00
+1.115161450e-01
+1.011034445e+01
+6.288330417e+00
+1.079748170e-04
+1.540430218e-04
+1.316290546e-04
+4.764982212e-02
+6.640030175e-05
+3.094400442e-05
+9.912221058e-02
+1.727801911e-04
+3.265390437e-01
+9.794647714e-05
+1.445379016e-04
+1.013874798e-03
+1.407671564e-02
+2.073172042e-01
+1.997505321e+02
+2.431747813e-04
+5.786980574e-01
+1.416413057e-01
+1.079438153e-04
+2.077193169e-02
+1.286551785e-02
+2.733483086e-03
+1.344822840e-02
+1.269017227e-02
+8.586744736e-04
+1.608607035e-02
+9.978918370e+00
+1.152699232e-04
+2.060869926e-04
+3.139393623e-04
+1.265479087e-02
+1.513568455e-02
+4.569403325e-02
+1.159712361e-03
+3.006756632e+00
+5.396471457e+05
+1.540278565e-04
+1.587167845e-02
+5.602024240e+01
+8.122954791e-04
+1.935432592e-03
+3.330573999e-04
+5.616854495e-03
+6.871050615e-03
+1.848802593e-01
+5.608218540e-03
+1.199456761e-04
+1.039532170e-04
+2.671960451e-03
+5.907318331e-03
+1.021441490e-04
+3.069081287e-04
+6.033182921e-04
+3.474698565e-05
+2.418041921e-03
+7.684174962e-03
+4.417459132e-02
+6.746325611e-04
+2.291458777e-03
+1.025603629e+01
+2.456562218e-03
+1.554257428e-04
+2.332727301e-03
+8.019041615e+00
+1.161014511e-04
+1.190187747e-04
+6.749828518e-04
+8.559415906e-03
+8.373436386e-05
+1.230360174e-04
+9.914519133e-05
+2.851505832e-05
+2.728166362e-03
+1.098319839e-04
+1.466762208e-04
+3.856361878e-02
+4.423268227e+01
+6.122216919e-03
+1.366452645e-02
+1.277559269e-01
+2.439572283e-05
+1.603293733e-04
+5.646741069e-05
+4.566728266e-04
+4.000074919e+01
+3.048770004e-03
+1.158332019e-04
+5.744887242e+02
+1.060120461e-05
+3.157310874e-05
+3.683685908e-01
+3.747626910e-04
+1.130073796e-01
+4.470034868e-05
+3.668196229e-03
+1.025185058e-04
+9.273809105e-05
+8.895001350e-03
+5.672343727e-05
+1.361492512e-02
+5.138674152e-03
+4.738976273e-04
+7.010059951e-05
+2.673582997e-03
+2.518096953e-04
+1.084864113e-04
+1.027172047e-04
+9.838708293e-03
+2.054786108e-04
+2.060256447e-02
+3.492343089e-02
+8.136267604e-05
+5.149454269e-04
+3.484764696e-03
+1.502710585e-04
+4.709319215e-04
+1.122120671e+01
+9.098326426e-04
+8.932765053e-05
+2.969591984e+00
+9.128053176e-05
+8.771873115e-04
+2.376060416e-03
+5.417083157e-05
+1.432145602e-03
+9.110855355e-06
+1.566801597e-02
+6.492450642e+02
+3.729195815e-04
+6.158840098e-01
+7.026375336e-06
+2.543774151e-01
+2.121603044e-04
+3.378433866e-04
+9.126491126e-05
+9.137541887e-05
+8.435901169e-01
+1.111109380e-04
+7.138397931e-04
+3.412513552e-05
+3.135274841e-04
+4.412761458e-02
+2.911681023e-05
+5.725200571e+01
+1.312509812e-03
+1.613642790e-04
+7.019457135e-03
+5.422531174e-05
+1.253986917e-02
+3.787166231e-03
+6.392732154e-04
+4.326425777e-03
+1.056906038e-01
+8.260231372e+02
+3.218545480e-04
+5.695804185e-03
+2.900418255e-03
+2.146207895e+01
+3.367808240e-04
+1.909985746e-04
+4.888505542e-05
+4.808063713e-05
+5.612738991e-04
+2.151645193e-03
+1.116201178e-04
+3.022804475e-03
+8.059348757e-05
+1.145759432e-04
+1.760936028e-02
+2.366619821e-05
+9.240043396e-05
+3.317635875e-03
+2.674951749e-04
+4.450218420e-03
+6.377413282e-04
+6.362640249e-05
+4.127537855e-05
+3.871611372e-02
+1.248980494e-01
+3.948331060e+01
+4.542337051e-02
+2.140097204e-04
+2.483594136e-03
+9.618341264e-03
+2.570656590e-01
+3.716902514e-04
+3.826901008e+00
+2.508965025e-04
+5.492112486e-04
+4.033350589e-05
+3.029881998e-04
+3.473304858e-04
+9.312098850e-03
+3.918675945e-05
+1.651786170e-04
+3.911735258e-05
+1.176613601e-04
+1.274488887e-04
+9.955775183e-04
+7.047594490e-03
+2.402198122e-03
+7.650844627e-01
+4.983023617e-04
+6.446755521e-04
+4.631950898e-03
+4.338330579e-04
+1.911950174e-01
+7.049018940e-04
+8.653593740e-04
+1.537140959e-04
+1.509326113e-03
+1.333400008e-03
+1.246338586e-02
+2.334057711e-05
+4.685751992e-05
+2.396936029e-01
+3.026678414e-05
+6.774556426e-02
+1.744612233e-04
+2.370183257e-01
+3.630398347e-04
+1.808922993e-03
+1.191341224e-04
+3.547898828e-05
+1.366248018e+01
+1.627207101e-02
+8.508027241e-02
+1.244872802e-04
+2.403438658e-03
+9.490627482e-03
+4.261424311e-04
+7.619134278e-05
+9.551111854e-05
+7.009804627e-04
+4.441547998e-03
+2.157000178e-05
+1.704934420e+00
+6.574312603e-04
+4.916816998e-04
+9.013593687e-01
+1.477458756e-04
+7.517405078e-01
+6.920613310e-04
+9.115905339e-05
+8.452768873e-03
+7.042886926e-05
+4.106438108e-03
+1.547935327e-04
+2.342856935e-04
+1.717419540e+00
+3.218140617e-02
+1.038695440e-04
+9.320597152e-03
+8.100525895e-01
+7.079485654e-05
+8.853609071e-05
+4.142326704e-03
+3.395964744e-05
+1.854234428e-02
+7.908373703e-02
+4.258410786e-03
+1.873605147e-04
+6.027693445e+00
+1.353719540e-01
+2.787141459e-05
+1.055372228e-02
+1.815141035e+00
+1.676539851e-04
+1.902848647e+01
+1.494202547e-02
+1.593654751e-01
+2.050443392e-04
+1.167640041e-04
+8.638487041e-03
+2.120107376e-04
+1.060486880e-04
+3.334421917e-02
+5.279501326e-05
+4.077745922e-04
+2.610042216e-01
+7.456103761e-04
+1.018323466e-04
+6.901454661e-05
+7.742843237e-05
+4.909127924e-05
+1.273653363e-02
+7.985314406e-03
+3.936279714e-04
+1.291516513e-01
+2.995287720e-04
+2.651956943e-01
+1.600526119e-04
+3.612296595e-03
+1.279544755e+00
+4.183827039e-03
+4.051000701e-04
+4.702842597e-01
+1.593739257e-03
+7.673301482e-02
+9.145684691e-05
+3.619928917e+01
+1.474871706e-04
+1.187865403e-03
+1.263927797e-04
+5.492357103e-01
+8.522712854e-02
+4.056699517e+00
+1.055466952e-04
+1.357591392e-04
+1.748736405e-02
+4.666513843e-05
+9.333837188e+01
+2.445420885e-03
+4.093200447e-04
+1.460578524e-04
+2.255367348e-03
+2.155171685e+00
+1.122165089e-04
+8.791940688e-02
+1.523733577e-03
+1.531512607e-04
+2.371851429e-05
+5.945351648e-02
+6.818363419e-01
+3.353992032e-03
+9.215896665e+00
+1.529139719e-03
+9.274690141e-06
+2.677488933e-04
+8.883354752e-04
+1.999449961e-04
+1.068643670e-04
+7.422347408e-01
+4.809383598e-05
+1.956270075e-04
+9.846263782e-05
+2.548275845e-04
+8.879794317e-05
+3.327347107e-01
+1.308768687e-04
+2.443947412e-03
+1.595299950e-04
+8.302061071e-05
+2.766273723e-05
+9.139637163e-05
+1.613952354e-04
+6.617868621e-03
+6.457781796e-03
+9.606570167e-05
+4.736684330e-02
+2.865560088e-03
+1.072809848e-01
+1.144303823e-02
+2.878264145e-05
+3.082463646e-04
+9.611297782e-05
+6.616368439e-05
+9.944437150e-05
+2.082011563e-02
+1.785473536e-04
+8.062916496e-02
+4.515563014e-04
+8.816542793e-04
+1.363355642e-03
+1.987894141e-04
+3.283217373e-05
+1.246856258e-04
+1.157064859e-01
+9.861002820e-05
+1.013085337e+01
+3.216675288e-05
+3.094484962e-04
+3.741993782e-04
+2.082274389e+01
+3.208676656e-04
+7.250634429e-04
+2.565818985e+01
+9.963050780e-05
+2.900509129e-03
+2.855755215e-04
+6.663478968e-02
+4.065901362e-02
+1.172433796e-04
+3.434910578e-04
+2.434579811e-04
+2.579364552e-05
+2.107265609e-03
+1.077482701e+01
+4.896969448e-03
+3.218164899e-03
+8.120588212e-03
+1.366782157e-04
+4.069314661e-04
+2.859383541e-05
+5.522785730e-05
+7.040931448e-05
+1.616280394e-03
+2.293972441e-04
+3.953229601e-04
+2.708105582e-04
+1.589260452e-02
+1.678634581e-02
+9.865405933e-02
+1.483097858e-01
+1.128036107e-04
+7.255547131e-02
+3.505437940e-01
+1.984166616e-04
+4.049497751e-04
+2.114662645e+03
+1.211013435e-04
+1.248931676e-03
+7.582074438e+00
+6.416845155e-04
+1.296293166e-03
+1.282187343e-04
+2.412535843e-04
+2.330209042e-04
+9.501570909e-05
+9.614958957e-06
+5.015836892e-05
+1.169138042e-04
+1.211464882e-03
+1.973325376e-04
+1.891607124e-03
+1.162140050e-03
+1.117696922e-03
+2.415373649e-05
+2.934615606e-05
+2.124454320e-01
+1.671264464e-04
+1.344034805e-04
+8.721867576e-04
+3.821772157e-04
+7.699890506e-04
+1.539333491e-03
+3.668372333e-04
+8.507990639e-05
+2.311063991e-05
+1.127911890e-03
+1.587714734e-04
+4.449246223e+01
+1.166516481e-01
+5.653602216e-03
+6.518636905e-03
+2.022317953e-04
+4.768246397e-04
+6.473780298e-05
+1.590729830e-04
+7.357326980e-03
+1.131855787e-02
+6.868854794e-03
+1.322596342e-05
+4.557424840e-05
+5.127274318e+02
+6.936451333e-04
+8.431894382e-02
+1.259258122e+00
+9.738600735e-05
+1.123231587e-04
+1.721492247e-02
+3.496585607e-05
+1.045061306e-03
+3.691782360e-02
+2.486633330e-05
+1.366690264e-04
+1.148649342e-04
+1.979241464e-04
+2.377774735e-02
+1.667109793e-04
+2.141359201e-01
+5.754643197e-04
+2.410656905e-04
+1.480751657e-04
+2.097989719e-02
+1.611713122e-04
+5.731357745e-01
+5.888202253e-04
+4.102148650e-02
+2.812474159e-06
+2.453269962e-04
+2.288993800e-04
+1.179422404e-04
+2.109045835e-04
+1.620585866e-02
+1.170465806e-06
+1.272369719e-04
+3.638318670e-01
+9.674914176e-03
+1.024658715e-04
+1.036877486e-04
+1.083835114e-04
+1.408131680e-02
+7.834006353e-02
+4.045170270e-05
+3.824743465e-05
+1.157862124e-03
+6.562522724e-05
+2.222154811e-04
+1.991359699e-01
+1.847172402e-04
+8.798010400e+01
+8.888517240e-05
+3.493921489e-05
+4.371948208e-05
+3.719291396e-04
+1.034471740e-04
+2.660901597e-02
+3.949321211e-02
+1.833647367e-01
+9.742747106e-04
+9.621410640e-05
+9.506661460e-04
+2.459730056e-04
+1.629853849e-02
+3.489886088e-04
+7.491902671e-02
+5.948261981e-05
+9.358708530e-05
+1.669324325e+01
+8.984404898e-05
+1.206455721e-01
+9.323198099e-04
+1.923570051e-03
+5.200130923e-04
+1.243523903e+00
+5.391953839e-04
+1.778454806e-04
+3.459477147e-04
+1.323895172e-04
+4.727671587e-02
+6.990304119e+00
+5.741307226e-05
+1.654839352e-02
+1.177493419e-04
+1.342091356e-04
+1.139384028e-04
+1.631287579e-02
+1.920974517e+00
+1.240013047e-03
+4.690468593e-01
+3.555322918e-04
+4.926525883e-04
+2.110905540e-04
+2.811115644e-05
+1.815918553e+00
+1.728427741e-04
+4.444398798e-01
+5.476677137e+02
+9.798199691e-02
+5.671122996e+00
+3.492810941e-04
+1.090285268e-04
+2.043277783e-04
+3.050287069e-04
+6.806933758e-04
+2.836538334e-02
+2.682552063e-03
+1.280233282e-03
+2.602042261e-02
+1.317499959e-04
+8.956413433e-04
+6.494003226e-05
+1.873036368e-03
+1.188530270e-04
+3.642281475e-03
+8.597036875e+02
+1.076904595e-04
+1.087404182e-04
+1.588422132e-03
+8.624647108e-01
+5.688846506e-04
+8.266745680e-03
+1.449074600e-02
+5.001847712e-02
+1.833303507e-04
+1.131963244e-04
+2.601662362e-04
+1.418040719e-03
+1.193276516e+01
+7.579518003e-04
+2.740632626e+00
+2.414333460e-05
+8.686485751e-04
+5.751731222e-05
+1.488862135e+02
+9.128757124e-04
+2.146830000e-05
+1.172440755e-04
+1.803925493e-04
+1.374565795e-04
+1.595590178e-01
+1.530729321e-04
+2.308208498e-02
+3.898450019e-05
+2.097415794e-02
+8.061163222e+00
+3.446917721e-04
+2.885029381e-04
+4.524202155e-02
+3.218825308e+02
+5.317281318e-03
+9.065304103e-06
+1.052546440e-03
+2.629892754e-02
+1.320653737e-04
+1.283670693e-04
+5.835986440e-04
+1.654285696e-03
+2.422940424e-02
+2.021482118e-04
+7.586341220e-04
+4.383659779e-01
+1.265136396e-02
+3.448991669e-05
+1.885250726e-03
+9.368060644e-05
+1.284735242e+01
+9.612522601e-05
+4.880226451e-04
+1.887820769e-03
+2.367397583e-03
+9.957072546e-05
+4.100436426e-04
+5.291476382e-02
+2.851325810e-03
+6.910768064e-05
+8.385317679e-04
+3.509269690e-04
+3.212389454e-02
+2.452446405e-02
+4.566982764e-04
+7.631682253e-04
+2.911861614e-03
+3.797395386e-02
+4.516134522e-02
+1.692613798e-01
+4.698333202e-05
+3.713357711e-04
+2.192284940e-04
+2.346595257e-03
+2.313377103e-04
+9.614002357e-03
+1.712101134e-01
+7.321417198e-04
+1.367034591e-03
+8.901981463e-06
+4.367481883e-04
+3.582914274e-05
+5.539468517e-04
+3.960864848e-01
+8.474842825e-03
+1.040834769e-01
+6.702809113e-05
+4.050507695e-04
+6.227722917e-05
+5.900496098e-03
+7.955267157e-05
+2.910375378e-04
+7.913861878e-03
+8.534865441e-05
+1.081603572e-03
+2.169522002e-04
+8.745246892e-03
+2.261408778e-02
+5.509010045e+00
+1.255794392e+01
+1.286972400e-04
+5.011431891e-03
+1.847797828e-01
+5.451323027e-03
+6.584877780e-04
+2.420750808e-05
+6.220656908e-05
+5.209790191e-02
+5.003506474e-04
+1.922088606e-02
+2.995299066e-04
+4.081698450e-04
+6.336742941e-05
+8.953477854e-05
+1.467650930e-04
+4.210145128e-05
+3.053782863e-03
+5.554558477e-02
+1.583492508e+02
+4.413747082e-01
+1.029679765e-02
+3.636496730e-04
+4.325427162e-03
+1.051491941e-04
+1.069623321e-03
+1.525614770e-05
+8.223492897e-04
+6.385161606e-02
+8.852458644e-05
+1.609568597e-04
+2.062929633e-03
+2.699034803e-03
+1.103357831e-03
+3.921930595e-04
+3.586523782e-04
+3.150865900e+00
+1.116854085e-04
+1.641584966e+03
+1.313656828e-04
+9.197982791e-04
+3.703793690e-02
+1.448717314e-04
+9.836967783e-04
+2.808143403e-04
+1.463385018e+00
+3.290493136e+00
+4.459815627e-04
+1.573624139e-04
+4.066652323e-05
+1.511657341e-03
+3.814582481e-04
+2.901442675e-03
+4.644144602e-01
+1.240302918e-04
+2.761663981e+05
+1.072521873e-03
+2.945735308e-04
+8.176402477e-02
+5.966833128e-02
+2.798888985e-04
+1.287370218e-03
+6.911317621e-05
+2.250939462e-03
+2.870126997e-03
+9.366881035e-05
+1.528036278e-04
+1.401847478e-04
+1.504644546e-03
+1.647485899e-01
+3.763208585e-04
+5.953215168e-02
+2.420301864e-02
+2.388656923e-04
+2.710393226e-01
+9.482033317e-05
+8.873488914e+01
+1.079741758e-04
+4.543463111e-05
+1.380369610e+00
+5.252113073e-02
+1.145823911e+02
+2.449930683e+00
+9.834477093e-04
+6.510455407e-06
+2.879663518e-04
+4.681496832e-03
+3.292794491e-02
+1.169227525e-03
+2.805843011e-03
+3.519812829e-04
+3.995440817e-03
+2.236126015e+00
+1.574908754e-04
+2.057140647e-04
+1.868921726e+00
+1.297363692e+00
+4.232041081e-02
+4.462849813e-04
+5.406569097e-04
+1.165876886e-03
+2.725490035e-03
+2.458383109e-02
+4.098097916e-01
+8.040306218e-03
+1.800516398e-03
+3.725326127e-04
+1.365139586e-04
+4.804135754e+00
+9.385664992e-03
+3.220704964e-01
+9.188596655e-03
+1.160997818e-04
+1.814472732e-02
+1.831987830e+00
+3.021952357e-02
+1.748238639e-02
+1.457866046e-03
+3.345252481e-01
+1.083862853e+03
+5.355710331e-01
+7.217911188e-05
+9.443838897e-05
+2.023917699e-04
+1.220461141e-04
+1.279016223e-04
+5.236369442e-05
+7.902731080e-03
+1.430661929e-04
+4.101706939e-05
+2.896169867e-03
+1.712494380e-04
+6.715561884e-05
+1.047703033e-03
+8.180128139e-04
+1.679107995e-04
+2.169655649e-03
+9.196927686e-05
+1.277858203e-02
+5.538484661e-02
+6.513003175e-04
+6.201298319e+00
+9.764655420e-03
+1.443689137e+01
+1.472582170e-03
+1.491476570e-03
+1.351789888e-04
+1.022254576e-04
+2.592061086e+01
+8.805867470e+00
+5.519060034e-04
+2.307444786e-02
+2.775230005e-04
+5.173617752e-05
+2.905379444e-01
+3.133294771e-03
+4.294888552e-05
+3.339861288e-03
+7.552334106e+02
diff --git a/t/ME_data/ME_hj_mtinf_virt.dat b/t/ME_data/ME_hj_mtinf_virt.dat
new file mode 100644
index 0000000..7037ab3
--- /dev/null
+++ b/t/ME_data/ME_hj_mtinf_virt.dat
@@ -0,0 +1,1687 @@
+2.948436168e-01
+9.923292151e-02
+1.748147191e-01
+7.591002871e-01
+2.276391084e-01
+2.174677369e-01
+8.441405151e-02
+4.288111439e-01
+4.293949575e-01
+2.461853267e-01
+1.522944787e-02
+3.366663480e-02
+1.017992834e-01
+8.564242727e-03
+1.050055647e-01
+7.573950387e-02
+1.574021370e-01
+9.309027685e-02
+4.487454686e-02
+1.219688593e-01
+8.247928162e-03
+6.265850926e-03
+7.967271603e-02
+5.653783079e-02
+2.313296470e-01
+4.400356120e-01
+1.246652154e-01
+6.698066782e-01
+7.056025675e-02
+1.435994567e-02
+1.127108762e-02
+3.701673978e-02
+9.162850930e-02
+3.024451530e-01
+3.418020743e-01
+1.576744690e-02
+1.174734705e-01
+8.606141367e-01
+7.498006690e-01
+1.634728506e-01
+1.981528026e-01
+4.041902780e-02
+1.085656183e-01
+2.086108831e-03
+3.713361211e-01
+1.009727126e-01
+2.464119072e-02
+4.512411883e-02
+1.425000334e-01
+6.060169860e-02
+4.569495169e-02
+2.450830278e-01
+9.328283803e-02
+6.759028405e-01
+1.638031437e-02
+1.564986925e-01
+1.084235573e-01
+3.550440792e-02
+4.076167189e-01
+9.917768657e-02
+1.113336718e-01
+7.006748481e-01
+2.402669310e-02
+2.234676219e-02
+3.210870213e-01
+9.945028604e-01
+2.867964123e-01
+2.330361612e-01
+6.282972421e-01
+4.330558653e-01
+3.010493997e-01
+1.035790109e-01
+3.741721443e-01
+4.565939491e-02
+4.596111060e-01
+7.210504987e-01
+5.478509844e-01
+6.076772948e-02
+1.301055635e-01
+7.535992281e-02
+4.151743534e-01
+1.706413433e-01
+8.663004996e-01
+6.550448365e-01
+6.908675726e-02
+7.970270645e-03
+1.065167747e-01
+2.761688492e-02
+2.338745730e-03
+3.712172534e-01
+9.283126161e-01
+3.907009907e-01
+1.231748587e-02
+1.155292470e-01
+7.234688711e-01
+6.857350537e-01
+5.482837803e-01
+2.573310224e-01
+6.901989008e-01
+1.801555680e-01
+8.719851783e-01
+1.587247116e-01
+3.853748311e-02
+7.363438565e-01
+8.394854877e-02
+6.830796992e-01
+9.099651118e-01
+2.516605477e-02
+4.615383416e-01
+1.066615691e-01
+4.728094613e-01
+8.326535028e-02
+1.635447447e-02
+8.435051438e-02
+5.330836495e-02
+1.572943050e-01
+1.007536267e-01
+3.419469648e-01
+6.248918043e-01
+7.056512614e-01
+8.522090351e-02
+1.710407724e-01
+1.626312621e-01
+1.549019947e-01
+1.768221797e-02
+5.620799005e-02
+7.805876878e-02
+2.638877443e-01
+4.698531462e-01
+2.896507091e-01
+9.752187983e-02
+9.000216346e-02
+1.107923703e-02
+2.825799560e-01
+5.906691062e-02
+7.938409883e-01
+5.174031604e-01
+8.552148409e-02
+2.620176826e-01
+3.105491789e-01
+1.119171261e-01
+4.569059492e-02
+7.457849641e-01
+6.516477096e-01
+3.939561184e-01
+1.240934783e-02
+1.642172115e-01
+1.211633779e-02
+9.185283802e-03
+9.795584751e-01
+2.127394326e-01
+2.273147139e-01
+7.203488927e-01
+1.395693704e-01
+4.296761924e-02
+6.646873718e-01
+5.571720425e-03
+5.562784142e-01
+1.622305885e-02
+2.938779566e-01
+3.059265214e-01
+9.632928590e-01
+2.788538324e-01
+9.849187436e-01
+7.031880786e-01
+2.922162078e-01
+1.099072751e-01
+2.252510523e-03
+1.343865194e-01
+1.550389856e-01
+6.851581800e-01
+4.065622056e-01
+2.670959521e-01
+5.005507553e-02
+2.055793964e-01
+5.542203609e-02
+3.485942381e-02
+3.898242760e-01
+2.585248214e-02
+5.071457669e-01
+2.395994089e-01
+9.782657743e-01
+2.997206583e-01
+6.076425636e-01
+7.046902284e-02
+2.513557260e-01
+2.221713560e-01
+1.055907861e-01
+7.206488363e-02
+1.847907023e-01
+1.088043292e-01
+3.284586042e-01
+3.007184766e-01
+3.313513947e-02
+8.749638873e-01
+9.544267259e-01
+1.014319293e-01
+3.465879147e-02
+5.186090247e-02
+1.525036060e-01
+2.243490487e-01
+7.102867936e-02
+6.057672663e-02
+2.316057175e-02
+1.878950557e-01
+2.310460050e-01
+5.219824581e-02
+5.369887561e-01
+2.701310226e-01
+6.055388875e-01
+4.873049113e-01
+4.529807828e-01
+1.588353766e-01
+7.343736754e-01
+9.604035883e-02
+1.483732380e-01
+1.633331281e-01
+1.911159578e-02
+2.419346380e-02
+1.343069371e-01
+7.950663643e-02
+3.155129315e-01
+4.935929468e-01
+1.347462119e-01
+6.984569184e-01
+1.260101066e-01
+6.989127015e-01
+2.190388651e-01
+3.416994849e-05
+2.839702993e-01
+2.721886360e-01
+1.457242256e-03
+6.040231691e-02
+5.493638930e-02
+1.388608910e-01
+1.540253206e-01
+1.498925471e-01
+1.611199089e-01
+5.473601180e-01
+2.297863983e-02
+3.980098240e-01
+2.012076094e-02
+3.895027115e-01
+4.454161532e-03
+6.279835476e-02
+9.559220730e-02
+4.172959352e-01
+2.858672879e-02
+4.426286831e-02
+9.932716190e-01
+5.533684501e-02
+8.743949329e-01
+2.256626926e-02
+5.579761062e-01
+1.097822403e-01
+1.099048715e-01
+1.185083407e-01
+3.021691378e-01
+4.846015768e-01
+6.571930240e-02
+1.271552870e-01
+4.197184741e-01
+3.435398107e-01
+1.978877366e-01
+8.389319002e-01
+1.664540519e-01
+3.105503428e-03
+2.140487589e-02
+7.720831219e-03
+2.487178555e-02
+1.000509847e-02
+2.733351931e-03
+1.545611028e-02
+3.596386605e-02
+4.038491110e-01
+6.824734773e-03
+6.649755790e-01
+2.689821103e-02
+5.969031346e-02
+1.498593683e-01
+2.708306642e-01
+4.790750153e-01
+2.644669601e-02
+4.552475380e-02
+2.310397637e-01
+4.100899974e-02
+7.678656730e-01
+5.406050420e-03
+3.705387077e-02
+1.285991248e-01
+4.423246301e-01
+8.786167024e-04
+2.115219108e-02
+1.647140953e-01
+1.276595097e-02
+6.530461145e-01
+1.148235880e-01
+1.333670051e-02
+1.990551913e-02
+4.423154249e-01
+5.584129841e-01
+1.002162025e-01
+1.186342426e-01
+7.739619711e-02
+1.470824555e-03
+1.227260829e-01
+2.084384515e-01
+5.906294077e-01
+4.095301751e-01
+3.631485036e-04
+8.717553588e-03
+4.621574316e-01
+7.744197499e-01
+3.505265450e-01
+5.123123295e-01
+1.624019691e-01
+1.074126240e-01
+2.526910389e-02
+3.476472717e-01
+1.477224762e-01
+4.958177088e-02
+2.350948259e-02
+2.349402635e-02
+5.656183010e-02
+4.847643019e-02
+3.142824912e-01
+2.894981341e-01
+8.836552622e-01
+8.783201318e-02
+5.710887461e-03
+1.308700289e-01
+4.474200473e-02
+4.693404478e-02
+7.300777786e-02
+2.181925761e-01
+8.658877245e-02
+6.029264630e-01
+2.763493012e-02
+1.526085859e-01
+1.830548418e-01
+1.280811322e-01
+4.745555770e-02
+1.794296460e-01
+7.451798156e-02
+5.863510256e-01
+3.377840424e-01
+8.043741366e-01
+1.405698930e-01
+3.613033028e-02
+4.115919441e-02
+2.026644485e-01
+4.690677580e-01
+6.469996872e-01
+5.450485551e-01
+3.311109932e-01
+5.187546294e-02
+1.699138107e-02
+2.844068183e-02
+1.170252832e-01
+1.033613777e-01
+2.388139987e-01
+1.578947595e-01
+7.158409446e-02
+3.279510388e-02
+8.532362282e-02
+2.564890053e-01
+2.245489395e-01
+4.665864300e-02
+8.529626342e-02
+1.014489717e-01
+4.747194872e-02
+8.457577197e-02
+2.806367858e-01
+5.865448325e-02
+4.284637042e-02
+4.909193809e-01
+5.639984521e-01
+7.120079913e-03
+3.145272929e-02
+2.917119402e-01
+2.505750422e-01
+2.907759781e-02
+2.532000238e-02
+1.833951743e-01
+3.727834086e-02
+5.101777328e-02
+9.778849709e-01
+5.705200961e-02
+3.594032584e-01
+5.178357865e-01
+4.169817111e-01
+6.263320663e-01
+4.718204653e-01
+3.336879074e-02
+1.004423641e-02
+1.457976048e-03
+4.707532742e-02
+4.017086427e-02
+4.835504674e-02
+1.478954428e-01
+4.329209433e-01
+3.121200260e-02
+4.152715177e-01
+4.412444589e-01
+3.049635672e-02
+8.554573618e-01
+3.358993572e-02
+3.906297516e-02
+9.721600659e-01
+5.193297611e-03
+7.681153644e-01
+1.765986749e-01
+1.272056902e-01
+7.186357292e-01
+1.053477891e-01
+1.587453770e-01
+7.818271668e-01
+5.875395930e-01
+1.857187637e-01
+8.128935552e-02
+3.330435756e-01
+6.365928060e-02
+3.188482662e-02
+1.147629074e-01
+2.273981791e-01
+7.706014865e-01
+1.543659980e-01
+7.896538528e-01
+1.307986106e-02
+6.082065011e-03
+4.750078654e-01
+1.613521311e-01
+1.461720917e-01
+2.349438986e-01
+5.670186984e-01
+4.257519081e-01
+4.757395142e-01
+9.585750932e-02
+3.050161890e-01
+2.341001873e-01
+4.848901656e-01
+2.306934694e-01
+2.649289063e-02
+3.786571074e-01
+5.082376613e-01
+4.357132567e-01
+1.061955544e-03
+4.284288356e-01
+8.082074645e-01
+3.730169154e-02
+8.628918845e-01
+8.051637512e-01
+6.557811419e-01
+2.437803339e-01
+2.083827220e-01
+6.006103562e-02
+4.044550069e-01
+1.295006522e-01
+8.323329349e-01
+2.738847443e-03
+8.914641573e-02
+8.639340972e-01
+5.239775774e-02
+7.586749573e-02
+1.323215186e-01
+3.016435863e-02
+1.022036491e-01
+2.537977551e-01
+6.535882530e-01
+7.476832511e-01
+9.358984725e-02
+3.312074833e-01
+3.747160115e-01
+1.002939402e-01
+9.475308523e-01
+3.885350513e-01
+9.278698842e-01
+4.958016381e-03
+2.761025687e-02
+1.682547217e-01
+3.115966958e-01
+2.181854002e-01
+1.342012105e-01
+1.214210380e-01
+1.878457702e-01
+5.509975888e-01
+6.714263722e-01
+2.525446073e-01
+7.363840309e-01
+3.274543243e-01
+7.658641302e-01
+4.381769499e-01
+4.253257950e-02
+3.053075321e-01
+8.033688641e-01
+1.816158560e-01
+1.292348833e-01
+3.044580060e-02
+1.637949303e-01
+9.274635899e-03
+1.034953334e-01
+9.932801698e-02
+5.493805493e-01
+3.933104651e-02
+9.248081314e-02
+1.851205688e-01
+9.891565415e-02
+4.713170344e-02
+8.858340823e-02
+6.318891122e-02
+5.486383941e-02
+5.592638831e-02
+4.459801424e-01
+1.790916462e-01
+9.696456824e-01
+3.582282614e-01
+6.519110782e-02
+4.983050749e-02
+3.772344518e-01
+9.936800350e-01
+1.276776658e-01
+7.469804437e-01
+6.926784343e-02
+6.259424373e-02
+1.023674336e-01
+9.036594000e-02
+3.169812848e-02
+3.765940559e-01
+6.434656394e-01
+1.397762970e-01
+8.018465891e-01
+2.708381699e-02
+4.223005243e-01
+6.773913969e-01
+6.449421024e-01
+2.023362140e-02
+3.650741275e-01
+7.916020855e-01
+7.452670372e-02
+4.586432442e-01
+6.172254611e-01
+1.355480729e-01
+6.282698591e-02
+3.809293998e-02
+6.256033092e-01
+3.947170391e-02
+4.383692659e-01
+9.272530458e-02
+4.816907041e-01
+3.713926790e-01
+5.411707711e-02
+5.927336438e-02
+5.023114854e-01
+4.161517979e-01
+3.643925871e-02
+3.435198600e-01
+6.220983891e-01
+1.618682099e-02
+1.611804446e-01
+8.704244667e-01
+9.993824404e-01
+8.115831858e-03
+3.519421964e-01
+7.630494049e-02
+5.667230826e-02
+2.254057749e-02
+7.049121727e-01
+3.042003537e-01
+3.062356013e-01
+7.458259666e-02
+1.888946845e-01
+5.028429898e-02
+4.952868799e-01
+1.216795224e-01
+5.483567313e-02
+4.986643535e-01
+3.348262838e-01
+6.238039838e-01
+6.811775138e-01
+5.871601637e-01
+8.838635868e-02
+2.237994850e-01
+5.793516799e-02
+3.170298275e-01
+8.866529896e-03
+9.473561387e-03
+4.725697068e-02
+5.298414268e-01
+5.362791257e-03
+3.692116073e-01
+1.077162412e-01
+1.800825621e-02
+8.252922004e-02
+8.988453053e-02
+3.870119757e-02
+2.800793209e-01
+9.892955082e-02
+4.547301795e-01
+5.784461430e-02
+1.718965919e-02
+2.898312964e-02
+3.934116861e-02
+1.859478079e-02
+5.777819362e-02
+8.241881441e-03
+2.688242360e-02
+2.360514330e-02
+8.923675462e-01
+3.345063585e-01
+1.412759102e-01
+1.305321613e-01
+1.456774156e-01
+2.890677063e-02
+3.521183905e-02
+1.352504803e-01
+1.459312528e-01
+6.502090376e-01
+8.231797018e-03
+6.542679836e-01
+2.734036444e-01
+9.889348991e-02
+2.448726823e-01
+5.976182851e-01
+1.417973941e-01
+1.000736380e-01
+2.780459169e-02
+4.442470381e-01
+8.999910521e-01
+1.122237237e-01
+6.605170494e-02
+9.768048557e-01
+1.249206842e-01
+3.767669167e-01
+7.917966649e-01
+5.146527188e-01
+4.204155094e-01
+1.525048167e-01
+7.723263567e-01
+2.857110039e-02
+5.247842724e-01
+5.762401676e-01
+2.237113078e-02
+7.715057605e-01
+2.760432368e-01
+8.919205234e-01
+1.646502816e-01
+1.205426650e-01
+2.095660879e-01
+6.300033321e-01
+8.386071683e-02
+7.374768692e-01
+1.657848388e-01
+1.231181491e-01
+2.472012810e-01
+1.129612185e-01
+7.608779697e-01
+3.352808824e-03
+6.105513527e-02
+4.184781507e-02
+8.806080972e-02
+4.851091209e-01
+1.665479231e-01
+3.101574433e-01
+1.639468791e-02
+2.743726364e-01
+5.220794892e-01
+8.315105751e-02
+5.189038864e-01
+9.207601574e-02
+3.646975202e-02
+9.281662623e-02
+1.021594845e-02
+8.477077390e-01
+4.493327251e-01
+2.145365687e-01
+8.535104697e-01
+1.139246627e-03
+1.494647852e-01
+3.992139991e-01
+1.504362465e-01
+5.828588749e-01
+1.034106121e-01
+1.673574307e-01
+3.197073958e-01
+1.366045508e-01
+3.014180452e-02
+3.773202602e-02
+3.753877015e-01
+9.839659054e-01
+3.198345635e-03
+9.072133655e-01
+4.694023492e-01
+1.559065228e-01
+8.824600716e-01
+5.219773218e-01
+7.817214103e-01
+4.728860446e-01
+5.344520846e-01
+3.065996192e-02
+3.171077645e-01
+1.669893662e-01
+7.523327351e-01
+4.242568283e-02
+4.882531901e-01
+8.204605159e-02
+9.171857771e-01
+7.475666055e-01
+1.758563031e-01
+5.628301270e-02
+7.229870256e-01
+1.365871715e-01
+2.639050113e-01
+3.967639717e-01
+2.865619889e-01
+3.660002621e-01
+7.714098548e-02
+1.025565881e-01
+9.316131989e-02
+2.294754761e-01
+5.035152745e-01
+6.838996859e-01
+9.436927538e-01
+4.388116295e-01
+3.000388734e-02
+5.620173140e-02
+1.623333893e-01
+4.351874359e-01
+8.920756787e-03
+8.070330336e-03
+9.886583171e-02
+3.796319998e-02
+3.026330873e-03
+1.898417506e-01
+8.202086446e-01
+5.413144548e-01
+1.329344816e-01
+8.785437043e-01
+2.075113762e-02
+8.677067615e-01
+5.417625012e-01
+8.102383030e-01
+4.454297233e-02
+7.690236841e-01
+1.466803524e-01
+6.163293052e-02
+9.800178657e-02
+1.967717578e-01
+1.426482135e-01
+2.930865631e-01
+1.957694963e-01
+5.608333175e-01
+2.543783641e-01
+6.300700932e-01
+6.326951712e-01
+6.949600656e-01
+1.059289872e-01
+1.137147728e-01
+2.459878724e-01
+1.410069022e-01
+3.072049784e-02
+4.411651110e-01
+2.881513565e-01
+9.644873254e-02
+4.629626222e-01
+6.841120968e-02
+4.123826230e-01
+4.597156293e-02
+2.491562554e-01
+5.914415684e-01
+1.287966737e-01
+3.088374134e-01
+2.999857191e-01
+3.571151412e-01
+1.134290970e-01
+1.634483480e-01
+4.466840368e-02
+8.212796345e-01
+3.626285931e-01
+3.219922374e-01
+6.000269025e-02
+5.381909054e-01
+6.327422991e-01
+3.982744552e-01
+3.059490144e-01
+3.676046553e-01
+8.190031466e-01
+9.790670348e-02
+6.653155136e-01
+1.237330441e-01
+1.688689108e-01
+1.311372180e-01
+3.218081548e-01
+3.886622461e-01
+7.305653800e-01
+1.591911538e-01
+9.347262520e-01
+9.736723275e-02
+3.775449701e-03
+9.357053451e-01
+4.346334363e-01
+1.561636123e-01
+6.292887851e-02
+3.903835564e-02
+1.970537810e-02
+1.770469944e-02
+5.697672408e-02
+9.591680564e-01
+1.607454022e-02
+4.586954496e-01
+1.567654115e-01
+4.924900548e-02
+4.339184438e-02
+5.115891537e-01
+1.946414952e-01
+2.720942440e-01
+1.309768010e-01
+8.291809784e-01
+7.798112362e-01
+2.206224356e-02
+4.217325348e-01
+9.657299787e-01
+7.510915242e-01
+3.620241190e-01
+1.333321420e-01
+9.611732607e-01
+1.087459512e-01
+1.069926596e-01
+3.758784297e-01
+4.660340470e-01
+1.808820898e-01
+1.763340370e-01
+8.181163061e-02
+1.491914241e-04
+8.269449924e-02
+1.027590493e-01
+1.272281101e-01
+3.612341666e-02
+3.589872145e-01
+5.398770423e-04
+5.140120240e-02
+1.662333083e-01
+4.130510672e-02
+7.373974190e-02
+2.404595031e-01
+1.889255509e-01
+1.641028614e-01
+6.353981995e-01
+9.828356107e-01
+7.611801135e-02
+6.724055878e-04
+1.073785773e-01
+1.083117690e-01
+2.456899647e-01
+2.928379071e-01
+9.420449820e-02
+1.403671313e-01
+2.089100916e-02
+4.889274031e-01
+3.510817016e-02
+1.902371921e-02
+8.011372051e-03
+1.472455607e-03
+6.202418677e-01
+1.699732957e-01
+5.461876003e-01
+1.325933902e-01
+5.941631580e-01
+6.236223314e-01
+1.116309649e-02
+4.380596048e-01
+5.874891888e-04
+7.161510811e-01
+7.488742469e-01
+1.669845342e-01
+1.416245121e-01
+3.569414432e-02
+3.189373713e-02
+1.206970279e-01
+1.856972779e-02
+1.471803816e-02
+6.530218784e-01
+7.805694835e-03
+8.637551889e-03
+2.008403333e-01
+7.082131183e-02
+2.641730540e-02
+8.041476529e-02
+1.395104180e-01
+2.745828362e-02
+5.438630230e-01
+6.355546977e-02
+2.320323174e-01
+3.491705116e-01
+1.712754255e-02
+7.395826654e-02
+4.941252303e-01
+2.485365331e-02
+3.257393631e-03
+9.542689274e-01
+8.788352958e-02
+2.129523538e-03
+1.305566332e-01
+2.695369539e-01
+1.739699543e-01
+7.663688345e-02
+7.405332217e-02
+8.100277758e-03
+1.070409489e-02
+6.694436101e-01
+9.065665316e-01
+4.131855421e-01
+1.987016805e-01
+7.811500751e-01
+1.894484253e-01
+1.515522409e-01
+9.318106675e-01
+1.925522498e-01
+1.563876161e-02
+1.799023303e-02
+1.019397064e-01
+1.151299291e-01
+5.818169091e-03
+1.750389840e-01
+9.642895057e-01
+5.488284732e-01
+4.607145209e-02
+9.185347533e-01
+5.213931660e-01
+1.923792019e-02
+1.526105410e-01
+1.657331307e-01
+5.040906991e-01
+2.442240686e-01
+7.051970714e-01
+6.092188759e-01
+5.695923308e-01
+4.426813015e-01
+1.559164320e-02
+5.451089931e-03
+2.812073410e-02
+2.642816690e-02
+4.949127412e-02
+9.418700854e-01
+4.396474355e-01
+8.799476191e-01
+4.880948850e-01
+1.854192479e-02
+8.141804811e-02
+1.918524250e-01
+1.418255904e-01
+1.974189381e-01
+6.508087841e-01
+8.800488720e-03
+2.163613732e-01
+3.730654636e-02
+1.185799140e-01
+2.864473984e-02
+6.546467943e-01
+8.697540253e-01
+1.104536454e-01
+3.447586331e-01
+3.998956371e-01
+9.166949415e-02
+4.402737195e-02
+8.813367555e-01
+1.144078224e-01
+4.220579643e-01
+6.600606948e-01
+7.097288443e-01
+2.355569490e-01
+2.647023951e-01
+1.580373464e-01
+6.824860659e-02
+2.794359799e-01
+1.402280404e-01
+1.581512558e-01
+3.642813912e-01
+1.247981887e-01
+1.406743570e-02
+8.989716018e-02
+9.564788230e-01
+1.392959616e-02
+9.764869280e-01
+8.024938165e-02
+2.333433916e-01
+3.642774978e-01
+1.897803610e-01
+4.509111831e-01
+3.331100392e-02
+1.622179843e-02
+1.659841404e-01
+1.079572971e-02
+2.606805822e-01
+2.287049348e-02
+4.396470701e-01
+2.269192741e-02
+8.979028931e-01
+1.129400980e-01
+3.943598497e-02
+5.912833432e-01
+5.206224998e-01
+6.496346212e-01
+8.200088002e-01
+4.546955188e-01
+6.990692767e-01
+7.961532515e-03
+6.208001486e-02
+3.436471111e-01
+6.847880708e-02
+3.563595927e-01
+7.851331140e-02
+1.956393151e-01
+7.368679463e-02
+1.585955679e-02
+2.980149211e-02
+4.751403359e-02
+8.791591548e-02
+2.307790720e-02
+5.736032327e-01
+2.094658610e-03
+6.430203329e-01
+4.627196926e-01
+3.927115969e-01
+6.421319247e-01
+5.776431832e-02
+1.396055777e-02
+3.654361209e-01
+1.719303557e-01
+3.347055221e-01
+4.848578667e-01
+4.891684347e-01
+8.583099378e-01
+8.757945906e-01
+5.106840843e-02
+2.109917967e-01
+9.233433780e-02
+2.345157492e-01
+3.545534173e-01
+1.388402912e-01
+5.877214817e-02
+2.237434969e-02
+4.561064009e-03
+1.700422207e-01
+4.181590120e-02
+9.319236418e-02
+8.100848565e-02
+3.083047094e-02
+2.611438482e-02
+2.715232523e-02
+2.837395848e-01
+9.677303227e-02
+7.838316672e-01
+1.853725724e-01
+2.612393970e-01
+2.318356765e-01
+5.214994778e-01
+1.058031357e-01
+5.242679499e-01
+7.792986057e-03
+7.323099914e-01
+3.314378389e-01
+3.479945265e-02
+3.606842322e-02
+3.088821446e-02
+1.479903895e-01
+4.991299358e-02
+2.242277690e-02
+9.330519102e-01
+1.462285942e-01
+4.575911746e-01
+9.584940922e-01
+5.075157432e-01
+1.924054200e-01
+2.561995732e-01
+3.442742898e-01
+8.886639303e-01
+3.069859194e-01
+1.851636628e-01
+6.375685460e-01
+1.491584738e-01
+1.450359932e-01
+2.383019450e-02
+2.336861546e-01
+4.195698045e-01
+8.860655183e-01
+5.574751652e-01
+7.720090579e-03
+4.927772828e-01
+1.155788278e-01
+2.093528438e-01
+1.174561997e-01
+1.907095735e-01
+3.595678916e-01
+1.094483900e-01
+8.841677024e-01
+2.855822738e-01
+1.739902283e-02
+9.865644265e-01
+5.193795273e-02
+6.698238589e-02
+2.932724189e-02
+6.858015230e-02
+3.742201359e-01
+2.923037356e-02
+5.758717485e-02
+9.597180499e-01
+4.531756099e-02
+2.841097509e-01
+1.502885142e-01
+6.121537675e-01
+2.448197599e-01
+6.428162759e-03
+3.264014457e-01
+7.564684076e-01
+1.330236726e-01
+3.198187880e-01
+6.116797450e-02
+6.269892754e-01
+9.279850910e-02
+8.309384574e-01
+9.676677633e-02
+5.853531027e-02
+4.802023022e-01
+9.316467520e-01
+1.851756583e-03
+4.993335800e-02
+7.105997110e-01
+1.509732129e-01
+4.889053839e-03
+6.914960256e-02
+6.381507970e-03
+1.762442036e-01
+4.493409341e-01
+1.412161321e-01
+6.232254687e-01
+3.265525056e-01
+8.841349618e-01
+1.443277395e-01
+9.087553107e-02
+2.796772698e-01
+1.411566936e-01
+7.700979096e-02
+3.581281843e-01
+6.769994034e-01
+1.354733065e-01
+1.104808033e-01
+5.492002105e-01
+1.146516560e-02
+4.801236656e-02
+1.486280540e-01
+7.019064183e-03
+2.622201124e-01
+4.551849381e-02
+8.746802732e-01
+5.267553366e-01
+1.430254530e-01
+2.579736502e-01
+2.827449094e-02
+1.518521980e-02
+4.889164561e-02
+1.527164631e-02
+8.730160577e-01
+1.913035051e-02
+4.902208834e-01
+1.511828009e-02
+5.280296449e-01
+1.332195734e-01
+3.058697063e-02
+5.885115246e-03
+7.469406149e-01
+3.173192164e-01
+3.693944157e-01
+8.559689788e-01
+5.397299070e-02
+1.231906916e-01
+3.378143501e-01
+5.892225917e-01
+1.392290765e-01
+1.117183174e-01
+6.359523675e-01
+1.270395335e-01
+7.830570046e-01
+1.533708167e-01
+8.770383320e-01
+3.625962662e-02
+3.807423540e-02
+2.532752444e-02
+1.817754144e-03
+4.656950080e-02
+5.795449751e-01
+9.304918014e-01
+1.874372308e-01
+9.290306176e-01
+9.992818264e-01
+3.478229682e-03
+5.987387097e-01
+7.298985378e-01
+8.185317388e-01
+5.139550983e-01
+9.606826321e-01
+4.650107159e-02
+5.454266146e-01
+2.914327126e-01
+3.800671871e-01
+7.515351199e-01
+7.198954542e-01
+9.340253903e-01
+1.485790810e-01
+1.053644718e-01
+3.938100500e-01
+7.606565781e-01
+4.417781996e-02
+2.682454258e-02
+9.071252748e-02
+1.061687124e-01
+2.564500788e-01
+6.544895990e-03
+2.536056279e-01
+6.192146125e-02
+8.914729220e-01
+2.316774867e-01
+3.027750582e-01
+7.659752192e-02
+9.928302092e-01
+1.307583500e-01
+3.431088180e-01
+3.593271793e-01
+8.272202405e-01
+1.138642805e-01
+4.838200506e-02
+7.109778274e-01
+1.549895772e-01
+7.088300913e-02
+2.019942607e-01
+4.308846444e-01
+1.034999987e-02
+2.306991410e-01
+9.823274214e-02
+6.287777582e-03
+2.385080039e-01
+3.348319224e-01
+3.681050799e-01
+3.009970868e-02
+6.407312886e-02
+5.102785600e-01
+2.576435369e-01
+4.701764204e-01
+1.350158736e-01
+2.253658522e-01
+2.965028867e-02
+2.053339185e-01
+1.125752169e-01
+1.459440026e-01
+4.121274597e-01
+8.051643519e-02
+7.698142782e-01
+3.908571002e-01
+2.816139599e-01
+5.703324896e-02
+2.453556073e-01
+1.641990785e-01
+6.503216787e-01
+1.040356051e-01
+8.229258706e-02
+9.839068994e-03
+1.774953417e-01
+5.442515146e-01
+2.216258339e-01
+4.200218582e-02
+2.781796095e-01
+3.379729836e-01
+3.685408062e-02
+3.441895697e-01
+9.214853608e-01
+7.971085543e-02
+4.929944859e-02
+4.300230587e-01
+6.158385241e-01
+2.524673875e-01
+3.745466438e-01
+8.526566902e-01
+2.426650341e-01
+1.486141081e-01
+1.924177225e-01
+9.153927610e-01
+4.050510616e-01
+2.433777290e-01
+2.681347231e-01
+5.263960353e-01
+8.454798682e-01
+6.603461420e-01
+5.651902546e-03
+3.319511888e-01
+9.991244375e-01
+8.627082761e-02
+5.415840531e-01
+5.502491716e-01
+5.937031073e-02
+4.794558546e-01
+5.906776400e-01
+9.022366277e-01
+4.472810282e-02
+7.391480917e-01
+1.576280608e-02
+3.413534744e-02
+2.526193855e-02
+9.672765348e-02
+6.279205258e-01
+2.094306781e-01
+3.390691889e-01
+6.419421004e-01
+4.508563646e-02
+5.105598741e-02
+8.296865645e-02
+7.865134471e-01
+4.180948744e-01
+2.168818278e-02
+7.978178229e-02
+9.630680089e-02
+4.064440993e-02
+7.562686330e-01
+6.687659858e-01
+2.114755311e-02
+5.451878508e-01
+9.550424257e-03
+5.206078055e-02
+4.273136794e-01
+4.135336725e-01
+6.032283416e-01
+4.416030530e-01
+5.154638771e-02
+1.430054131e-01
+6.162815314e-02
+1.790149378e-01
+2.751059898e-01
+2.805005374e-01
+4.214036532e-02
+1.627420346e-01
+1.755804159e-02
+4.955622890e-01
+2.206155539e-01
+6.893237200e-01
+2.344350795e-01
+1.082488543e-01
+5.092570119e-01
+2.638636263e-01
+1.423075428e-02
+4.013885694e-01
+3.297110355e-01
+5.638832578e-02
+6.819803838e-02
+5.233552566e-02
+6.771550624e-01
+4.751489644e-01
+1.768580263e-01
+2.012202761e-02
+4.199058056e-01
+7.334895880e-01
+1.411103652e-01
+3.855521869e-01
+3.413250277e-01
+3.328502650e-02
+9.853659999e-01
+1.374683662e-02
+9.659319338e-01
+5.809955127e-01
+7.238211524e-01
+1.639176569e-01
+8.987465497e-01
+4.553163178e-02
+1.768547203e-03
+2.863683958e-02
+1.504047115e-01
+8.714133537e-01
+2.617786993e-01
+4.298272202e-01
+3.342080781e-01
+1.329590776e-01
+1.441197379e-02
+5.605971520e-01
+9.024616284e-01
+8.717799551e-03
+9.828674789e-01
+1.853374574e-01
+7.363474073e-02
+1.125998149e-01
+1.417460070e-01
+1.937189213e-02
+7.385497159e-02
+2.136252508e-01
+8.200325595e-02
+4.593309990e-01
+1.614582456e-01
+3.671134498e-02
+7.237906256e-01
+8.388436826e-03
+4.086463846e-01
+4.570833583e-01
+5.739723008e-01
+1.381742667e-01
+2.565722063e-02
+6.551784450e-02
+1.616709718e-02
+3.384357342e-01
+5.316300960e-01
+2.645203149e-01
+7.067506736e-01
+1.060479859e-02
+4.085185336e-01
+1.017940652e-01
+8.269405060e-03
+1.069763932e-01
+2.573195748e-02
+3.377387757e-01
+4.141165556e-01
+3.527587755e-01
+4.997449868e-02
+5.034913282e-02
+1.189302396e-01
+7.496432245e-02
+1.375267423e-01
+3.230363503e-01
+1.983120837e-01
+1.857116591e-01
+7.576581215e-01
+6.718762794e-02
+1.868333897e-01
+1.569635852e-01
+2.740829448e-03
+2.140085823e-01
+4.649064014e-01
+5.276917554e-02
+3.450218090e-02
+1.072004442e-01
+1.048075514e-01
+5.465563350e-02
+2.504849149e-02
+3.125818707e-01
+6.469537810e-01
+1.014600182e-01
+1.124083335e-01
+7.334526493e-03
+1.453728594e-01
+5.529923613e-02
+8.478464855e-01
+6.844529601e-01
+3.666757046e-01
+1.806852203e-02
+6.860901926e-02
+9.810706088e-01
+1.915823569e-01
+3.027873950e-01
+7.241877347e-01
+6.041183633e-02
+8.478504773e-01
+1.976798300e-01
+2.121324973e-01
+1.784228305e-02
+1.023864880e-02
+1.003997539e-01
+3.520184698e-01
+1.429527012e-01
+4.895789324e-02
+2.749981090e-02
+5.854836883e-01
+5.240712424e-01
+3.071402651e-02
+7.002391619e-01
+6.888761535e-01
+5.712757502e-02
+3.596644624e-01
+5.159486158e-02
+1.931703407e-01
+1.516676194e-01
+5.284277524e-03
+6.292262492e-02
+6.150489712e-01
+3.662881439e-01
+8.007608762e-01
+1.176204885e-02
+7.535324933e-01
+1.328838932e-01
+1.175023545e-01
+3.796905474e-01
+2.286012147e-01
+1.412854546e-01
+6.629627862e-02
+4.731401993e-02
+6.476820918e-02
+2.648376883e-01
+1.616811960e-01
+1.902160808e-02
+2.026854027e-01
+6.271162795e-02
+9.056956521e-02
+2.163098808e-01
+6.964987499e-02
+3.328240150e-02
+1.020417203e-01
+5.741139381e-01
+6.214922005e-02
+1.432353119e-01
+7.875748773e-02
+2.392406656e-01
+1.907435598e-02
+2.472823892e-02
+1.107928948e-01
+9.002988346e-02
+4.410603161e-02
+9.837454182e-02
+3.151729791e-01
+4.371443915e-02
+1.264755881e-01
+9.834515717e-02
+5.300226354e-02
+3.327160252e-01
+4.152594131e-01
+2.473620524e-02
+3.361270218e-01
+2.750199345e-01
+1.935383596e-01
+2.591493467e-01
+1.527296093e-01
+2.840759067e-01
+9.019051657e-01
+1.797107641e-01
+6.984871107e-02
+2.631748261e-02
+1.758218215e-01
+5.758606252e-01
+3.599497136e-01
+1.142005308e-01
+3.303075281e-01
+2.381513472e-01
+9.201812515e-01
+3.152859361e-01
+8.612879653e-02
+1.555625692e-01
+8.395020493e-01
+2.044229940e-01
+3.593187293e-01
+6.018064947e-01
+9.519371273e-01
+4.522064112e-01
+4.667913329e-01
+7.024297684e-02
+2.244869230e-01
+2.377235885e-03
+3.273133810e-03
+2.763512042e-02
+3.724414723e-01
+5.919707616e-02
+7.876743440e-01
+3.775150288e-01
+1.393272608e-01
+2.174738628e-01
+3.412376785e-01
+3.342796308e-01
+2.413442522e-01
+1.494095777e-01
+4.428154876e-02
+1.416304674e-01
+7.233347643e-01
+1.663592654e-01
+1.699684780e-02
+6.053436306e-01
+3.966050677e-03
+5.466370313e-01
+2.305675377e-01
+2.598637374e-02
+2.195962693e-01
+8.016902180e-01
+3.575359001e-01
+2.851542411e-02
+3.647157857e-02
+9.880968331e-01
+6.471982294e-01
+7.206894234e-01
+3.631762038e-01
+1.619466885e-01
+1.944931055e-01
+6.530284803e-02
+7.564726502e-01
+1.392825564e-03
+7.794293113e-02
+4.445128941e-01
+2.035601306e-01
+1.470924631e-01
+1.205716708e-01
+4.104671626e-02
+1.210176140e-01
+3.197581472e-01
+1.811431345e-01
+2.230108296e-01
+6.147192291e-01
+5.040403536e-01
+9.473339022e-02
+7.147412928e-02
+6.903156629e-02
+8.169254675e-03
+4.151135671e-03
+6.687123044e-01
+7.625193940e-02
+9.237396488e-01
+7.882591557e-03
+8.590647832e-01
+1.715376271e-01
+1.628732658e-02
+8.701269176e-02
+1.004045357e-02
+1.428845489e-02
+7.301589779e-02
+1.146068844e-02
+2.062030730e-01
+3.317497804e-01
+2.025889206e-01
+8.145466740e-02
+9.661007330e-02
+1.706539924e-01
+1.192554610e-01
+3.161459154e-02
+7.355618431e-01
+1.435574076e-01
+1.053409170e-02
+7.898015081e-03
+5.787304335e-02
+1.678049920e-01
+1.418631404e-01
+3.279733983e-02
+8.626568073e-02
+3.440640060e-02
+1.662636070e-01
+1.441035184e-01
+2.769932830e-01
+4.977783566e-01
+4.774700040e-01
+3.577847118e-02
+8.489642729e-01
+4.051629608e-03
+2.292417200e-01
+6.697828915e-01
+1.571232910e-01
+7.376756865e-03
+1.625869244e-01
+2.671055651e-02
+3.311819549e-01
+2.794823582e-02
+3.963105265e-02
+3.390307319e-02
+2.815686621e-01
+4.497652930e-01
+2.249806187e-01
+6.099259004e-01
+4.523729542e-01
+6.200158008e-01
+5.766470283e-02
+4.216505823e-01
+4.813300363e-01
+6.123925338e-02
+3.836309616e-01
+5.513431395e-01
+1.579842368e-01
+1.648163721e-01
+3.201450163e-01
+7.464127590e-02
+2.331957254e-01
+1.164233855e-01
+1.032207299e-01
+4.855516841e-01
+2.107645038e-03
+1.018087699e-01
+2.829516360e-02
+5.227839531e-02
+6.290694265e-02
+2.033903496e-01
+8.604731603e-01
+3.154262253e-02
+1.901602657e-01
+2.074251766e-01
+3.640009106e-01
+9.762445063e-02
+2.696210494e-01
+2.273213287e-02
+2.511693950e-01
+6.854858269e-01
+2.742923829e-02
+9.311132307e-03
diff --git a/t/ME_data/ME_hj_mtmb_tree.dat b/t/ME_data/ME_hj_mtmb_tree.dat
new file mode 100644
index 0000000..84dcd2a
--- /dev/null
+++ b/t/ME_data/ME_hj_mtmb_tree.dat
@@ -0,0 +1,1687 @@
+2.750198212e-05
+8.671995071e-04
+6.081591909e-01
+5.116795157e-05
+5.765484290e-03
+1.018354475e-02
+2.304538715e-01
+2.394449211e-06
+1.373133786e-04
+3.966325473e-03
+1.191333168e-01
+4.964815982e+00
+1.416820905e-01
+5.261660014e-01
+1.046281588e-04
+8.066931411e-03
+5.676100325e-04
+1.207204970e-05
+5.983557555e-02
+5.211894727e-04
+4.137938297e-01
+1.454926797e+00
+3.014409364e-02
+2.286316904e-03
+2.443111283e-04
+1.355818252e-04
+2.605103434e-03
+3.142691059e-05
+4.252186549e-03
+1.684651299e+02
+4.028945245e+01
+3.242820689e-02
+4.834046948e-05
+6.779263262e-05
+3.529644486e-04
+8.434431958e-04
+1.092437971e-02
+9.690055689e-05
+9.843829623e-05
+3.552724992e-04
+3.003191502e-03
+2.400727072e-03
+5.378257006e-02
+4.874240639e+01
+1.977525490e-04
+1.541056296e+00
+1.210897441e-02
+3.774187920e-01
+3.561375384e-03
+1.549857803e-01
+2.810725616e-01
+9.279747242e-05
+1.402861994e-02
+1.182358000e-04
+1.965208654e+01
+3.040268708e-04
+7.478247704e-04
+2.023074901e-01
+5.545170727e-05
+3.077866102e-03
+5.087237408e-03
+4.611114488e-03
+8.067202493e-01
+3.395819521e-02
+8.675805625e-04
+1.590003676e-04
+2.202028269e-04
+5.764850094e-04
+1.246663059e-04
+1.414568985e-04
+1.470448972e-04
+1.438132887e-03
+1.693803125e-04
+9.906169122e-04
+1.560588481e-04
+1.491123365e-04
+1.613346359e-04
+1.742493784e-02
+1.053324258e-01
+4.673580216e-02
+5.080490862e-05
+6.190694123e-03
+9.890360335e-05
+4.226803922e-05
+2.850431659e-02
+6.155488884e+02
+9.977530802e-03
+1.421009428e-01
+1.519482212e+03
+1.826478789e-04
+2.704811658e-05
+1.620224704e-04
+1.500552852e+01
+3.304358345e-04
+1.016571990e-04
+2.046895882e-04
+5.925058505e-05
+8.877373861e-05
+3.005810998e-05
+1.787929760e-04
+8.950237919e-05
+1.950644654e-02
+1.801065188e-02
+1.025796688e-04
+7.012126170e-04
+1.177663365e-04
+9.549380059e-05
+1.795729591e-03
+5.337074081e-05
+2.922996638e-03
+1.028209484e-03
+5.048290902e-01
+1.299954883e+00
+2.676111747e-01
+3.273560512e-03
+1.515162354e-04
+4.697042421e-01
+1.764066014e-03
+4.251259173e-05
+1.081397144e-04
+1.404051474e-01
+3.619625936e-02
+1.328568924e-02
+2.549866207e-03
+3.393580930e-03
+7.108601904e-04
+1.016958031e-03
+8.031907484e-05
+4.398598195e-04
+9.523712082e-05
+7.662902290e-03
+7.849841074e-02
+1.283130888e-01
+4.840585055e-04
+2.130720033e-02
+1.155051020e-04
+1.563673688e-04
+3.410531682e-04
+7.287618816e-03
+4.759407876e-04
+2.385661944e-04
+2.428122477e+00
+4.845260934e-05
+1.194058958e-04
+1.011587929e-04
+1.831519467e-02
+1.989602306e-03
+1.548870267e+01
+6.446772767e-01
+3.120827620e-05
+2.839228937e-04
+2.005833766e-03
+1.079509650e-04
+9.816246192e-04
+1.018590824e-02
+1.186032313e-04
+7.690571739e+01
+1.343124167e-04
+2.707457452e+03
+1.037485311e-03
+3.467543544e-05
+1.002231990e-04
+1.169823877e-02
+9.086510186e-05
+5.916372253e-06
+3.400382495e-04
+3.907175719e-05
+1.220030003e+01
+1.094648318e-03
+6.676743565e-04
+1.279030130e-04
+5.888983770e-05
+3.387152450e-05
+1.092565659e-04
+3.380016602e-02
+4.778126101e-02
+6.987028451e-02
+1.720873494e-04
+1.740801628e-03
+4.154616729e-05
+6.691856820e-04
+4.124107931e-05
+2.090512277e-04
+1.116032635e-04
+4.581842675e-05
+2.320316339e-04
+2.579132701e-04
+4.033540611e-04
+1.035860427e-03
+1.132396718e-02
+7.049685793e-04
+1.459859381e-02
+2.852761909e-04
+2.245103168e-04
+1.609967772e-04
+1.106603450e-04
+4.704172185e-05
+1.944785365e-03
+4.708323250e-03
+7.723450495e-04
+1.238382750e-04
+2.981628886e-03
+9.941857026e-03
+1.366463099e-01
+9.229987812e-03
+3.520577886e-03
+2.506228002e-03
+1.530047520e-03
+3.297701380e-02
+3.297188979e-05
+1.280647104e-04
+7.052847342e-03
+6.089192647e-02
+1.956313582e-04
+6.932423019e-01
+1.670732560e-01
+1.581903181e-03
+1.213040897e-02
+1.542608947e-02
+2.142021142e-02
+6.111552345e+00
+3.793395998e-04
+1.257819038e-04
+3.573408369e-03
+3.056884047e-05
+2.851574339e-06
+2.331438740e-03
+9.966415160e-03
+1.354204297e+00
+2.813254175e-04
+2.613055859e-03
+9.676874121e+01
+5.263156416e-03
+4.722857745e-03
+5.946163652e-05
+1.187270452e-02
+1.126497077e-03
+1.797140157e-02
+1.398767335e-03
+2.686175396e-01
+2.277916484e-04
+3.228608761e-03
+5.240539022e-05
+4.012059090e-02
+1.191456567e-03
+5.860064442e-05
+2.612313212e-04
+1.599840350e-02
+6.177517762e-04
+9.182482169e-05
+5.271484203e-02
+3.086465016e-04
+1.710119333e+00
+3.743238494e-05
+1.068307990e-03
+5.258355167e-01
+3.662462400e-03
+1.937381717e-04
+1.435414072e-04
+1.250345653e-03
+2.141785293e-04
+6.054898017e-04
+8.749800191e-04
+7.646500678e-04
+2.946888713e-05
+4.021347732e-04
+2.764084896e-03
+2.001548767e+00
+9.679155813e+00
+9.018388173e-01
+1.133920628e+00
+3.759890823e+01
+7.439026836e-05
+2.105641543e-01
+2.356425672e-04
+8.154619072e+02
+1.065558870e-04
+1.302289779e+00
+2.877127069e+00
+4.359193830e-04
+7.166859005e-04
+1.411517857e-04
+3.610076233e-03
+1.157866424e-02
+8.188422643e-05
+2.627044213e-02
+1.006379126e-04
+1.767519273e-01
+8.238151996e-03
+1.017712173e-04
+1.554703969e-04
+2.187603370e+01
+8.920120887e-02
+3.854088021e-03
+3.492186660e-08
+2.070172873e-04
+6.249158118e-01
+3.837388403e-03
+1.972167614e-02
+2.201984812e-04
+1.593144721e-03
+6.073536248e-03
+2.051324085e-04
+6.043465805e-02
+7.066293595e-01
+2.364827302e-04
+1.041689409e-01
+5.815357776e-05
+1.735862903e-04
+1.081238704e+00
+1.176684239e+01
+3.505629248e-04
+2.464554963e-04
+6.387533857e-06
+6.058687121e-04
+1.023804650e-02
+5.786125750e-03
+2.192699258e-02
+6.834193649e-05
+9.598497830e-03
+1.010363523e-03
+3.791722907e-01
+2.878374165e-02
+1.126946216e-02
+1.620185559e-01
+6.487755032e-05
+1.938452083e-04
+2.660571709e-04
+1.468616400e-04
+1.207742212e-01
+1.510010260e-04
+9.053625916e-04
+4.199121570e-03
+8.479303011e-03
+1.766544583e-04
+1.748767438e+00
+9.268292345e-04
+3.723644941e-03
+3.271314015e-02
+9.248933975e-03
+4.153056631e-03
+5.526014262e-01
+6.679741823e-05
+1.492739330e+00
+5.325524884e-05
+3.195004299e-03
+2.509990957e-04
+6.485645405e-03
+6.766683493e-02
+3.786349051e+00
+5.105782998e-05
+3.806439567e-04
+1.511134107e-04
+2.192416739e-03
+3.648682029e-03
+6.528530224e-02
+2.052812889e-02
+5.813670098e-05
+5.879437618e-04
+7.837220677e-04
+1.249756636e-02
+1.838549477e-04
+9.089393496e-01
+9.855018435e-01
+2.012660372e-02
+5.745255410e-04
+6.492404366e-04
+2.264057713e-02
+2.390843043e-01
+2.739448698e-04
+1.714154217e-03
+4.531989094e-03
+3.615862201e-05
+8.310542953e-02
+9.485217445e-05
+3.328304772e-04
+1.219078379e-04
+2.257561398e+04
+1.212149467e-03
+2.041112720e-04
+3.308687829e-05
+1.034466025e-02
+1.130742365e+00
+3.936763242e-04
+5.550218982e-02
+2.506129167e-02
+9.183125539e-05
+7.852401702e-02
+4.896389001e-04
+1.214092116e-04
+3.980077904e-04
+8.026000722e-04
+8.055832097e-05
+5.491802119e-03
+5.042388658e-03
+4.278239440e+00
+1.858664444e-01
+5.318058675e-01
+6.662556260e-01
+1.460639065e-04
+2.271309523e-04
+1.766374919e-03
+5.171547061e-05
+1.938860548e-02
+1.164869205e+00
+2.414055598e-05
+3.242346864e-03
+4.754563053e-02
+2.393291872e-05
+9.639989270e+02
+1.226608835e-04
+3.356429452e-04
+2.381303791e-03
+1.075278917e-04
+6.892491511e-04
+8.706712897e-05
+2.648325234e-05
+3.551785367e-05
+8.327007634e-04
+3.635545916e-04
+2.614563808e-05
+8.884920331e-03
+6.678429233e-03
+1.752342771e-03
+2.856481151e-06
+2.723523786e-05
+1.504430872e-02
+9.639130647e-05
+1.625329517e-01
+1.293048085e-01
+6.931513680e-05
+4.208892971e-04
+4.789927857e-04
+4.342192339e-02
+1.179587272e-04
+1.375335879e-04
+1.318645463e-04
+2.374972134e-02
+6.791015521e-05
+1.013582397e-01
+4.294957170e-05
+5.788516285e-03
+3.203987505e-01
+1.509474611e-04
+2.574464167e-02
+3.313339165e-05
+9.683307372e+02
+1.123272955e-02
+5.157250165e-05
+1.057263523e-05
+2.851640909e-04
+1.545491189e-04
+6.737254153e-05
+5.261739279e-02
+3.647813939e-04
+2.624528239e-01
+5.353611518e-05
+5.779632936e-04
+2.528096887e-05
+1.697661326e+01
+1.778500598e-02
+7.450740100e-05
+1.024063912e-03
+5.713573139e-03
+2.119528478e-04
+6.361275951e-02
+3.791792439e-02
+5.906782929e-03
+1.097751556e-04
+6.139410404e-05
+1.232884407e-03
+1.999182632e-04
+3.287969237e-05
+6.435720974e-04
+9.262523817e-05
+1.462336834e-04
+1.137083762e-04
+4.238472393e+05
+1.710580334e-03
+5.683553770e-04
+5.686083343e-04
+2.858448703e+00
+3.972459960e-04
+5.330910566e-03
+1.140035042e-04
+3.657215748e-05
+9.216098373e-05
+2.350392574e-03
+2.220791904e-03
+1.349208985e-04
+3.113902797e-04
+1.372138095e-04
+4.256864976e-03
+2.507781815e-04
+5.340777461e-06
+6.095234866e-04
+8.387995759e-03
+3.364133022e-01
+3.532281647e-04
+2.337102821e-01
+6.832662909e-01
+1.616348731e-03
+1.155654942e-04
+1.928066385e-01
+1.337097209e-02
+3.017508723e-04
+1.032343013e-03
+1.830301688e+01
+8.943956721e-03
+6.008754576e-04
+8.168280467e-02
+3.062459367e-04
+1.965225149e-04
+1.350705602e-04
+9.003818774e-05
+5.410849900e-04
+2.188753855e-02
+1.136494690e-01
+2.467628347e-05
+1.203950066e-04
+9.267072769e-04
+1.242539249e-04
+1.091153989e-03
+7.784308869e-04
+3.678691149e-01
+4.095344387e-03
+6.014656742e-04
+1.872846732e-04
+1.921087689e-04
+2.253489245e-03
+2.590514113e-02
+9.198905052e-04
+9.965289925e-05
+3.130274250e-05
+1.282393462e-04
+2.217401356e-02
+1.910233589e-04
+1.935937522e-04
+5.152891349e+00
+1.106679437e-02
+1.101138203e-04
+1.755269751e-01
+9.236526186e-02
+6.058256777e-01
+4.074142011e-04
+6.357796535e-04
+1.360686220e-04
+1.063790763e-03
+9.093316268e-04
+5.926244854e-05
+5.850313918e-02
+1.737336649e-03
+5.199681629e-04
+4.740251136e-04
+1.112322005e-02
+2.915411294e-04
+7.643180068e-05
+2.672248028e-02
+2.128443342e-04
+1.244875843e-04
+6.855742465e-05
+2.210725343e-02
+3.671489298e-04
+6.325799486e-02
+1.780904491e+01
+5.794290765e-03
+2.953118149e-05
+4.671551094e-04
+5.575524178e-03
+7.074274922e-03
+3.229163000e-03
+5.944396810e-02
+1.915872005e-04
+1.014634863e-02
+1.441566419e-03
+4.272389089e-05
+2.032550976e-01
+2.164725458e-04
+1.408648363e-04
+3.079029637e-04
+5.816370318e-02
+1.125426847e-03
+5.614227714e-01
+1.194500648e-02
+1.491767263e+02
+3.383832567e-01
+2.476709985e-03
+6.227176645e-05
+7.536097259e-01
+5.660936046e-04
+8.216567297e-05
+4.179184665e-02
+2.346358242e-05
+3.954143606e-03
+6.341927796e+02
+2.039994748e-04
+1.086809468e-01
+1.333373503e-04
+1.316001137e-03
+2.001403476e-01
+1.402205845e-01
+2.611351736e-02
+3.569609392e-03
+4.051382570e-02
+1.490023426e+01
+7.616610461e-04
+2.263766602e-02
+9.353370065e-05
+2.732060143e-04
+8.357388496e-03
+3.516679699e-03
+4.039281758e-04
+5.469498729e-02
+7.540693810e-04
+9.133943908e-03
+2.233578137e-04
+1.191817489e-04
+5.207658975e+00
+2.440202281e-04
+2.080312081e-04
+1.860996854e-03
+2.584839289e-04
+1.579391875e-04
+1.886637064e-03
+4.728910657e-03
+3.136910195e-02
+5.774952299e-03
+9.395471637e-05
+8.705826541e-05
+6.726928731e-02
+3.763740223e-05
+6.116355611e-01
+5.313319830e-05
+1.072341825e-04
+4.837522101e-04
+1.131697262e-04
+6.762610796e-03
+2.708581972e-04
+8.748600221e-01
+1.423058910e-04
+9.209516242e-05
+1.856514059e+02
+1.055481244e-04
+2.161677923e-02
+7.553763075e-05
+3.970981334e-02
+3.281842309e-03
+1.026415093e-02
+1.848018893e-04
+1.355000016e-03
+5.267400023e-04
+1.016329615e-01
+2.397200980e-04
+1.746394500e-02
+8.703509981e-03
+1.296334020e-04
+9.204403457e+02
+4.449984325e-01
+2.022934739e-03
+3.666778291e-03
+4.240908426e-05
+3.459727102e-04
+2.053420888e-04
+1.157071891e-01
+1.363669456e-04
+1.702912281e-05
+2.423037100e-02
+5.000134449e-04
+7.407267627e-05
+1.128215585e-03
+6.435332253e-02
+6.601933196e-02
+1.163252660e-04
+2.051867257e-04
+1.116142409e-04
+4.890392337e-05
+2.259964752e-01
+4.333049437e-06
+9.137212628e-06
+4.399601535e-04
+1.128250461e-04
+8.220609960e-02
+3.434228729e-04
+1.997885285e-06
+3.746373625e-03
+1.783264969e-01
+2.513340762e-03
+1.723785745e-04
+2.568353575e-05
+1.232542079e+01
+1.069392684e-04
+4.413292795e-05
+3.726152071e-04
+9.473019173e-05
+2.927996899e-04
+9.930838136e-05
+1.276803422e-04
+4.584846266e-06
+1.861357833e-03
+2.533527887e-02
+7.114240229e-04
+3.131072504e-04
+1.039604966e-04
+1.660890629e-04
+3.927308744e-03
+9.379375770e-05
+1.225443190e-04
+2.714942420e-02
+1.447964912e-02
+2.823860181e-05
+7.470523204e-04
+1.900906380e-02
+5.014169465e-05
+4.047037530e-04
+5.563333417e-05
+4.466739563e-04
+8.692795891e-04
+2.602127277e-03
+2.925309790e-04
+5.052368103e-05
+1.354226954e-04
+2.305815648e-05
+1.355268547e-04
+3.289279911e-03
+3.325337978e-02
+1.554025776e-03
+1.653465800e-04
+2.152226639e+01
+1.311773002e+01
+3.205902794e-02
+9.823884396e-04
+3.168430463e+00
+1.258193298e-03
+1.061245162e-04
+9.581398749e-03
+7.051854639e-01
+2.809456687e-05
+4.981698631e-03
+3.999833670e-05
+2.471565349e-04
+1.079186221e-04
+5.870062606e-01
+3.832244738e-05
+6.877489971e-04
+7.037801185e-03
+3.685553769e-01
+1.491764933e-04
+1.304009780e-02
+2.180676924e-04
+3.389240168e-03
+1.142315046e-04
+9.575899657e-04
+4.960417218e-05
+5.062567959e-05
+1.157219344e-04
+2.708079495e-04
+6.286693208e-04
+2.270751602e-04
+1.211556245e-01
+4.262378055e-03
+2.088632017e-02
+1.986301851e-04
+3.114100076e-04
+3.158039050e-04
+6.128501856e-04
+1.410503310e-04
+2.046889015e-01
+8.078140376e-04
+1.129148878e-03
+4.309000352e-04
+1.929389979e-02
+3.133165382e-03
+1.260054614e-05
+3.596146856e-05
+1.901510069e-03
+2.553021289e-03
+2.619515722e-04
+5.931373303e-05
+1.475859767e-03
+4.366272933e+00
+1.170972641e-04
+1.494986734e-04
+2.107853089e-04
+7.803837399e-07
+2.361375492e-04
+3.114570131e-05
+6.767353195e-04
+5.242771012e-06
+8.219747471e-03
+2.040357385e-02
+4.065491314e-03
+1.815709729e-04
+1.476815224e-04
+2.802228835e-05
+1.492292367e-04
+9.996196807e-05
+1.450582643e-02
+6.534519523e+00
+9.118804523e-05
+9.320429646e-02
+9.815014615e-04
+3.729733622e-04
+1.113756309e-01
+7.260863411e-01
+1.509362918e-03
+4.513728355e-02
+4.708677043e-05
+1.031052948e-03
+2.777621140e-04
+1.562437699e-04
+1.085859233e+01
+8.131613704e-02
+3.880282578e-04
+3.283342319e-04
+8.438467332e-05
+1.297754706e+01
+1.380029047e-04
+2.658677913e-05
+3.364947681e+02
+4.240577221e-04
+2.285210337e-05
+1.573018018e-04
+2.080205759e-02
+4.930386129e-04
+9.854944074e-05
+1.052896280e-04
+6.227241435e+01
+3.528991205e-04
+1.185312483e-04
+3.615986547e-04
+9.668361425e-06
+8.361545327e-03
+2.740821113e+00
+4.599572047e-02
+1.696356509e-04
+3.643987106e-02
+8.167226124e-04
+3.102075683e-04
+7.787896961e+00
+1.416435128e-02
+1.303327707e-04
+5.272305796e-02
+7.518430943e-03
+3.351234898e-04
+1.796930896e-03
+3.581697236e-04
+1.124757858e-04
+9.228471900e-05
+2.222957005e-05
+4.557912620e+04
+6.223351052e-06
+4.845643963e-04
+9.360164410e-05
+2.550307096e-04
+1.765008108e-03
+1.081811315e-03
+2.461043324e-04
+3.354875943e-02
+1.275580650e+00
+1.139959672e-01
+1.023979237e+01
+6.460315878e+00
+1.121323513e-04
+1.546594530e-04
+1.293638214e-04
+4.956363611e-02
+5.709073082e-05
+3.214963224e-05
+1.031409169e-01
+1.655303263e-04
+1.655465115e-01
+1.008034112e-04
+1.301270298e-04
+1.054905192e-03
+1.455493528e-02
+2.112107789e-01
+2.037737039e+02
+2.500822314e-04
+5.996018951e-01
+1.414309119e-01
+1.083909825e-04
+2.157197690e-02
+1.337031769e-02
+2.769741919e-03
+8.197414678e-04
+1.320395245e-02
+8.933345362e-04
+1.669210751e-02
+1.018939946e+01
+1.197659900e-04
+1.983551782e-04
+3.008525154e-04
+1.253912175e-02
+1.557291634e-02
+4.526924177e-02
+1.171826786e-03
+3.128654585e+00
+5.577390760e+05
+1.295857876e-04
+1.651265256e-02
+5.733146242e+01
+8.452290913e-04
+2.014240383e-03
+3.460074285e-04
+5.838985700e-03
+7.112566945e-03
+1.869466438e-01
+4.765440485e-03
+1.248378501e-04
+1.000399208e-04
+2.525828094e-03
+6.082682953e-03
+1.011381634e-04
+3.185923639e-04
+5.224705147e-04
+3.280390914e-05
+8.715706159e-04
+7.930556369e-03
+4.580985182e-02
+6.757655850e-04
+2.382727584e-03
+1.065609853e+01
+2.427139501e-03
+1.300888123e-04
+4.335274882e-04
+8.267723810e+00
+1.208458030e-04
+1.237501363e-04
+7.024189439e-04
+8.794054280e-03
+8.548494953e-05
+1.280108983e-04
+1.021062160e-04
+2.967084289e-05
+2.689063097e-03
+1.135473926e-04
+1.110252903e-04
+4.004230347e-02
+3.689425036e+01
+5.980471294e-03
+1.414167825e-02
+1.315285877e-01
+2.476672527e-05
+1.138191748e-04
+4.726715474e-05
+2.944863584e-04
+4.140798684e+01
+3.173382963e-03
+1.203475363e-04
+5.979086173e+02
+1.103127774e-05
+3.243333439e-05
+2.974493193e-01
+3.484398356e-04
+1.837552457e-03
+4.643960352e-05
+3.516928637e-03
+1.059770653e-04
+9.563081020e-05
+9.258296340e-03
+5.891289261e-05
+1.251235076e-02
+5.337367630e-03
+4.859525943e-04
+5.448877343e-05
+2.770576922e-03
+2.178023997e-04
+1.085590656e-04
+1.032016725e-04
+1.022991935e-02
+2.138692546e-04
+2.138839427e-02
+3.633844768e-02
+8.378415142e-05
+5.322144621e-04
+3.596902641e-03
+1.560038234e-04
+4.899843769e-04
+1.135795298e+01
+9.396936619e-04
+9.023823569e-05
+3.088045747e+00
+9.413418639e-05
+8.872917930e-04
+2.353400476e-03
+5.628977029e-05
+1.474836093e-03
+9.480268554e-06
+1.624456418e-02
+6.636857291e+02
+3.756995307e-04
+6.346707812e-01
+7.290867703e-06
+2.517949649e-01
+1.916257136e-04
+3.516378334e-04
+9.387644444e-05
+9.428890442e-05
+8.719505546e-01
+1.127126157e-04
+7.311629248e-04
+3.457815336e-05
+2.039559066e-04
+4.194926473e-02
+3.028158196e-05
+5.799317948e+01
+1.360753276e-03
+1.679520947e-04
+7.276754706e-03
+5.643962954e-05
+7.667206385e-03
+3.928060744e-03
+6.653581254e-04
+4.096509145e-03
+1.091107920e-01
+8.548524659e+02
+3.349636293e-04
+5.913560784e-03
+2.979877290e-03
+5.197317955e+00
+2.283654120e-04
+1.981310670e-04
+5.082389398e-05
+4.542851813e-05
+5.767698162e-04
+2.204984267e-03
+1.121904341e-04
+3.128429170e-03
+8.380749835e-05
+7.168165555e-05
+1.832787071e-02
+2.459180649e-05
+9.523408352e-05
+3.403382942e-03
+2.073324990e-04
+4.619931543e-03
+5.772622252e-04
+6.439976526e-05
+4.115863452e-05
+3.950532689e-02
+1.299819887e-01
+4.105004463e+01
+4.601722241e-02
+2.211404837e-04
+2.583990232e-03
+9.922194871e-03
+2.656394920e-01
+3.858654455e-04
+3.516052424e+00
+2.418724223e-04
+4.481083929e-04
+3.806946044e-05
+2.358260482e-04
+2.141012234e-04
+9.675511093e-03
+4.023708400e-05
+1.558195410e-04
+4.056034531e-05
+1.224707562e-04
+1.325723645e-04
+4.895684571e-04
+4.067396732e-03
+2.469019094e-03
+7.938547254e-01
+5.104679277e-04
+6.572373702e-04
+4.788159213e-03
+2.276806510e-04
+1.990084794e-01
+6.983011462e-04
+9.007090319e-04
+1.471657954e-04
+1.568809966e-03
+3.067219810e-04
+1.207477743e-02
+2.429222425e-05
+4.861923373e-05
+2.468034872e-01
+3.148048725e-05
+5.306600282e-02
+1.815492624e-04
+2.462680043e-01
+3.327928345e-04
+1.882544138e-03
+1.103899372e-04
+3.664071097e-05
+1.410166036e+01
+1.689054711e-02
+7.567167690e-02
+1.240105753e-04
+2.498971531e-03
+9.825890714e-03
+3.182174684e-04
+7.607676274e-05
+9.482292407e-05
+7.229516539e-04
+3.392454948e-03
+2.244334434e-05
+1.774024765e+00
+6.839046456e-04
+4.727255665e-04
+9.281857447e-01
+1.535883616e-04
+7.709875055e-01
+7.130244301e-04
+9.396416016e-05
+8.762427628e-03
+7.320722624e-05
+4.761782022e-04
+1.422110884e-04
+2.433148599e-04
+1.787594550e+00
+3.093708511e-02
+1.079651944e-04
+9.700861802e-03
+5.116775019e-01
+7.216192107e-05
+7.018661752e-05
+4.295732553e-03
+3.294463373e-05
+1.210453147e-02
+8.100956569e-02
+1.585321910e-03
+8.817738764e-05
+5.148847198e-01
+1.299032429e-01
+2.901071197e-05
+1.003508641e-02
+1.881606260e+00
+1.740318079e-04
+1.696952094e+01
+1.539545047e-02
+8.163515934e-02
+2.025713456e-04
+1.214363546e-04
+8.691956517e-03
+1.608013885e-04
+1.101652851e-04
+3.446830873e-02
+5.409091500e-05
+4.244420895e-04
+2.662941694e-01
+7.758870243e-04
+1.036076609e-04
+7.129974834e-05
+8.046972731e-05
+4.776089006e-05
+1.161366560e-02
+8.285895084e-03
+4.041457526e-04
+1.343652142e-01
+2.809430727e-04
+2.149871994e-01
+1.351552343e-04
+3.756040907e-03
+8.686266262e-01
+4.103791235e-03
+4.162803530e-04
+4.810111700e-01
+1.648445512e-03
+7.683037789e-02
+9.391122442e-05
+3.746742912e+01
+1.437770918e-04
+1.235186996e-03
+1.263656361e-04
+5.139052981e-01
+8.827684721e-02
+4.131602477e+00
+1.042327086e-04
+1.161200978e-04
+1.791809445e-02
+4.161504213e-05
+9.637383692e+01
+2.540542612e-03
+3.451065513e-04
+1.375080609e-04
+2.328872007e-03
+1.782198706e+00
+1.167608492e-04
+9.147351716e-02
+1.494902039e-03
+1.530690309e-04
+2.449407644e-05
+6.170980956e-02
+6.955847458e-01
+2.344147663e-03
+9.580718135e+00
+1.491890895e-03
+9.573173402e-06
+2.750738576e-04
+9.245097109e-04
+1.534796761e-04
+1.005258457e-04
+5.988869543e-01
+4.614088778e-05
+1.601353109e-04
+9.791225750e-05
+2.643941643e-04
+9.064656048e-05
+3.079960351e-01
+1.361559760e-04
+2.380912405e-03
+1.658806385e-04
+8.569119726e-05
+2.879302961e-05
+9.419752050e-05
+1.677128322e-04
+6.676152296e-03
+6.691071371e-03
+9.904304271e-05
+3.882984707e-02
+2.968711665e-03
+1.102007470e-01
+1.177141451e-02
+2.868207238e-05
+2.953275916e-04
+9.654682824e-05
+6.884934400e-05
+1.032474367e-04
+2.165344231e-02
+1.858051144e-04
+7.611391207e-02
+2.267029091e-04
+7.307390695e-04
+1.387304113e-03
+2.052774045e-04
+3.210827035e-05
+1.288836707e-04
+1.128107515e-01
+1.017415635e-04
+1.052576251e+01
+3.243400126e-05
+3.197408063e-04
+3.894927923e-04
+1.136627647e+01
+2.195296405e-04
+7.202976656e-04
+2.602185986e+01
+1.024559301e-04
+3.014142540e-03
+2.463569686e-04
+6.768254698e-02
+4.195984062e-02
+1.211295294e-04
+3.546733580e-04
+1.357670363e-04
+2.667222247e-05
+9.630440305e-04
+1.099605755e+01
+5.016723110e-03
+3.104891543e-03
+7.999847226e-03
+1.411460123e-04
+4.024018503e-04
+2.909383475e-05
+5.627652994e-05
+7.197045665e-05
+1.527939945e-03
+2.384578790e-04
+4.055189638e-04
+2.014679260e-04
+1.649079849e-02
+1.726791289e-02
+9.943404808e-02
+1.524247216e-01
+1.162223002e-04
+6.792188710e-02
+3.578913900e-01
+2.064700725e-04
+4.197650112e-04
+2.080114197e+03
+1.046890360e-04
+3.078011245e-04
+7.776949058e+00
+6.599654781e-04
+1.348364593e-03
+8.805722407e-05
+2.497968081e-04
+2.132780758e-04
+9.830052305e-05
+9.466811723e-06
+4.609414732e-05
+1.213265970e-04
+3.072609546e-04
+1.857096047e-04
+1.552325558e-03
+1.155885756e-03
+1.160103610e-03
+2.513699688e-05
+3.051704234e-05
+1.845676222e-01
+1.739580726e-04
+1.174762036e-04
+8.588444340e-04
+3.592368648e-04
+7.898958791e-04
+1.601094482e-03
+3.818193760e-04
+6.968689320e-05
+2.405338247e-05
+9.936696575e-04
+1.391451560e-04
+4.626304893e+01
+1.208468603e-01
+5.822398475e-03
+5.629607566e-03
+1.696711863e-04
+4.144406619e-04
+6.591990768e-05
+1.435163652e-04
+7.506207850e-03
+1.178122353e-02
+7.136806085e-03
+1.364087703e-05
+4.741922973e-05
+5.312260852e+02
+6.779973748e-04
+8.387043840e-02
+1.303135677e+00
+1.007080930e-04
+1.110172615e-04
+1.767620376e-02
+3.636411613e-05
+1.087565662e-03
+2.275146457e-02
+2.570721130e-05
+1.420146209e-04
+1.195304794e-04
+1.951438002e-04
+2.314505051e-02
+1.734735034e-04
+2.107707587e-01
+3.273084954e-04
+2.366787035e-04
+1.540099548e-04
+2.169736108e-02
+1.663549064e-04
+4.703180165e-01
+6.054657458e-04
+3.993058982e-02
+2.772559541e-06
+2.496193832e-04
+2.380338581e-04
+1.223018739e-04
+2.193758625e-04
+1.676091477e-02
+1.213373273e-06
+1.250374679e-04
+3.716033766e-01
+1.000399840e-02
+8.899739384e-05
+1.076044744e-04
+1.127569696e-04
+1.465633937e-02
+8.086150878e-02
+4.198961265e-05
+3.950688700e-05
+1.200341280e-03
+6.480661903e-05
+2.312503029e-04
+1.979967947e-01
+1.444043311e-04
+9.106449667e+01
+8.995789800e-05
+3.592918908e-05
+4.116833287e-05
+3.853527107e-04
+1.075427047e-04
+2.077270549e-02
+4.110755225e-02
+1.897843450e-01
+9.972438065e-04
+9.969016666e-05
+2.901606512e-04
+1.425151937e-04
+1.621407284e-02
+3.518980820e-04
+7.707372015e-02
+5.654405319e-05
+9.332336478e-05
+1.677706272e+01
+9.238284645e-05
+1.228102850e-01
+9.600679071e-04
+1.993144658e-03
+5.329630001e-04
+1.281229552e+00
+5.557753608e-04
+1.783317591e-04
+3.588640855e-04
+1.377971071e-04
+4.872908077e-02
+6.480286726e+00
+5.029674162e-05
+9.934069791e-03
+1.214629176e-04
+1.359446358e-04
+1.184796147e-04
+1.679163335e-02
+1.991328550e+00
+1.214352694e-03
+4.856466889e-01
+3.686723944e-04
+3.757261605e-04
+2.160989276e-04
+2.925931586e-05
+1.193010614e+00
+1.790104239e-04
+4.622920674e-01
+5.567250388e+02
+1.009938372e-01
+5.808002991e+00
+2.883979858e-04
+9.186991967e-05
+2.016297647e-04
+3.162474764e-04
+7.003534461e-04
+4.953687878e-03
+2.542121619e-03
+8.700896036e-04
+2.578545527e-02
+1.355832797e-04
+9.275334440e-04
+5.411374800e-05
+1.537080481e-03
+1.231747034e-04
+3.758991956e-03
+8.921408704e+02
+1.112385376e-04
+8.828054543e-05
+1.649526303e-03
+8.771704599e-01
+5.898960724e-04
+8.577883281e-03
+1.469454030e-02
+3.965325460e-02
+1.906454990e-04
+1.178028573e-04
+2.706747696e-04
+1.302051510e-03
+1.241894615e+01
+7.795976139e-04
+2.819890496e+00
+2.498774377e-05
+8.955062845e-04
+5.891145930e-05
+1.518587247e+02
+7.033568819e-04
+2.231380670e-05
+1.210751613e-04
+1.877660204e-04
+1.264579897e-04
+1.659840025e-01
+1.320462019e-04
+2.038764963e-02
+4.038022792e-05
+2.129851996e-02
+7.435728290e+00
+3.582670579e-04
+2.513311254e-04
+4.516530721e-02
+3.297510819e+02
+2.562713308e-03
+9.027000831e-06
+9.238170468e-04
+2.531928212e-02
+1.373062562e-04
+1.335125321e-04
+6.074539008e-04
+5.369900572e-04
+2.492311403e-02
+1.795169585e-04
+7.893990096e-04
+3.852437641e-01
+6.208174010e-03
+3.520850586e-05
+1.960267763e-03
+9.585785657e-05
+1.334571718e+01
+9.898259475e-05
+4.900171378e-04
+1.954468828e-03
+2.463145888e-03
+1.018049686e-04
+4.267717529e-04
+4.148005723e-02
+2.650199534e-03
+7.174477761e-05
+8.713744946e-04
+3.619008970e-04
+3.335875334e-02
+2.546482008e-02
+4.742717689e-04
+5.510455038e-04
+3.030801503e-03
+3.056947669e-02
+3.315053717e-02
+1.672462329e-01
+4.571960152e-05
+3.601283810e-04
+2.273382619e-04
+2.256283865e-03
+2.406434239e-04
+7.117447369e-03
+1.775247364e-01
+7.620281579e-04
+1.153421712e-03
+6.912314270e-06
+4.496315388e-04
+3.720311617e-05
+5.703206191e-04
+4.118684298e-01
+8.445167709e-03
+1.082570845e-01
+6.807415661e-05
+4.215988499e-04
+6.002677003e-05
+6.135207878e-03
+8.268490174e-05
+2.260675836e-04
+8.161941689e-03
+8.825143571e-05
+1.119111030e-03
+1.622389800e-04
+8.632762162e-03
+2.349305042e-02
+5.729231842e+00
+1.297705190e+01
+1.259568232e-04
+1.519563384e-03
+1.905554433e-01
+5.639776292e-03
+6.852533710e-04
+2.470262316e-05
+6.474543977e-05
+5.422549635e-02
+4.740072402e-04
+1.992265382e-02
+3.103977965e-04
+3.104605467e-04
+5.659488989e-05
+9.038825926e-05
+1.456391164e-04
+4.374694250e-05
+2.487315956e-03
+5.753437922e-02
+1.210284428e+02
+4.593975972e-01
+1.061456000e-02
+2.862383002e-04
+4.501879272e-03
+1.093495163e-04
+1.108490651e-03
+1.581400763e-05
+8.475687354e-04
+5.265945866e-02
+9.149233887e-05
+1.429415766e-04
+9.952070558e-04
+2.657892069e-03
+1.146012615e-03
+3.652815601e-04
+2.724771515e-04
+3.254465759e+00
+1.125893737e-04
+2.192686509e+02
+1.366554114e-04
+7.913473591e-04
+3.782597720e-02
+1.369205061e-04
+1.015843498e-03
+2.456887865e-04
+1.523115465e+00
+3.422862957e+00
+2.259416933e-04
+1.421937261e-04
+3.898091419e-05
+1.572350823e-03
+3.848270122e-04
+2.661667965e-03
+4.739872211e-01
+1.166578481e-04
+2.860269966e+05
+1.103438901e-03
+2.374822723e-04
+8.476209758e-02
+6.180692692e-02
+2.911689675e-04
+1.300493641e-03
+6.868988577e-05
+2.329961156e-03
+2.986034208e-03
+9.749602234e-05
+1.407913649e-04
+1.376873491e-04
+1.462709667e-03
+1.709018313e-01
+3.872968309e-04
+6.144923039e-02
+2.102210189e-02
+1.854758324e-04
+1.959116825e-01
+9.376191433e-05
+9.148540379e+01
+1.123414064e-04
+4.716637145e-05
+1.196857067e+00
+4.466287729e-02
+1.177316530e+02
+2.314903709e+00
+9.962053975e-04
+6.573553564e-06
+2.984590978e-04
+4.257793553e-03
+3.414466498e-02
+1.191655122e-03
+2.816036581e-03
+3.569829141e-04
+4.124290336e-03
+2.283821700e+00
+1.385213659e-04
+2.103888027e-04
+1.944774213e+00
+1.339213108e+00
+4.404706241e-02
+4.630068903e-04
+5.527571105e-04
+1.206071458e-03
+2.791106513e-03
+2.553389476e-02
+4.254196581e-01
+8.368916976e-03
+1.736629013e-03
+3.871618875e-04
+1.420400446e-04
+4.981802572e+00
+9.586116308e-03
+1.092576081e-01
+9.468186838e-03
+1.136629572e-04
+1.849087315e-02
+1.876225397e+00
+3.119823798e-02
+1.205040187e-02
+1.503416243e-03
+3.476448031e-01
+7.828807892e+02
+5.573640741e-01
+7.484527837e-05
+8.125565203e-05
+2.010678333e-04
+1.198639243e-04
+1.330130379e-04
+4.884049218e-05
+6.736229685e-03
+1.488978611e-04
+4.261148894e-05
+3.014520710e-03
+1.776170834e-04
+6.037534955e-05
+1.064832948e-03
+8.513619987e-04
+1.743230221e-04
+2.237944193e-03
+9.504451723e-05
+1.309867154e-02
+5.481224773e-02
+6.779140407e-04
+6.394068332e+00
+1.010270780e-02
+1.497781769e+01
+1.530677272e-03
+1.532131120e-03
+1.330915341e-04
+1.062403808e-04
+8.496368075e-02
+8.655627663e+00
+4.562587100e-04
+1.268882032e-02
+2.863978281e-04
+5.380908638e-05
+3.010177498e-01
+3.227609984e-03
+4.108360358e-05
+3.462506248e-03
+7.583142415e+02
diff --git a/t/ME_data/PSP_hj.lhe.gz b/t/ME_data/PSP_hj.lhe.gz
new file mode 100644
index 0000000..059ade7
--- /dev/null
+++ b/t/ME_data/PSP_hj.lhe.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6f2557f3b0c06ee0a034f34172c5de8f8e80762f837b3b8b5a157d6ea4b66be1
+size 369733
diff --git a/t/check_res.cc b/t/check_res.cc
index aee30d1..476fa15 100644
--- a/t/check_res.cc
+++ b/t/check_res.cc
@@ -1,164 +1,163 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "hej_test.hh"
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <utility>
#include "HEJ/Config.hh"
#include "HEJ/CrossSectionAccumulator.hh"
#include "HEJ/Event.hh"
#include "HEJ/event_types.hh"
#include "HEJ/EventReweighter.hh"
#include "HEJ/EWConstants.hh"
#include "HEJ/Fraction.hh"
#include "HEJ/HiggsCouplingSettings.hh"
#include "HEJ/Mixmax.hh"
#include "HEJ/Parameters.hh"
#include "HEJ/ScaleFunction.hh"
-#include "HEJ/stream.hh"
+#include "HEJ/EventReader.hh"
#include "fastjet/JetDefinition.hh"
#include "LHEF/LHEF.h"
namespace HEJ { struct RNG; }
namespace {
const fastjet::JetDefinition JET_DEF{fastjet::kt_algorithm, 0.4};
const fastjet::JetDefinition BORN_JET_DEF{JET_DEF};
constexpr double BORN_JETPTMIN = 30;
constexpr double JETPTMIN = 35;
constexpr bool LOG_CORR = false;
constexpr std::size_t NUM_TRIES = 100;
constexpr HEJ::ParticleProperties WPROP{80.385, 2.085};
constexpr HEJ::ParticleProperties ZPROP{91.187, 2.495};
constexpr HEJ::ParticleProperties HPROP{125, 0.004165};
constexpr double VEV = 246.2196508;
using EventTreatment = HEJ::EventTreatment;
using namespace HEJ::event_type;
HEJ::EventTreatMap TREAT{
- {no_2_jets, EventTreatment::discard},
+ {not_enough_jets, EventTreatment::discard},
{bad_final_state, EventTreatment::discard},
{non_resummable, EventTreatment::discard},
{unof, EventTreatment::discard},
{unob, EventTreatment::discard},
{qqbar_exb, EventTreatment::discard},
{qqbar_exf, EventTreatment::discard},
{qqbar_mid, EventTreatment::discard},
{FKL, EventTreatment::reweight}
};
bool correct_colour(HEJ::Event const & ev){
if(!HEJ::event_type::is_resummable(ev.type()))
return true;
return ev.is_leading_colour();
}
} // namespace
int main(int argn, char** argv) {
if(argn == 5 && std::string(argv[4]) == "unof"){
--argn;
TREAT[unof] = EventTreatment::reweight;
TREAT[unob] = EventTreatment::discard;
TREAT[FKL] = EventTreatment::discard;
}
if(argn == 5 && std::string(argv[4]) == "unob"){
--argn;
TREAT[unof] = EventTreatment::discard;
TREAT[unob] = EventTreatment::reweight;
TREAT[FKL] = EventTreatment::discard;
}
else if(argn == 5 && std::string(argv[4]) == "splitf"){
--argn;
TREAT[qqbar_exb] = EventTreatment::discard;
TREAT[qqbar_exf] = EventTreatment::reweight;
TREAT[FKL] = EventTreatment::discard;
}
else if(argn == 5 && std::string(argv[4]) == "splitb"){
--argn;
TREAT[qqbar_exb] = EventTreatment::reweight;
TREAT[qqbar_exf] = EventTreatment::discard;
TREAT[FKL] = EventTreatment::discard;
}
else if(argn == 5 && std::string(argv[4]) == "qqbar_mid"){
--argn;
TREAT[qqbar_mid] = EventTreatment::reweight;
TREAT[FKL] = EventTreatment::discard;
}
if(argn != 4){
std::cerr << "Usage: check_res eventfile xsection tolerance [uno]";
return EXIT_FAILURE;
}
const double xsec_ref = std::stod(argv[2]);
const double tolerance = std::stod(argv[3]);
- HEJ::istream in{argv[1]};
- LHEF::Reader reader{in};
+ auto reader = HEJ::make_reader(argv[1]);
HEJ::PhaseSpacePointConfig psp_conf;
psp_conf.jet_param = HEJ::JetParameters{JET_DEF, JETPTMIN};
HEJ::MatrixElementConfig ME_conf;
ME_conf.log_correction = LOG_CORR;
ME_conf.Higgs_coupling = HEJ::HiggsCouplingSettings{};
ME_conf.ew_parameters.set_vevWZH(VEV, WPROP, ZPROP, HPROP);
HEJ::EventReweighterConfig conf;
conf.psp_config = std::move(psp_conf);
conf.ME_config = std::move(ME_conf);
conf.treat = TREAT;
- reader.readEvent();
+ reader->read_event();
const bool has_Higgs = std::find(
- begin(reader.hepeup.IDUP),
- end(reader.hepeup.IDUP),
+ begin(reader->hepeup().IDUP),
+ end(reader->hepeup().IDUP),
25
- ) != end(reader.hepeup.IDUP);
+ ) != end(reader->hepeup().IDUP);
const double mu = has_Higgs?125.:91.188;
HEJ::ScaleGenerator scale_gen{
{{std::to_string(mu), HEJ::FixedScale{mu}}}, {}, 1.
};
std::shared_ptr<HEJ::RNG> ran{std::make_shared<HEJ::Mixmax>()};
- HEJ::EventReweighter hej{reader.heprup, std::move(scale_gen), conf, ran};
+ HEJ::EventReweighter hej{reader->heprup(), std::move(scale_gen), conf, ran};
HEJ::CrossSectionAccumulator xs;
do{
- auto ev_data = HEJ::Event::EventData{reader.hepeup};
+ auto ev_data = HEJ::Event::EventData{reader->hepeup()};
shuffle_particles(ev_data);
ev_data.reconstruct_intermediate();
HEJ::Event ev{
ev_data.cluster(
BORN_JET_DEF, BORN_JETPTMIN
)
};
auto resummed_events = hej.reweight(ev, NUM_TRIES);
for(auto const & res_ev: resummed_events) {
ASSERT(correct_colour(res_ev));
ASSERT(std::isfinite(res_ev.central().weight));
// we fill the xs uncorrelated since we only want to test the uncertainty
// of the resummation
xs.fill(res_ev);
}
- } while(reader.readEvent());
+ } while(reader->read_event());
const double xsec = xs.total().value;
const double xsec_err = std::sqrt(xs.total().error);
const double significance =
std::abs(xsec - xsec_ref) / std::sqrt( xsec_err*xsec_err + tolerance*tolerance );
std::cout << xsec_ref << " +/- " << tolerance << " ~ "
<< xsec << " +- " << xsec_err << " => " << significance << " sigma\n";
if(significance > 3.){
std::cerr << "Cross section is off by over 3 sigma!\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/t/h_1j.lhe.gz b/t/h_1j.lhe.gz
new file mode 100644
index 0000000..fbc0db9
--- /dev/null
+++ b/t/h_1j.lhe.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:186ffee4c98a93a5afe15db936c0638d728a4f0ee764b3a9d9acd3b1a234cc2c
+size 242335
diff --git a/t/h_1j_large.lhe.gz b/t/h_1j_large.lhe.gz
new file mode 100644
index 0000000..2eae66b
--- /dev/null
+++ b/t/h_1j_large.lhe.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d32e3afcdd2e22958a831c1d7fa35f1ff02baa60672e4f0d143c1c81ea7e5a70
+size 28926220
diff --git a/t/hej_test.cc b/t/hej_test.cc
index afde785..cbf1b00 100644
--- a/t/hej_test.cc
+++ b/t/hej_test.cc
@@ -1,563 +1,586 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "hej_test.hh"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdlib>
#include <iterator>
#include <memory>
#include <numeric>
#include <random>
#include <utility>
#include "HEJ/Particle.hh"
#include "HEJ/PDG_codes.hh"
HEJ::Event::EventData get_process(int const njet, int const pos_boson){
using namespace HEJ::pid;
HEJ::Event::EventData ev;
- if(njet == 0){ // jet idx: -1 -1
- ev.outgoing.push_back({gluon, { -24, 12, -57, 63}, {}});
- ev.outgoing.push_back({gluon, { 24, -12, 41, 49}, {}});
- ev.incoming[0] = {gluon, { 0, 0, -64, 64}, {}};
- ev.incoming[1] = {gluon, { 0, 0, 48, 48}, {}};
- return ev;
+ if(njet == 0){
+ switch(pos_boson){
+ case 0:
+ ev.outgoing.push_back({higgs, { 0, 0, 44, 132}, {}});
+ ev.incoming[0] = {gluon, { 0, 0, -44, 44}, {}};
+ ev.incoming[1] = {gluon, { 0, 0, 88, 88}, {}};
+ return ev;
+ default: // jet idx: -1 -1
+ ev.outgoing.push_back({gluon, { -24, 12, -57, 63}, {}});
+ ev.outgoing.push_back({gluon, { 24, -12, 41, 49}, {}});
+ ev.incoming[0] = {gluon, { 0, 0, -64, 64}, {}};
+ ev.incoming[1] = {gluon, { 0, 0, 48, 48}, {}};
+ return ev;
+ }
}
- if(njet == 1){ // jet idx: 0 -1 -1
- ev.outgoing.push_back({gluon, { 23, 28, -44, 57}, {}});
- ev.outgoing.push_back({gluon, { -11, -24, -12, 29}, {}});
- ev.outgoing.push_back({gluon, { -12, -4, 39, 41}, {}});
- ev.incoming[0] = {gluon, { 0, 0, -72, 72}, {}};
- ev.incoming[1] = {gluon, { 0, 0, 55, 55}, {}};
- return ev;
+ if(njet == 1){
+ switch(pos_boson){
+ case 0:
+ ev.outgoing.push_back({higgs, { 16, -32, -99, 163}, {}});
+ ev.outgoing.push_back({gluon, { -16, 32, 76, 84}, {}});
+ ev.incoming[0] = {gluon, { 0, 0, -135, 135}, {}};
+ ev.incoming[1] = {gluon, { 0, 0, 112, 112}, {}};
+ return ev;
+ case 1:
+ ev.outgoing.push_back({gluon, { -92, 84, -57, 137}, {}});
+ ev.outgoing.push_back({higgs, { 92, -84, -79, 193}, {}});
+ ev.incoming[0] = {gluon, { 0, 0, -233, 233}, {}};
+ ev.incoming[1] = {gluon, { 0, 0, 97, 97}, {}};
+ return ev;
+ default: // jet idx: 0 -1 -1
+ ev.outgoing.push_back({gluon, { 23, 28, -44, 57}, {}});
+ ev.outgoing.push_back({gluon, { -11, -24, -12, 29}, {}});
+ ev.outgoing.push_back({gluon, { -12, -4, 39, 41}, {}});
+ ev.incoming[0] = {gluon, { 0, 0, -72, 72}, {}};
+ ev.incoming[1] = {gluon, { 0, 0, 55, 55}, {}};
+ return ev;
+ }
}
if(njet == 2){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 198, 33, -170, 291}, {}});
ev.outgoing.push_back({gluon, {-154, 68, 44, 174}, {}});
ev.outgoing.push_back({gluon, { -44, -101, 88, 141}, {}});
ev.incoming[0] = {gluon, { 0, 0, -322, 322}, {}};
ev.incoming[1] = {gluon, { 0, 0, 284, 284}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, { -6, 82, -159, 179}, {}});
ev.outgoing.push_back({higgs, { 195, -106, 74, 265}, {}});
ev.outgoing.push_back({gluon, {-189, 24, 108, 219}, {}});
ev.incoming[0] = {gluon, { 0, 0, -320, 320}, {}};
ev.incoming[1] = {gluon, { 0, 0, 343, 343}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, { -80, -80, -140, 180}, {}});
ev.outgoing.push_back({gluon, { -60, -32, 0, 68}, {}});
ev.outgoing.push_back({higgs, { 140, 112, 177, 281}, {}});
ev.incoming[0] = {gluon, { 0, 0, -246, 246}, {}};
ev.incoming[1] = {gluon, { 0, 0, 283, 283}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, { -72, 24, 18, 78}, {}});
ev.outgoing.push_back({gluon, { 72, -24, 74, 106}, {}});
ev.incoming[0] = {gluon, { 0, 0, -46, 46}, {}};
ev.incoming[1] = {gluon, { 0, 0, 138, 138}, {}};
return ev;
}
}
if(njet == 3){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 152, -117, -88, 245}, {}});
ev.outgoing.push_back({gluon, {-146, 62, -11, 159}, {}});
ev.outgoing.push_back({gluon, { 126, -72, 96, 174}, {}});
ev.outgoing.push_back({gluon, {-132, 127, 144, 233}, {}});
ev.incoming[0] = {gluon, { 0, 0, -335, 335}, {}};
ev.incoming[1] = {gluon, { 0, 0, 476, 476}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, {-191, 188, -128, 297}, {}});
ev.outgoing.push_back({higgs, { 199, 72, -76, 257}, {}});
ev.outgoing.push_back({gluon, { 184, -172, -8, 252}, {}});
ev.outgoing.push_back({gluon, {-192, -88, 54, 218}, {}});
ev.incoming[0] = {gluon, { 0, 0, -591, 591}, {}};
ev.incoming[1] = {gluon, { 0, 0, 433, 433}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, { -42, 18, -49, 67}, {}});
ev.outgoing.push_back({gluon, { -12, -54, -28, 62}, {}});
ev.outgoing.push_back({higgs, { 99, 32, -16, 163}, {}});
ev.outgoing.push_back({gluon, { -45, 4, 72, 85}, {}});
ev.incoming[0] = {gluon, { 0, 0, -199, 199}, {}};
ev.incoming[1] = {gluon, { 0, 0, 178, 178}, {}};
return ev;
case 3:
ev.outgoing.push_back({gluon, { -65, -32, -76, 105}, {}});
ev.outgoing.push_back({gluon, { -22, 31, -34, 51}, {}});
ev.outgoing.push_back({gluon, { -12, -67, -36, 77}, {}});
ev.outgoing.push_back({higgs, { 99, 68, -4, 173}, {}});
ev.incoming[0] = {gluon, { 0, 0, -278, 278}, {}};
ev.incoming[1] = {gluon, { 0, 0, 128, 128}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, { -90, -135, 30, 165}, {}});
ev.outgoing.push_back({gluon, {-108, 198, 76, 238}, {}});
ev.outgoing.push_back({gluon, { 198, -63, 126, 243}, {}});
ev.incoming[0] = {gluon, { 0, 0, -207, 207}, {}};
ev.incoming[1] = {gluon, { 0, 0, 439, 439}, {}};
return ev;
}
}
if(njet == 4){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 199, 72, -76, 257}, {}});
ev.outgoing.push_back({gluon, {-200, -155, -64, 261}, {}});
ev.outgoing.push_back({gluon, { 198, 194, 57, 283}, {}});
ev.outgoing.push_back({gluon, { 1, 32, 8, 33}, {}});
ev.outgoing.push_back({gluon, {-198, -143, 186, 307}, {}});
ev.incoming[0] = {gluon, { 0, 0, -515, 515}, {}};
ev.incoming[1] = {gluon, { 0, 0, 626, 626}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, { 198, 61, -162, 263}, {}});
ev.outgoing.push_back({higgs, { 199, 72, -76, 257}, {}});
ev.outgoing.push_back({gluon, {-200, 135, 144, 281}, {}});
ev.outgoing.push_back({gluon, {-198, -186, 171, 321}, {}});
ev.outgoing.push_back({gluon, { 1, -82, 122, 147}, {}});
ev.incoming[0] = {gluon, { 0, 0, -535, 535}, {}};
ev.incoming[1] = {gluon, { 0, 0, 734, 734}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, {-180, -27, -164, 245}, {}});
ev.outgoing.push_back({gluon, {-108, 78, -36, 138}, {}});
ev.outgoing.push_back({higgs, { 196, -189, 68, 307}, {}});
ev.outgoing.push_back({gluon, {-107, 136, 76, 189}, {}});
ev.outgoing.push_back({gluon, { 199, 2, 178, 267}, {}});
ev.incoming[0] = {gluon, { 0, 0, -512, 512}, {}};
ev.incoming[1] = {gluon, { 0, 0, 634, 634}, {}};
return ev;
case 3:
ev.outgoing.push_back({gluon, { -12, -30, -84, 90}, {}});
ev.outgoing.push_back({gluon, { -72, 22, -96, 122}, {}});
ev.outgoing.push_back({gluon, { 68, 0, -51, 85}, {}});
ev.outgoing.push_back({higgs, { 64, 72, -81, 177}, {}});
ev.outgoing.push_back({gluon, { -48, -64, 84, 116}, {}});
ev.incoming[0] = {gluon, { 0, 0, -409, 409}, {}};
ev.incoming[1] = {gluon, { 0, 0, 181, 181}, {}};
return ev;
case 4:
ev.outgoing.push_back({gluon, { -72, -49, -72, 113}, {}});
ev.outgoing.push_back({gluon, { -48, 0, -36, 60}, {}});
ev.outgoing.push_back({gluon, { -12, 54, -36, 66}, {}});
ev.outgoing.push_back({gluon, { 68, -77, -56, 117}, {}});
ev.outgoing.push_back({higgs, { 64, 72, -81, 177}, {}});
ev.incoming[0] = {gluon, { 0, 0, -407, 407}, {}};
ev.incoming[1] = {gluon, { 0, 0, 126, 126}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, { 248, -56, -122, 282}, {}});
ev.outgoing.push_back({gluon, { 249, 30, -10, 251}, {}});
ev.outgoing.push_back({gluon, {-249, -18, 26, 251}, {}});
ev.outgoing.push_back({gluon, {-248, 44, 199, 321}, {}});
ev.incoming[0] = {gluon, { 0, 0, -506, 506}, {}};
ev.incoming[1] = {gluon, { 0, 0, 599, 599}, {}};
return ev;
}
}
if(njet == 6){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 349, 330, -94, 505}, {}});
ev.outgoing.push_back({gluon, {-315, -300, 0, 435}, {}});
ev.outgoing.push_back({gluon, { 347, 306, 18, 463}, {}});
ev.outgoing.push_back({gluon, {-249, -342, 162, 453}, {}});
ev.outgoing.push_back({gluon, { 345, 312, 284, 545}, {}});
ev.outgoing.push_back({gluon, {-324, -126, 292, 454}, {}});
ev.outgoing.push_back({gluon, {-153, -180, 304, 385}, {}});
ev.incoming[0] = {gluon, { 0, 0, -1137, 1137}, {}};
ev.incoming[1] = {gluon, { 0, 0, 2103, 2103}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, { 242, 241, -182, 387}, {}});
ev.outgoing.push_back({higgs, { 243, 238, -190, 409}, {}});
ev.outgoing.push_back({gluon, {-218, -215, -74, 315}, {}});
ev.outgoing.push_back({gluon, {-224, -224, 112, 336}, {}});
ev.outgoing.push_back({gluon, { 241, 182, 154, 339}, {}});
ev.outgoing.push_back({gluon, { -53, -234, 126, 271}, {}});
ev.outgoing.push_back({gluon, {-231, 12, 156, 279}, {}});
ev.incoming[0] = {gluon, { 0, 0, -1117, 1117}, {}};
ev.incoming[1] = {gluon, { 0, 0, 1219, 1219}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, { 151, 102, -42, 187}, {}});
ev.outgoing.push_back({gluon, { -86, -46, -17, 99}, {}});
ev.outgoing.push_back({higgs, { 152, 153, 0, 249}, {}});
ev.outgoing.push_back({gluon, { -60, -135, 64, 161}, {}});
ev.outgoing.push_back({gluon, { 150, 123, 110, 223}, {}});
ev.outgoing.push_back({gluon, {-154, -49, 98, 189}, {}});
ev.outgoing.push_back({gluon, {-153, -148, 144, 257}, {}});
ev.incoming[0] = {gluon, { 0, 0, -504, 504}, {}};
ev.incoming[1] = {gluon, { 0, 0, 861, 861}, {}};
return ev;
case 3:
ev.outgoing.push_back({gluon, { 198, 197, -66, 287}, {}});
ev.outgoing.push_back({gluon, {-198, -189, -54, 279}, {}});
ev.outgoing.push_back({gluon, {-200, -64, 2, 210}, {}});
ev.outgoing.push_back({higgs, { 199, 158, 6, 283}, {}});
ev.outgoing.push_back({gluon, {-199, -184, 172, 321}, {}});
ev.outgoing.push_back({gluon, { 196, 168, 177, 313}, {}});
ev.outgoing.push_back({gluon, { 4, -86, 92, 126}, {}});
ev.incoming[0] = {gluon, { 0, 0, -745, 745}, {}};
ev.incoming[1] = {gluon, { 0, 0, 1074, 1074}, {}};
return ev;
case 4:
ev.outgoing.push_back({gluon, { 151, 102, -42, 187}, {}});
ev.outgoing.push_back({gluon, { -86, -133, -14, 159}, {}});
ev.outgoing.push_back({gluon, {-154, -104, -8, 186}, {}});
ev.outgoing.push_back({gluon, { -60, 11, 0, 61}, {}});
ev.outgoing.push_back({higgs, { 152, 153, 0, 249}, {}});
ev.outgoing.push_back({gluon, { 150, 125, 90, 215}, {}});
ev.outgoing.push_back({gluon, {-153, -154, 126, 251}, {}});
ev.incoming[0] = {gluon, { 0, 0, -578, 578}, {}};
ev.incoming[1] = {gluon, { 0, 0, 730, 730}, {}};
return ev;
case 5:
ev.outgoing.push_back({gluon, { -15, -90, -94, 131}, {}});
ev.outgoing.push_back({gluon, { -11, 82, -74, 111}, {}});
ev.outgoing.push_back({gluon, { 23, -80, -64, 105}, {}});
ev.outgoing.push_back({gluon, { -48, -25, -36, 65}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -16, 101}, {}});
ev.outgoing.push_back({higgs, { 68, 92, -18, 170}, {}});
ev.outgoing.push_back({gluon, { -5, -78, 54, 95}, {}});
ev.incoming[0] = {gluon, { 0, 0, -513, 513}, {}};
ev.incoming[1] = {gluon, { 0, 0, 265, 265}, {}};
return ev;
case 6:
ev.outgoing.push_back({gluon, { 198, 197, -66, 287}, {}});
ev.outgoing.push_back({gluon, { 4, -84, -18, 86}, {}});
ev.outgoing.push_back({gluon, {-198, -60, -36, 210}, {}});
ev.outgoing.push_back({gluon, { 196, -78, -36, 214}, {}});
ev.outgoing.push_back({gluon, {-200, 45, 0, 205}, {}});
ev.outgoing.push_back({gluon, {-199, -178, 2, 267}, {}});
ev.outgoing.push_back({higgs, { 199, 158, 6, 283}, {}});
ev.incoming[0] = {gluon, { 0, 0, -850, 850}, {}};
ev.incoming[1] = {gluon, { 0, 0, 702, 702}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, {-350, -112, -280, 462}, {}});
ev.outgoing.push_back({gluon, { 347, 266, -322, 543}, {}});
ev.outgoing.push_back({gluon, {-349, -314, -38, 471}, {}});
ev.outgoing.push_back({gluon, { 349, 348, 12, 493}, {}});
ev.outgoing.push_back({gluon, {-342, -54, 23, 347}, {}});
ev.outgoing.push_back({gluon, { 345, -134, 138, 395}, {}});
ev.incoming[0] = {gluon, { 0, 0, -1589, 1589}, {}};
ev.incoming[1] = {gluon, { 0, 0, 1122, 1122}, {}};
return ev;
}
}
if(njet == 7){
switch(pos_boson){
case -1: // jet idx: -1 0 1 2 3 4 5
ev.outgoing.push_back({gluon, { -15, -18, -54, 59}, {}});
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { 23, -100, -64, 121}, {}});
ev.outgoing.push_back({gluon, { 68, 93, -20, 117}, {}});
ev.outgoing.push_back({gluon, { -5, -92, -12, 93}, {}});
ev.outgoing.push_back({gluon, { -48, -76, -2, 90}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.incoming[0] = {gluon, { 0, 0, -439, 439}, {}};
ev.incoming[1] = {gluon, { 0, 0, 273, 273}, {}};
return ev;
case -2: // jet idx: 0 1 2 3 4 -1 -1
ev.outgoing.push_back({gluon, { -5, -86, -82, 119}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -48, -14, 20, 54}, {}});
ev.outgoing.push_back({gluon, { 23, -50, 26, 61}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -15, -18, 54, 59}, {}});
ev.outgoing.push_back({gluon, { -11, -20, 88, 91}, {}});
ev.incoming[0] = {gluon, { 0, 0, -215, 215}, {}};
ev.incoming[1] = {gluon, { 0, 0, 397, 397}, {}};
return ev;
case -3: // jet idx: 0 0 1 2 2 3 4
// jet pt fraction: 0.6 0.38 1 0.49 0.51 1 1
ev.outgoing.push_back({gluon, { 23, -94, -62, 1.2e+02}, {}});
ev.outgoing.push_back({gluon, { -5, -62, -34, 71}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 1.2e+02}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 1.1e+02}, {}});
ev.outgoing.push_back({gluon, { -11, 98, 70, 1.2e+02}, {}});
ev.outgoing.push_back({gluon, { -48, -1e+02, 82, 1.4e+02}, {}});
ev.outgoing.push_back({gluon, { -15, -30, 78, 85}, {}});
ev.incoming[0] = {gluon, { 0, 0, -2.7e+02, 2.7e+02}, {}};
ev.incoming[1] = {gluon, { 0, 0, 4.8e+02, 4.8e+02}, {}};
return ev;
case -4: // jet idx: 0 1 1 2 3 4 4
// jet pt fraction: 1 0.51 0.49 1 1 0.25 0.75
ev.outgoing.push_back({gluon, { -5, -88, -64, 109}, {}});
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { 23, -70, 22, 77}, {}});
ev.outgoing.push_back({gluon, { -15, -32, 16, 39}, {}});
ev.outgoing.push_back({gluon, { -48, -96, 75, 131}, {}});
ev.incoming[0] = {gluon, { 0, 0, -381, 381}, {}};
ev.incoming[1] = {gluon, { 0, 0, 324, 324}, {}};
return ev;
case -5: // jet idx: 0 1 -1 -1 2 3 4
ev.outgoing.push_back({gluon, { -15, -26, -62, 69}, {}});
ev.outgoing.push_back({gluon, { -48, -60, -54, 94}, {}});
ev.outgoing.push_back({gluon, { 23, 10, -14, 29}, {}});
ev.outgoing.push_back({gluon, { -5, -20, 0, 21}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -11, -92, 40, 101}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.incoming[0] = {gluon, { 0, 0, -278, 278}, {}};
ev.incoming[1] = {gluon, { 0, 0, 264, 264}, {}};
return ev;
case -6: // jet idx: 0 1 1 2 -1 2 3
// jet pt fraction: 1 0.63 0.36 0.49 1 0.51 1
ev.outgoing.push_back({gluon, { 68, 93, -20, 117}, {}});
ev.outgoing.push_back({gluon, { -48, -100, 26, 114}, {}});
ev.outgoing.push_back({gluon, { -15, -62, 26, 69}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -28, 20, 35}, {}});
ev.outgoing.push_back({gluon, { -11, 98, 70, 121}, {}});
ev.outgoing.push_back({gluon, { 23, -96, 92, 135}, {}});
ev.incoming[0] = {gluon, { 0, 0, -216, 216}, {}};
ev.incoming[1] = {gluon, { 0, 0, 486, 486}, {}};
return ev;
case -7: // jet idx: 0 1 2 2 3 3 4
// jet pt fraction: 1 1 0.51 0.49 0.18 0.82 1
ev.outgoing.push_back({gluon, { -15, -80, -100, 129}, {}});
ev.outgoing.push_back({gluon, { 23, -96, -92, 135}, {}});
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -22, -10, 25}, {}});
ev.outgoing.push_back({gluon, { -48, -88, -31, 105}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.incoming[0] = {gluon, { 0, 0, -541, 541}, {}};
ev.incoming[1] = {gluon, { 0, 0, 202, 202}, {}};
return ev;
case -8: // jet idx: 0 1 2 2 2 3 4
// jet pt fraction: 1 1 0.21 0.37 0.41 1 1
ev.outgoing.push_back({gluon, { -48, -44, -62, 90}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -50, -22, 55}, {}});
ev.outgoing.push_back({gluon, { 23, -90, -34, 99}, {}});
ev.outgoing.push_back({gluon, { -15, -100, -28, 105}, {}});
ev.outgoing.push_back({gluon, { 68, 93, -20, 117}, {}});
ev.outgoing.push_back({gluon, { -11, 96, 76, 123}, {}});
ev.incoming[0] = {gluon, { 0, 0, -423, 423}, {}};
ev.incoming[1] = {gluon, { 0, 0, 277, 277}, {}};
return ev;
case -9: // jet idx: 0 1 2 1 3 0 4
// jet pt fraction: 0.72 0.51 1 0.49 1 0.28 1
ev.outgoing.push_back({gluon, { -15, -98, -62, 117}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { 23, -76, -40, 89}, {}});
ev.outgoing.push_back({gluon, { -11, 92, -40, 101}, {}});
ev.outgoing.push_back({gluon, { -48, -68, -34, 90}, {}});
ev.outgoing.push_back({gluon, { -5, -38, -14, 41}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.incoming[0] = {gluon, { 0, 0, -446, 446}, {}};
ev.incoming[1] = {gluon, { 0, 0, 220, 220}, {}};
return ev;
case -10: // jet idx: 0 1 3 2 4 3 1
// jet pt fraction: 1 0.33 0.51 1 1 0.49 0.67
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -5, -48, 16, 51}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { 23, -76, 52, 95}, {}});
ev.outgoing.push_back({gluon, { -48, -60, 54, 94}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 68, 115}, {}});
ev.outgoing.push_back({gluon, { -15, -96, 72, 121}, {}});
ev.incoming[0] = {gluon, { 0, 0, -183, 183}, {}};
ev.incoming[1] = {gluon, { 0, 0, 521, 521}, {}};
return ev;
case -11: // jet idx: 0 1 2 3 4 -1 5
// jet pt fraction: 1 1 1 1 1 1 1
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -15, -98, -62, 117}, {}});
ev.outgoing.push_back({gluon, { 23, -90, -2, 93}, {}});
ev.outgoing.push_back({gluon, { -48, -76, 2, 90}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -5, -22, 10, 25}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.incoming[0] = {gluon, { 0, 0, -360, 360}, {}};
ev.incoming[1] = {gluon, { 0, 0, 314, 314}, {}};
return ev;
case -12: // jet idx: 0 1 -1 2 3 4 3
// jet pt fraction: 1 1 1 1 0.35 1 0.65
ev.outgoing.push_back({gluon, { 23, -94, -62, 115}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -28, 4, 29}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -15, -58, 34, 69}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 68, 115}, {}});
ev.outgoing.push_back({gluon, { -48, -100, 82, 138}, {}});
ev.incoming[0] = {gluon, { 0, 0, -302, 302}, {}};
ev.incoming[1] = {gluon, { 0, 0, 392, 392}, {}};
return ev;
case -13: // jet idx: 0 1 2 3 3 4 2
// jet pt fraction: 1 1 0.5 0.35 0.65 1 0.5
ev.outgoing.push_back({gluon, { -15, -98, -62, 117}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -28, 20, 35}, {}});
ev.outgoing.push_back({gluon, { -48, -96, 75, 131}, {}});
ev.outgoing.push_back({gluon, { 23, -62, 50, 83}, {}});
ev.outgoing.push_back({gluon, { -11, 96, 76, 123}, {}});
ev.incoming[0] = {gluon, { 0, 0, -241, 241}, {}};
ev.incoming[1] = {gluon, { 0, 0, 476, 476}, {}};
return ev;
case -14: // jet idx: 0 1 2 3 3 4 2
// jet pt fraction: 1 1 0.52 0.35 0.65 1 0.48
ev.outgoing.push_back({gluon, { 23, -94, -62, 115}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -15, -96, 72, 121}, {}});
ev.outgoing.push_back({gluon, { -5, -42, 38, 57}, {}});
ev.outgoing.push_back({gluon, { -48, -44, 62, 90}, {}});
ev.outgoing.push_back({gluon, { -11, 88, 88, 125}, {}});
ev.incoming[0] = {gluon, { 0, 0, -231, 231}, {}};
ev.incoming[1] = {gluon, { 0, 0, 505, 505}, {}};
return ev;
case -15: // jet idx: 0 -1 1 0 2 3 4
// jet pt fraction: 0.51 1 1 0.49 1 1 1
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -5, -16, -12, 21}, {}});
ev.outgoing.push_back({gluon, { 23, -94, -62, 115}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -48, -76, 70, 114}, {}});
ev.outgoing.push_back({gluon, { -15, -100, 80, 129}, {}});
ev.incoming[0] = {gluon, { 0, 0, -379, 379}, {}};
ev.incoming[1] = {gluon, { 0, 0, 349, 349}, {}};
return ev;
}
}
throw HEJ::unknown_option{"unknown process"};
}
HEJ::Event::EventData parse_configuration(
std::array<std::string,2> const & in, std::vector<std::string> const & out,
int const overwrite_boson
){
auto boson = std::find_if(out.cbegin(), out.cend(),
[](std::string const & id){
return !HEJ::is_parton(HEJ::to_ParticleID(id)); });
int const pos_boson = (overwrite_boson!=0)?overwrite_boson:
((boson == out.cend())?-1:std::distance(out.cbegin(), boson));
std::size_t njets = out.size();
if( (overwrite_boson == 0) && boson != out.cend()) --njets;
HEJ::Event::EventData ev{get_process(njets, pos_boson)};
ASSERT((pos_boson<0) || (ev.outgoing[pos_boson].type == HEJ::ParticleID::higgs));
for(std::size_t i=0; i<out.size(); ++i){
ev.outgoing[i].type = HEJ::to_ParticleID(out[i]);
// decay W
if( std::abs(ev.outgoing[i].type) == HEJ::ParticleID::Wp )
ev.decays[i]=decay_W(ev.outgoing[i]);
// decay Z
if( ev.outgoing[i].type == HEJ::ParticleID::Z_photon_mix )
ev.decays[i]=decay_Z(ev.outgoing[i]);
}
for(std::size_t i=0; i<in.size(); ++i){
ev.incoming[i].type = HEJ::to_ParticleID(in[i]);
}
shuffle_particles(ev);
return ev;
}
namespace {
std::mt19937_64 RAN{0};
}
void shuffle_particles(HEJ::Event::EventData & ev) {
// incoming
std::shuffle(ev.incoming.begin(), ev.incoming.end(), RAN);
// outgoing (through index)
auto old_outgoing = std::move(ev).outgoing;
std::vector<std::size_t> idx(old_outgoing.size());
std::iota(idx.begin(), idx.end(), 0);
std::shuffle(idx.begin(), idx.end(), RAN);
ev.outgoing.clear();
ev.outgoing.reserve(old_outgoing.size());
for(std::size_t i: idx) {
ev.outgoing.emplace_back(std::move(old_outgoing[i]));
}
// find decays again
if(!ev.decays.empty()){
auto old_decays = std::move(ev).decays;
ev.decays.clear();
for(std::size_t i=0; i<idx.size(); ++i) {
auto decay = old_decays.find(idx[i]);
if(decay != old_decays.end())
ev.decays.emplace(i, std::move(decay->second));
}
for(auto & decay: ev.decays){
std::shuffle(decay.second.begin(), decay.second.end(), RAN);
}
}
}
std::vector<HEJ::Particle> decay_W( HEJ::Particle const & parent ){
if(parent.m() == 0.) // we can't decay massless partons
return {};
std::array<HEJ::ParticleID, 2> decays{};
if(parent.type==HEJ::ParticleID::Wp){
// order matters: first particle, second anti
decays[0] = HEJ::ParticleID::nu_e;
decays[1] = HEJ::ParticleID::e_bar;
} else {
// this function is for testing: we don't check that parent==W boson
decays[0] = HEJ::ParticleID::e;
decays[1] = HEJ::ParticleID::nu_e_bar;
}
std::vector<HEJ::Particle> decay_products(decays.size());
for(std::size_t i = 0; i < decays.size(); ++i){
decay_products[i].type = decays[i];
}
// choose polar and azimuth angle in parent rest frame
const double E = parent.m()/2;
const double theta = 2.*M_PI*RAN()/static_cast<double>(RAN.max());
const double cos_phi = 2.*RAN()/static_cast<double>(RAN.max())-1.;
const double sin_phi = std::sqrt(1. - cos_phi*cos_phi); // Know 0 < phi < pi
const double px = E*std::cos(theta)*sin_phi;
const double py = E*std::sin(theta)*sin_phi;
const double pz = E*cos_phi;
decay_products[0].p.reset(px, py, pz, E);
decay_products[1].p.reset(-px, -py, -pz, E);
for(auto & particle: decay_products) particle.p.boost(parent.p);
return decay_products;
}
std::vector<HEJ::Particle> decay_Z( HEJ::Particle const & parent ){
if(parent.m() == 0.) // we can't decay massless partons
return {};
std::array<HEJ::ParticleID, 2> decays{};
// order matters: first particle, second anti
decays[0] = HEJ::ParticleID::electron;
decays[1] = HEJ::ParticleID::positron;
std::vector<HEJ::Particle> decay_products(decays.size());
for(size_t i = 0; i < decays.size(); ++i){
decay_products[i].type = decays[i];
}
// choose polar and azimuth angle in parent rest frame
const double E = parent.m()/2;
const double theta = 2.*M_PI*RAN()/(1.*RAN.max());
const double cos_phi = 2.*RAN()/(1.*RAN.max())-1.;
const double sin_phi = sqrt(1. - cos_phi*cos_phi); // Know 0 < phi < pi
const double px = E*cos(theta)*sin_phi;
const double py = E*sin(theta)*sin_phi;
const double pz = E*cos_phi;
decay_products[0].p.reset(px, py, pz, E);
decay_products[1].p.reset(-px, -py, -pz, E);
for(auto & particle: decay_products) particle.p.boost(parent.p);
return decay_products;
}
diff --git a/t/test_classify.cc b/t/test_classify.cc
index 4194267..fbbbfb6 100644
--- a/t/test_classify.cc
+++ b/t/test_classify.cc
@@ -1,525 +1,542 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "hej_test.hh"
#include <array>
#include <cstdlib>
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include "fastjet/JetDefinition.hh"
#include "HEJ/Event.hh"
#include "HEJ/event_types.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/PDG_codes.hh"
namespace {
const fastjet::JetDefinition JET_DEF{fastjet::JetAlgorithm::antikt_algorithm, 0.4};
const double MIN_JET_PT{30.};
const std::vector<std::string> ALL_QUARKS{"-4","-1","1","2","3","4"};
const std::vector<std::string> ALL_PARTONS{"g","-2","-1","1","2","3","4"};
const std::vector<std::string> ALL_BOSONS{"h", "Wp", "Wm", "Z_photon_mix"};
const std::vector<std::string> ALL_G_Z{"photon", "Z"};
const std::vector<std::string> ALL_W{"W+", "W-"};
const std::size_t MAX_MULTI = 6;
std::mt19937_64 RAN{0};
bool couple_quark(std::string const & boson, std::string & quark){
if(std::abs(HEJ::to_ParticleID(boson)) == HEJ::ParticleID::Wp){
auto qflav{ HEJ::to_ParticleID(quark) };
if(!HEJ::is_anyquark(qflav)) return false;
const int W_charge = HEJ::to_ParticleID(boson)>0?1:-1;
if(W_charge*qflav < 0 && !(std::abs(qflav)%2)) return false; // not anti-down
if(W_charge*qflav > 0 && (std::abs(qflav)%2)) return false; // not up
quark=std::to_string(qflav-W_charge);
}
if(HEJ::to_ParticleID(boson) == HEJ::ParticleID::Z_photon_mix){
auto qflav{ HEJ::to_ParticleID(quark) };
if(!HEJ::is_anyquark(qflav)) return false;
}
return true;
}
bool match_expectation( HEJ::event_type::EventType expected,
std::array<std::string,2> const & in, std::vector<std::string> const & out,
int const overwrite_boson = 0
){
HEJ::Event ev{ parse_configuration(
in,out,overwrite_boson ).cluster(JET_DEF, MIN_JET_PT)};
if(ev.type() != expected){
std::cerr << "Expected type " << name(expected)
<< " but found " << name(ev.type()) << "\n" << ev;
auto jet_idx{ ev.particle_jet_indices() };
std::cout << "Particle Jet indices: ";
for(int const i: jet_idx)
std::cout << i << " ";
std::cout << std::endl;
return false;
}
return true;
}
//! test FKL configurations
//! if implemented==false : check processes that are not in HEJ yet
bool check_fkl( bool const implemented=true ){
using namespace HEJ;
auto const type{ implemented?event_type::FKL:event_type::non_resummable };
std::vector<std::string> bosons;
if(implemented)
bosons = ALL_BOSONS;
else {
bosons = ALL_G_Z;
}
for(std::string const & first: ALL_PARTONS) // all quark flavours
for(std::string const & last: ALL_PARTONS){
- for(std::size_t njet=2; njet<=MAX_MULTI; ++njet){ // all multiplicities
+ for(std::size_t njet=1; njet<=MAX_MULTI; ++njet){ // all multiplicities
if(njet==5) continue;
std::array<std::string,2> base_in{first,last};
std::vector<std::string> base_out(njet, "g");
- base_out.front() = first;
- base_out.back() = last;
- if(implemented && !match_expectation(type, base_in, base_out))
- return false;
- for(auto const & boson: bosons) // any boson
+ if(njet>1){ // pure jets only for >=2j
+ base_out.front() = first;
+ base_out.back() = last;
+ if(implemented && !match_expectation(type, base_in, base_out))
+ return false;
+ }
+ for(auto const & boson: bosons){ // any boson
for(std::size_t pos=0; pos<=njet; ++pos){ // at any position
+ if(njet == 1){
+ // special case: one jet only for g->h
+ if(boson != "h" || ((pos==0?first:last) != "g")){
+ continue;
+ } else {
+ base_out.front() = pos==0?last:first;
+ }
+ }
auto const & in{base_in};
auto out{base_out};
// change quark flavours for W
const bool couple_idx
= std::uniform_int_distribution<int>{0,1}(RAN) != 0;
if(!couple_quark(boson, couple_idx?out.back():out.front()))
continue;
out.insert(out.begin()+pos, boson);
if(!match_expectation(type, in, out))
return false;
}
+ }
}
}
return true;
}
//! test unordered configurations
//! if implemented==false : check processes that are not in HEJ yet
bool check_uno( bool const implemented=true ){
using namespace HEJ;
auto const b{ implemented?event_type::unob:event_type::non_resummable };
auto const f{ implemented?event_type::unof:event_type::non_resummable };
std::vector<std::string> bosons;
if(implemented) {
bosons = ALL_BOSONS;
} else {
bosons = ALL_G_Z;
}
for(std::string const & uno: ALL_QUARKS) // all quark flavours
for(std::string const & fkl: ALL_PARTONS){
for(std::size_t njet=3; njet<=MAX_MULTI; ++njet){ // all multiplicities >2
if(njet==5) continue;
for(std::size_t i=0; i<2; ++i){ // forward & backwards
std::array<std::string,2> base_in;
std::vector<std::string> base_out(njet, "g");
const std::size_t uno_pos = i?1:(njet-2);
const std::size_t fkl_pos = i?(njet-1):0;
base_in[i?0:1] = uno;
base_in[i?1:0] = fkl;
base_out[uno_pos] = uno;
base_out[fkl_pos] = fkl;
auto expectation{ i?b:f };
if( implemented
&& !match_expectation(expectation, base_in, base_out) )
return false;
for(auto const & boson: bosons){ // any boson
// at any position (higgs only inside FKL chain)
std::size_t start = 0;
std::size_t end = njet;
if(to_ParticleID(boson) == pid::higgs){
start = i?(uno_pos+1):fkl_pos;
end = i?(fkl_pos+1):uno_pos;
}
for(std::size_t pos=start; pos<=end; ++pos){
auto const & in{base_in};
auto out{base_out};
// change quark flavours for W
const bool couple_idx
= std::uniform_int_distribution<int>{0,1}(RAN) != 0;
if(!couple_quark(boson, couple_idx?out[fkl_pos]:out[uno_pos]))
continue;
out.insert(out.begin()+pos, boson);
if(!match_expectation(expectation, in, out))
return false;
}
}
}
}
}
return true;
}
//! test extremal qqbar configurations
//! if implemented==false : check processes that are not in HEJ yet
bool check_extremal_qqbar( bool const implemented=true ){
using namespace HEJ;
auto const b{ implemented?event_type::qqbar_exb:event_type::non_resummable };
auto const f{ implemented?event_type::qqbar_exf:event_type::non_resummable };
std::vector<std::string> bosons;
if(implemented)
bosons = ALL_W;
else {
bosons = ALL_G_Z;
bosons.emplace_back("h");
bosons.emplace_back("Z_photon_mix");
}
for(std::string const & qqbar: ALL_QUARKS) // all quark flavours
for(std::string const & fkl: ALL_PARTONS){
std::string const qqbar2{ std::to_string(HEJ::to_ParticleID(qqbar)*-1) };
for(std::size_t njet=3; njet<=MAX_MULTI; ++njet){ // all multiplicities >2
if(njet==5) continue;
for(std::size_t i=0; i<2; ++i){ // forward & backwards
std::array<std::string,2> base_in;
std::vector<std::string> base_out(njet, "g");
const std::size_t qqbar_pos = i?0:(njet-2);
const std::size_t fkl_pos = i?(njet-1):0;
base_in[i?0:1] = "g";
base_in[i?1:0] = fkl;
base_out[fkl_pos] = fkl;
base_out[qqbar_pos] = qqbar;
base_out[qqbar_pos+1] = qqbar2;
auto expectation{ i?b:f };
if( implemented
&& !match_expectation(expectation, base_in, base_out) )
return false;
for(auto const & boson: bosons){ // all bosons
// at any position (higgs only inside FKL chain)
std::size_t start = 0;
std::size_t end = njet;
if(to_ParticleID(boson) == pid::higgs){
start = i?(qqbar_pos+2):fkl_pos;
end = i?(fkl_pos+1):qqbar_pos;
}
for(std::size_t pos=start; pos<=end; ++pos){
auto const & in{base_in};
auto out{base_out};
// change quark flavours for W
const bool couple_idx
= std::uniform_int_distribution<int>{0,1}(RAN) != 0;
if(couple_idx || !couple_quark(boson, out[fkl_pos]) ){
// (randomly) try couple to FKL, else fall-back to qqbar
if(!couple_quark(boson, out[qqbar_pos]))
couple_quark(boson, out[qqbar_pos+1]);
}
out.insert(out.begin()+pos, boson);
if(!match_expectation(expectation, in, out))
return false;
}
}
}
}
// test allowed jet configurations
if( implemented){
if( !( match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -3)
&& match_expectation(b,{"g",fkl},{qqbar,qqbar2,"g","g","g","g",fkl}, -4)
&& match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -5)
&& match_expectation(b,{"g",fkl},{qqbar,qqbar2,"g","g","g","g",fkl}, -5)
&& match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -6)
&& match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -7)
&& match_expectation(b,{"g",fkl},{qqbar,qqbar2,"g","g","g","g",fkl}, -7)
&& match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -8)
&& match_expectation(b,{"g",fkl},{qqbar,qqbar2,"g","g","g","g",fkl}, -8)
&& match_expectation(b,{"g",fkl},{qqbar,qqbar2,"g","g","g","g",fkl}, -9)
&& match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -10)
&& match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -11)
&& match_expectation(b,{"g",fkl},{qqbar,qqbar2,"g","g","g","g",fkl}, -11)
&& match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqbar,qqbar2}, -12)
&& match_expectation(b,{"g",fkl},{qqbar,qqbar2,"g","g","g","g",fkl}, -12)
))
return false;
if (fkl == "2") {
if( !( match_expectation(f,{"2","g"},{"1","Wp","g","g","g",qqbar,qqbar2}, -3)
&& match_expectation(b,{"g","2"},{qqbar,qqbar2,"g","Wp","g","g","1"}, -4)
&& match_expectation(f,{"2","g"},{"1","Wp","g","g","g",qqbar,qqbar2}, -5)
&& match_expectation(b,{"g","2"},{qqbar,qqbar2,"g","Wp","g","g","1"}, -5)
&& match_expectation(f,{"2","g"},{"1","g","Wp","g","g",qqbar,qqbar2}, -6)
&& match_expectation(f,{"2","g"},{"1","g","g","g","Wp",qqbar,qqbar2}, -7)
&& match_expectation(b,{"g","2"},{qqbar,qqbar2,"g","g","g","Wp","1"}, -7)
&& match_expectation(f,{"2","g"},{"1","Wp","g","g","g",qqbar,qqbar2}, -8)
&& match_expectation(b,{"g","2"},{qqbar,qqbar2,"Wp","g","g","g","1"}, -8)
&& match_expectation(b,{"g","2"},{qqbar,qqbar2,"g","Wp","g","g","1"}, -9)
&& match_expectation(f,{"2","g"},{"1","g","g","g","Wp",qqbar,qqbar2}, -10)
&& match_expectation(f,{"2","g"},{"1","g","g","g","Wp",qqbar,qqbar2}, -11)
&& match_expectation(b,{"g","2"},{qqbar,qqbar2,"g","g","g","Wp","1"}, -11)
&& match_expectation(f,{"2","g"},{"1","g","g","g","Wp",qqbar,qqbar2}, -12)
&& match_expectation(b,{"g","2"},{qqbar,qqbar2,"g","Wp","g","g","1"}, -12)
))
return false;
}
}
}
return true;
}
//! test central qqbar configurations
//! if implemented==false : check processes that are not in HEJ yet
bool check_central_qqbar(bool const implemented=true){
using namespace HEJ;
auto const t{ implemented?event_type::qqbar_mid:event_type::non_resummable };
std::vector<std::string> bosons;
if(implemented)
bosons = ALL_W;
else {
bosons = ALL_G_Z;
bosons.emplace_back("h");
bosons.emplace_back("Z_photon_mix");
}
for(std::string const & qqbar: ALL_QUARKS) // all quark flavours
for(std::string const & fkl1: ALL_PARTONS)
for(std::string const & fkl2: ALL_PARTONS){
std::string const qqbar2{ std::to_string(HEJ::to_ParticleID(qqbar)*-1) };
for(std::size_t njet=4; njet<=MAX_MULTI; ++njet){ // all multiplicities >3
if(njet==5) continue;
for(std::size_t qqbar_pos=1; qqbar_pos<njet-2; ++qqbar_pos){ // any qqbar position
std::array<std::string,2> base_in;
std::vector<std::string> base_out(njet, "g");
base_in[0] = fkl1;
base_in[1] = fkl2;
base_out.front() = fkl1;
base_out.back() = fkl2;
base_out[qqbar_pos] = qqbar;
base_out[qqbar_pos+1] = qqbar2;
if( implemented && !match_expectation(t, base_in, base_out) )
return false;
for(auto const & boson: bosons) // any boson
for(std::size_t pos=0; pos<=njet; ++pos){ // at any position
if( to_ParticleID(boson) == pid::higgs
&& (pos==qqbar_pos || pos==qqbar_pos+1) )
continue;
auto const & in{base_in};
auto out{base_out};
// change quark flavours for W
const int couple_idx{ std::uniform_int_distribution<int>{0,2}(RAN) };
// (randomly) try couple to FKL, else fall-back to qqbar
if( couple_idx == 0 && couple_quark(boson, out.front()) ){}
else if( couple_idx == 1 && couple_quark(boson, out.back()) ){}
else {
if(!couple_quark(boson, out[qqbar_pos]))
couple_quark(boson, out[qqbar_pos+1]);
}
out.insert(out.begin()+pos, boson);
if(!match_expectation(t, in, out))
return false;
}
}
}
}
return true;
}
// this checks a (non excessive) list of non-resummable states
bool check_non_resummable(){
auto type{ HEJ::event_type::non_resummable};
return
+ // 1j - crossing lines
+ match_expectation(type, {"g","2"}, {"2","h"})
+ && match_expectation(type, {"-1","g"}, {"h","-1"})
// 2j - crossing lines
- match_expectation(type, {"g","2"}, {"2","g"})
+ && match_expectation(type, {"g","2"}, {"2","g"})
&& match_expectation(type, {"-1","g"}, {"g","-1"})
&& match_expectation(type, {"1","-1"}, {"-1","1"})
&& match_expectation(type, {"g","2"}, {"2","g","h"})
&& match_expectation(type, {"1","2"}, {"2","h","1"})
&& match_expectation(type, {"1","-1"}, {"h","-1","1"})
&& match_expectation(type, {"g","2"}, {"Wp","1","g"})
&& match_expectation(type, {"1","-1"}, {"-2","Wp","1"})
&& match_expectation(type, {"4","g"}, {"g","3","Wp"})
&& match_expectation(type, {"1","-2"}, {"-1","Wm","1"})
&& match_expectation(type, {"g","3"}, {"4","g","Wm"})
&& match_expectation(type, {"1","3"}, {"Wm","4","1"})
&& match_expectation(type, {"g","2"}, {"Z_photon_mix","2","g"})
&& match_expectation(type, {"1","-1"}, {"-1","Z_photon_mix","1"})
&& match_expectation(type, {"4","g"}, {"g","4","Z_photon_mix"})
// 2j - qqbar
&& match_expectation(type, {"g","g"}, {"1","-1"})
&& match_expectation(type, {"g","g"}, {"-2","2","h"})
&& match_expectation(type, {"g","g"}, {"-4","Wp","3"})
&& match_expectation(type, {"g","g"}, {"Wm","-1","2"})
&& match_expectation(type, {"g","g"}, {"-3","Z_photon_mix","3"})
// 3j - crossing lines
&& match_expectation(type, {"g","4"}, {"4","g","g"})
&& match_expectation(type, {"-1","g"}, {"g","g","-1"})
&& match_expectation(type, {"1","3"}, {"3","g","1"})
&& match_expectation(type, {"-2","2"}, {"2","g","-2","h"})
&& match_expectation(type, {"-3","g"}, {"g","g","Wp","-4"})
&& match_expectation(type, {"1","-2"}, {"Wm","-1","g","1"})
&& match_expectation(type, {"-1","g"}, {"1","-1","-1"})
&& match_expectation(type, {"1","-4"}, {"Z_photon_mix","-4","g","1"})
// higgs inside uno
&& match_expectation(type, {"-1","g"}, {"g","h","-1","g"})
&& match_expectation(type, {"-1","1"}, {"g","h","-1","1"})
&& match_expectation(type, {"g","2"}, {"g","2","h","g"})
&& match_expectation(type, {"-1","1"}, {"-1","1","h","g"})
// higgs outside uno
&& match_expectation(type, {"-1","g"}, {"h","g","-1","g"})
&& match_expectation(type, {"-1","1"}, {"-1","1","g","h"})
// higgs inside qqbar
&& match_expectation(type, {"g","g"}, {"-1","h","1","g","g"})
&& match_expectation(type, {"g","g"}, {"g","-1","h","1","g"})
&& match_expectation(type, {"g","g"}, {"g","g","2","h","-2"})
// higgs outside qqbar
&& match_expectation(type, {"g","g"}, {"h","-1","1","g","g"})
&& match_expectation(type, {"g","g"}, {"g","g","2","-2","h"})
// 4j - two uno
&& match_expectation(type, {"-2","2"}, {"g","-2","2","g"})
&& match_expectation(type, {"1","3"}, {"g","1","h","3","g"})
&& match_expectation(type, {"1","2"}, {"g","1","3","Wp","g"})
&& match_expectation(type, {"1","-2"}, {"g","Wm","1","-1","g"})
&& match_expectation(type, {"3","2"}, {"g","3","Z_photon_mix","2","g"})
// 4j - two gluon outside
&& match_expectation(type, {"g","4"}, {"g","4","g","g"})
&& match_expectation(type, {"1","3"}, {"1","3","h","g","g"})
&& match_expectation(type, {"1","2"}, {"1","3","g","Wp","g"})
&& match_expectation(type, {"1","-2"}, {"1","Wm","-1","g","g"})
&& match_expectation(type, {"-1","g"}, {"g","g","-1","g"})
&& match_expectation(type, {"1","3"}, {"g","g","1","3","h"})
&& match_expectation(type, {"1","2"}, {"g","g","1","Wp","3"})
&& match_expectation(type, {"1","-2"}, {"Wm","g","g","1","-1"})
&& match_expectation(type, {"-1","2"}, {"g","g","-1","Z_photon_mix","2"})
// 4j - ggx+uno
&& match_expectation(type, {"g","4"}, {"1","-1","4","g"})
&& match_expectation(type, {"2","g"}, {"g","2","-3","3"})
&& match_expectation(type, {"g","4"}, {"1","-1","h","4","g"})
&& match_expectation(type, {"2","g"}, {"g","2","-3","3","h"})
&& match_expectation(type, {"g","4"}, {"Wp","1","-1","3","g"})
&& match_expectation(type, {"2","g"}, {"g","2","-4","Wp","3"})
&& match_expectation(type, {"g","4"}, {"2","Wm","-1","4","g"})
&& match_expectation(type, {"2","g"}, {"g","2","Wp","-3","4"})
&& match_expectation(type, {"-4","g"}, {"g","-4","-3","3","Z_photon_mix"})
// 3j - crossing+uno
&& match_expectation(type, {"1","4"}, {"g","4","1"})
&& match_expectation(type, {"1","4"}, {"4","1","g"})
&& match_expectation(type, {"1","4"}, {"g","h","4","1"})
&& match_expectation(type, {"-1","-3"},{"Wm","g","-4","-1"})
&& match_expectation(type, {"1","4"}, {"3","1","Wp","g"})
&& match_expectation(type, {"1","4"}, {"3","1","g","h"})
&& match_expectation(type, {"2","3"}, {"3","2","Z_photon_mix","g"})
// 3j - crossing+qqbar
&& match_expectation(type, {"1","g"}, {"-1","1","g","1"})
&& match_expectation(type, {"1","g"}, {"-1","1","1","g"})
&& match_expectation(type, {"g","1"}, {"1","g","1","-1"})
&& match_expectation(type, {"g","1"}, {"g","1","1","-1"})
&& match_expectation(type, {"1","g"}, {"2","-2","g","1"})
&& match_expectation(type, {"1","g"}, {"2","-2","1","g"})
&& match_expectation(type, {"g","1"}, {"1","g","-2","2"})
&& match_expectation(type, {"g","1"}, {"g","1","-2","2"})
&& match_expectation(type, {"1","g"}, {"-1","1","h","g","1"})
&& match_expectation(type, {"1","g"}, {"-1","h","1","1","g"})
&& match_expectation(type, {"g","1"}, {"1","g","1","h","-1"})
&& match_expectation(type, {"g","1"}, {"h","g","1","1","-1"})
&& match_expectation(type, {"1","g"}, {"2","-2","1","g","h"})
&& match_expectation(type, {"g","1"}, {"g","h","1","-2","2"})
&& match_expectation(type, {"1","g"}, {"Wp","3","-4","g","1"})
&& match_expectation(type, {"3","g"}, {"-2","Wm","1","3","g"})
&& match_expectation(type, {"g","1"}, {"1","g","Wm","-3","4"})
&& match_expectation(type, {"g","-3"}, {"g","-3","-1","Wp","2"})
&& match_expectation(type, {"g","2"}, {"2","g","Z_photon_mix","4","-4"})
// 4j- gluon in qqbar
&& match_expectation(type, {"g","1"}, {"1","g","-1","1"})
&& match_expectation(type, {"1","g"}, {"1","-1","g","1"})
&& match_expectation(type, {"g","1"}, {"1","g","Wm","-2","1"})
&& match_expectation(type, {"2","g"}, {"2","-2","g","Wp","1"})
&& match_expectation(type, {"g","g"}, {"Wp","3","g","-4","g"})
&& match_expectation(type, {"1","g"}, {"1","h","-1","g","1"})
&& match_expectation(type, {"3","g"}, {"3","1","g","Z_photon_mix","-1"})
// 6j - two qqbar
&& match_expectation(type, {"g","g"}, {"1","-1","g","g","1","-1"})
&& match_expectation(type, {"g","g"}, {"1","-1","g","1","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","-1","g","1","-1"})
&& match_expectation(type, {"g","g"}, {"g","1","-1","1","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","1","-1","-1","g"})
&& match_expectation(type, {"g","g"}, {"h","1","-1","g","g","1","-1"})
&& match_expectation(type, {"g","g"}, {"1","Wp","-2","g","1","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","Wp","-1","g","1","-2"})
&& match_expectation(type, {"g","g"}, {"g","1","-1","Wm","2","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","2","-1","Wm","-1","g"})
&& match_expectation(type, {"g","g"}, {"2","-2","g","-1","1","Z_photon_mix","g"})
// random stuff (can be non-physical)
&& match_expectation(type, {"g","g"}, {"1","-2","2","-1"}) // != 2 qqbar
&& match_expectation(type, {"g","g"}, {"1","-2","2","g"}) // could be qqbar
&& match_expectation(type, {"e+","e-"},{"1","-1"}) // bad initial state
&& match_expectation(type, {"1","e-"}, {"g","1","Wm"}) // bad initial state
&& match_expectation(type, {"h","g"}, {"g","g"}) // bad initial state
&& match_expectation(type, {"-1","g"}, {"-1","1","1"}) // bad qqbar
&& match_expectation(type, {"-1","g"}, {"1","1","-1"}) // crossing in bad qqbar
&& match_expectation(type, {"-1","g"}, {"-2","1","1","Wp"}) // bad qqbar
&& match_expectation(type, {"1","2"}, {"1","-1","g","g","g","2"}) // bad qqbar
&& match_expectation(type, {"1","2"}, {"1","-1","-2","g","g","2"}) // gluon in bad qqbar
&& match_expectation(type, {"g","g"}, {"-1","2","g","g"}) // wrong back qqbar
&& match_expectation(type, {"g","g"}, {"g","g","2","1"}) // wrong forward qqbar
&& match_expectation(type, {"g","g"}, {"g","-2","1","g"}) // wrong central qqbar
&& match_expectation(type, {"1","g"}, {"1","-2","g","g","Wp"}) // extra quark
&& match_expectation(type, {"g","1"}, {"g","g","-2","1","Wp"}) // extra quark
&& match_expectation(type, {"g","1"}, {"g","g","Wp","-2","1"}) // extra quark
&& match_expectation(type, {"g","1"}, {"g","-2","1","g","Wp"}) // extra quark
&& match_expectation(type, {"g","g"}, {"g","g","g","-2","1","-1","Wp"}) // extra quark
&& match_expectation(type, {"1","g"}, {"g","Wp","1","-2","g"}) // extra quark
&& match_expectation(type, {"g","g"}, {"1","-1","-2","g","g","g","Wp"}) // extra quark
;
}
// Two boson states, that are currently not implemented
bool check_bad_FS(){
auto type{ HEJ::event_type::bad_final_state};
return
match_expectation(type, {"g","g"}, {"g","h","h","g"})
&& match_expectation(type, {"g","g"}, {"h","g","h","g"})
&& match_expectation(type, {"g","-1"}, {"g","h","Wp","-2"})
&& match_expectation(type, {"-3","-1"},{"-4","g","Wp","Wp","-2"})
&& match_expectation(type, {"-4","-1"},{"-3","Wp","g","Wm","-2"})
&& match_expectation(type, {"-4","-1"},{"g","-3","Wp","Wm","-2"})
&& match_expectation(type, {"-4","-1"},{"-4","g","11","-11","-2"})
&& match_expectation(type, {"-4","-1"},{"-4","g","-13","g","-2"})
&& match_expectation(type, {"3","-2"}, {"Wp","3","Wm","g","g","g","-2"}, -13)
&& match_expectation(type, {"1","2"},{"1","g","Z_photon_mix","Z_photon_mix","2"})
&& match_expectation(type, {"-4","g"},{"-4","Z_photon_mix","g","Z_photon_mix","g"})
&& match_expectation(type, {"g","-2"}, {"g","Z_photon_mix","Wm","-1"})
&& match_expectation(type, {"3","1"},{"3","g","h","Z_photon_mix","1"})
;
}
- // not 2 jets
- bool check_not_2_jets(){
- auto type{ HEJ::event_type::no_2_jets};
+ // not enough jets
+ bool check_not_enough_jets(){
+ auto type{ HEJ::event_type::not_enough_jets};
return
match_expectation(type, {"g","g"}, {})
&& match_expectation(type, {"1","-1"}, {})
&& match_expectation(type, {"g","-1"}, {"-1"})
&& match_expectation(type, {"g","g"}, {"g"})
+ && match_expectation(type, {"g","g"}, {"h"})
+ && match_expectation(type, {"g","2"}, {"Wp","1"})
+ && match_expectation(type, {"g","2"}, {"Z","2"})
;
}
// not implemented processes
bool check_not_implemented(){
return check_fkl(false)
&& check_uno(false)
&& check_extremal_qqbar(false)
&& check_central_qqbar(false);
}
} // namespace
int main() {
// tests for "no false negatives"
// i.e. all HEJ-configurations get classified correctly
if(!check_fkl()) return EXIT_FAILURE;
if(!check_uno()) return EXIT_FAILURE;
if(!check_extremal_qqbar()) return EXIT_FAILURE;
if(!check_central_qqbar()) return EXIT_FAILURE;
// test for "no false positive"
// i.e. non-resummable gives non-resummable
if(!check_non_resummable()) return EXIT_FAILURE;
if(!check_bad_FS()) return EXIT_FAILURE;
- if(!check_not_2_jets()) return EXIT_FAILURE;
+ if(!check_not_enough_jets()) return EXIT_FAILURE;
if(!check_not_implemented()) return EXIT_FAILURE;
return EXIT_SUCCESS;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 3, 5:37 AM (4 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4962575
Default Alt Text
(701 KB)

Event Timeline