1717#include < fastjet/PseudoJet.hh>
1818#include < fastjet/contrib/EnergyCorrelator.hh>
1919#include < fastjet/contrib/LundGenerator.hh>
20+ #include < fastjet/contrib/Njettiness.hh>
2021#include < fastjet/contrib/SoftDrop.hh>
2122
2223#include < pybind11/numpy.h>
@@ -28,6 +29,58 @@ namespace fj = fastjet;
2829namespace py = pybind11;
2930using namespace pybind11 ::literals;
3031
32+ // adapted from
33+ // https://github.com/cms-svj/SVJProduction/blob/Run3/interface/NjettinessHelper.h
34+ namespace njettiness {
35+ enum MeasureDefinition_t {
36+ NormalizedMeasure = 0 , // (beta,R0)
37+ UnnormalizedMeasure, // (beta)
38+ OriginalGeometricMeasure, // (beta)
39+ NormalizedCutoffMeasure, // (beta,R0,Rcutoff)
40+ UnnormalizedCutoffMeasure, // (beta,Rcutoff)
41+ GeometricCutoffMeasure, // (beta,Rcutoff)
42+ N_MEASURE_DEFINITIONS
43+ };
44+ enum AxesDefinition_t {
45+ KT_Axes = 0 ,
46+ CA_Axes,
47+ AntiKT_Axes, // (axAxesR0)
48+ WTA_KT_Axes,
49+ WTA_CA_Axes,
50+ Manual_Axes,
51+ OnePass_KT_Axes,
52+ OnePass_CA_Axes,
53+ OnePass_AntiKT_Axes, // (axAxesR0)
54+ OnePass_WTA_KT_Axes,
55+ OnePass_WTA_CA_Axes,
56+ OnePass_Manual_Axes,
57+ MultiPass_Axes,
58+ N_AXES_DEFINITIONS
59+ };
60+ const std::unordered_map<std::string, MeasureDefinition_t>
61+ measure_def_names_to_enum = {
62+ {" NormalizedMeasure" , NormalizedMeasure},
63+ {" UnnormalizedMeasure" , UnnormalizedMeasure},
64+ {" OriginalGeometricMeasure" , OriginalGeometricMeasure},
65+ {" NormalizedCutoffMeasure" , NormalizedCutoffMeasure},
66+ {" UnnormalizedCutoffMeasure" , UnnormalizedCutoffMeasure},
67+ {" GeometricCutoffMeasure" , GeometricCutoffMeasure}};
68+ const std::unordered_map<std::string, AxesDefinition_t> axis_def_names_to_enum =
69+ {{" KT_Axes" , KT_Axes},
70+ {" CA_Axes" , CA_Axes},
71+ {" AntiKT_Axes" , AntiKT_Axes},
72+ {" WTA_KT_Axes" , WTA_KT_Axes},
73+ {" WTA_CA_Axes" , WTA_CA_Axes},
74+ {" Manual_Axes" , Manual_Axes},
75+ {" OnePass_KT_Axes" , OnePass_KT_Axes},
76+ {" OnePass_CA_Axes" , OnePass_CA_Axes},
77+ {" OnePass_AntiKT_Axes" , OnePass_AntiKT_Axes},
78+ {" OnePass_WTA_KT_Axes" , OnePass_WTA_KT_Axes},
79+ {" OnePass_WTA_CA_Axes" , OnePass_WTA_CA_Axes},
80+ {" OnePass_Manual_Axes" , OnePass_Manual_Axes},
81+ {" MultiPass_Axes" , MultiPass_Axes}};
82+ } // namespace njettiness
83+
3184typedef struct {
3285 PyObject_HEAD void *ptr;
3386 void *ty;
@@ -2315,6 +2368,93 @@ PYBIND11_MODULE(_ext, m) {
23152368 None.
23162369 Returns:
23172370 pt, eta, phi, m of inclusive jets.
2371+ )pbdoc" )
2372+ .def (" to_numpy_njettiness" ,
2373+ [](
2374+ const output_wrapper ow,
2375+ const std::string& measure_definition,
2376+ const std::string& axes_definition,
2377+ const std::vector<unsigned int >& njets,
2378+ const double beta,
2379+ const double R0,
2380+ const double Rcutoff,
2381+ const int nPass,
2382+ const double akAxesR0
2383+ ) {
2384+ auto maybe_measdef = njettiness::measure_def_names_to_enum.find (measure_definition);
2385+ const auto measdefenum = maybe_measdef == njettiness::measure_def_names_to_enum.end () ? njettiness::NormalizedMeasure : maybe_measdef->second ;
2386+
2387+ auto maybe_axesdef = njettiness::axis_def_names_to_enum.find (axes_definition);
2388+ const auto axesdefenum = maybe_axesdef == njettiness::axis_def_names_to_enum.end () ? njettiness::KT_Axes : maybe_axesdef->second ;
2389+
2390+ // Get the measure definition
2391+ fastjet::contrib::NormalizedMeasure normalizedMeasure (beta, R0);
2392+ fastjet::contrib::UnnormalizedMeasure unnormalizedMeasure (beta);
2393+ fastjet::contrib::OriginalGeometricMeasure geometricMeasure (beta);
2394+ fastjet::contrib::NormalizedCutoffMeasure normalizedCutoffMeasure (beta, R0, Rcutoff);
2395+ fastjet::contrib::UnnormalizedCutoffMeasure unnormalizedCutoffMeasure (beta, Rcutoff);
2396+
2397+ fastjet::contrib::MeasureDefinition const * measureDef = 0 ;
2398+ switch ( measdefenum ) {
2399+ case njettiness::UnnormalizedMeasure : measureDef = &unnormalizedMeasure; break ;
2400+ case njettiness::OriginalGeometricMeasure : measureDef = &geometricMeasure; break ;
2401+ case njettiness::NormalizedCutoffMeasure : measureDef = &normalizedCutoffMeasure; break ;
2402+ case njettiness::UnnormalizedCutoffMeasure : measureDef = &unnormalizedCutoffMeasure; break ;
2403+ case njettiness::NormalizedMeasure : default : measureDef = &normalizedMeasure; break ;
2404+ }
2405+
2406+ // Get the axes definition
2407+ fastjet::contrib::KT_Axes kt_axes;
2408+ fastjet::contrib::CA_Axes ca_axes;
2409+ fastjet::contrib::AntiKT_Axes antikt_axes (akAxesR0);
2410+ fastjet::contrib::WTA_KT_Axes wta_kt_axes;
2411+ fastjet::contrib::WTA_CA_Axes wta_ca_axes;
2412+ fastjet::contrib::OnePass_KT_Axes onepass_kt_axes;
2413+ fastjet::contrib::OnePass_CA_Axes onepass_ca_axes;
2414+ fastjet::contrib::OnePass_AntiKT_Axes onepass_antikt_axes (akAxesR0);
2415+ fastjet::contrib::OnePass_WTA_KT_Axes onepass_wta_kt_axes;
2416+ fastjet::contrib::OnePass_WTA_CA_Axes onepass_wta_ca_axes;
2417+ fastjet::contrib::MultiPass_Axes multipass_axes (nPass);
2418+
2419+ fastjet::contrib::AxesDefinition const * axesDef = 0 ;
2420+ switch ( axesdefenum ) {
2421+ case njettiness::KT_Axes : default : axesDef = &kt_axes; break ;
2422+ case njettiness::CA_Axes : axesDef = &ca_axes; break ;
2423+ case njettiness::AntiKT_Axes : axesDef = &antikt_axes; break ;
2424+ case njettiness::WTA_KT_Axes : axesDef = &wta_kt_axes; break ;
2425+ case njettiness::WTA_CA_Axes : axesDef = &wta_ca_axes; break ;
2426+ case njettiness::OnePass_KT_Axes : axesDef = &onepass_kt_axes; break ;
2427+ case njettiness::OnePass_CA_Axes : axesDef = &onepass_ca_axes; break ;
2428+ case njettiness::OnePass_AntiKT_Axes : axesDef = &onepass_antikt_axes; break ;
2429+ case njettiness::OnePass_WTA_KT_Axes : axesDef = &onepass_wta_kt_axes; break ;
2430+ case njettiness::OnePass_WTA_CA_Axes : axesDef = &onepass_wta_ca_axes; break ;
2431+ case njettiness::MultiPass_Axes : axesDef = &multipass_axes; break ;
2432+ }
2433+
2434+ auto routine = std::make_shared<fastjet::contrib::Njettiness>(*axesDef, *measureDef);
2435+
2436+ const auto & constituents = ow.parts ;
2437+ std::vector<double > taus;
2438+
2439+ for (size_t i = 0 ; i < constituents.size (); ++i) {
2440+ for (size_t k = 0 ; k < njets.size (); ++k) {
2441+ auto tau = routine->getTau (njets[k], *constituents[i]);
2442+ taus.push_back (tau);
2443+ }
2444+ }
2445+
2446+ auto taus_out = py::array (taus.size (), taus.data ());
2447+ taus_out.resize ({taus.size ()/njets.size (), njets.size ()});
2448+
2449+ return std::make_tuple (
2450+ taus_out
2451+ );
2452+ }, R"pbdoc(
2453+ Calculates njettiness values from inputs and converts them to numpy arrays.
2454+ Args:
2455+ None.
2456+ Returns:
2457+ the <njets>-tuple of njettiness values for all found jets, and their offsets
23182458 )pbdoc" );
23192459 py::class_<ClusterSequence>(m, " ClusterSequence" )
23202460 .def (py::init<const std::vector<PseudoJet> &, const JetDefinition &,
0 commit comments