Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8309709
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
54 KB
Subscribers
None
View Options
Index: contrib/contribs/LundPlane/trunk/LundEEGenerator.hh
===================================================================
--- contrib/contribs/LundPlane/trunk/LundEEGenerator.hh (revision 0)
+++ contrib/contribs/LundPlane/trunk/LundEEGenerator.hh (revision 1286)
@@ -0,0 +1,373 @@
+// $Id: LundEEGenerator.hh 1153 2018-08-22 11:56:35Z akarlberg, lscyboz $
+//
+// Copyright (c) 2018-, Frederic A. Dreyer, A. Karlberg, Gavin P. Salam,
+// Ludovic Scyboz, Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#ifndef __FASTJET_CONTRIB_LUNDEEGENERATOR_HH__
+#define __FASTJET_CONTRIB_LUNDEEGENERATOR_HH__
+
+#include "EEHelpers.hh"
+
+#include <fastjet/internal/base.hh>
+#include "fastjet/tools/Recluster.hh"
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/PseudoJet.hh"
+#include <string>
+#include <vector>
+#include <utility>
+#include <queue>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace contrib{
+
+class LundEEGenerator;
+
+//----------------------------------------------------------------------
+/// \class LundEEDeclustering
+/// Contains the declustering variables associated with a single qnode
+/// on the LundEE plane
+class LundEEDeclustering {
+public:
+
+ /// return the pair PseudoJet, i.e. sum of the two subjets
+ const PseudoJet & pair() const {return pair_;}
+ /// returns the subjet with larger transverse momentum
+ const PseudoJet & harder() const {return harder_;}
+ /// returns the subjet with smaller transverse momentum
+ const PseudoJet & softer() const {return softer_;}
+
+
+ /// returns pair().m() [cached]
+ double m() const {return m_;}
+
+ /// returns the effective pseudorapidity of the emission [cached]
+ double eta() const {return eta_;}
+
+ /// returns sin(theta) of the branching [cached]
+ double sin_theta() const {return sin_theta_;}
+
+ /// returns softer().modp() / (softer().modp() + harder().modp()) [cached]
+ double z() const {return z_;}
+
+ /// returns softer().modp() * sin(theta()) [cached]
+ double kt() const {return kt_;}
+
+ /// returns ln(softer().modp() * sin(theta())) [cached]
+ double lnkt() const {return lnkt_;}
+
+ /// returns z() * Delta() [cached]
+ double kappa() const {return kappa_;}
+
+ /// returns the index of the plane to which this branching belongs
+ int iplane() const {return iplane_;}
+
+ /// returns the depth of the plane on which this declustering
+ /// occurred. 0 is the primary plane, 1 is the first set of leaves, etc.
+ int depth() const {return depth_;}
+
+ /// returns iplane (plane index) of the leaf associated with the
+ /// potential further declustering of the softer of the objects in
+ /// this splitting
+ int leaf_iplane() const {return leaf_iplane_;}
+
+ /// Returns sign_s, indicating the initial parent jet index of this splitting
+ int sign_s() const {return sign_s_;}
+
+ /// returns an azimuthal type angle between this declustering plane and the previous one
+ double psi() const {return psi_;}
+
+ /// update the azimuthal angle (deprecated)
+ void set_psi(double psi) {psi_ = psi;}
+
+ /// returns the azimuthal angle psibar between this declustering plane and the previous one
+ double psibar() const {return psibar_;}
+
+
+ /// returns the coordinates in the Lund plane
+ std::pair<double,double> const lund_coordinates() const {
+ return std::pair<double,double>(eta_,lnkt_);
+ }
+
+ virtual ~LundEEDeclustering() {}
+
+private:
+ int iplane_;
+ double psi_, psibar_, lnkt_, eta_;
+ double m_, z_, kt_, kappa_, sin_theta_;
+ PseudoJet pair_, harder_, softer_;
+ int depth_ = -1, leaf_iplane_ = -1;
+ int sign_s_;
+
+protected:
+ /// the constructor is private, because users will not generally be
+ /// constructing a LundEEDeclustering element themselves.
+ LundEEDeclustering(const PseudoJet& pair,
+ const PseudoJet& j1, const PseudoJet& j2,
+ int iplane = -1, double psi = 0.0, double psibar = 0.0, int depth = -1, int leaf_iplane = -1, int sign_s = 1);
+
+ friend class LundEEGenerator;
+ friend class RecursiveLundEEGenerator;
+
+};
+
+
+/// Default comparison operator for LundEEDeclustering, using kt as the ordering.
+/// Useful when including declusterings in structures like priority queues
+inline bool operator<(const LundEEDeclustering& d1, const LundEEDeclustering& d2) {
+ return d1.kt() < d2.kt();
+}
+
+//----------------------------------------------------------------------
+/// Class to carry out Lund declustering to get anything from the
+/// primary Lund plane declusterings to the full Lund diagram with all
+/// its leaves, etc.
+class RecursiveLundEEGenerator {
+ public:
+ /// constructs a RecursiveLundEEGenerator with the specified depth.
+ /// - depth = 0 means only primary declusterings are registered
+ /// - depth = 1 means the first set of leaves are declustered
+ /// - ...
+ /// - depth < 0 means no limit, i.e. recurse through all leaves
+ RecursiveLundEEGenerator(int max_depth = 0, bool dynamical_psi_ref = false) :
+ max_depth_(max_depth), nx_(1,0,0,0), ny_(0,1,0,0), dynamical_psi_ref_(dynamical_psi_ref)
+ {}
+
+ /// destructor
+ virtual ~RecursiveLundEEGenerator() {}
+
+ /// This takes a cluster sequence with an e+e- C/A style algorithm, e.g.
+ /// EECambridgePlugin(ycut=1.0).
+ ///
+ /// The output is a vector of LundEEDeclustering objects, ordered
+ /// according to kt
+ virtual std::vector<LundEEDeclustering> result(const ClusterSequence & cs) const {
+ std::vector<PseudoJet> exclusive_jets = cs.exclusive_jets(2);
+ assert(exclusive_jets.size() == 2);
+
+ // order the two jets according to momentum along z axis
+ if (exclusive_jets[0].pz() < exclusive_jets[1].pz()) {
+ std::swap(exclusive_jets[0],exclusive_jets[1]);
+ }
+
+ PseudoJet d_ev = exclusive_jets[0] - exclusive_jets[1];
+ Matrix3 rotmat = Matrix3::from_direction(d_ev);
+
+ std::vector<LundEEDeclustering> declusterings;
+ int depth = 0;
+ int max_iplane_sofar = 1;
+ for (unsigned ijet = 0; ijet < exclusive_jets.size(); ijet++) {
+
+ // reference direction for psibar calculation
+ PseudoJet axis = d_ev/sqrt(d_ev.modp2());
+ PseudoJet ref_plane = axis;
+
+ int sign_s = ijet == 0? +1 : -1;
+ // We can pass a vector normal to a plane of reference for phi definitions
+ append_to_vector(declusterings, exclusive_jets[ijet], depth, ijet, max_iplane_sofar,
+ rotmat, sign_s, exclusive_jets[0], exclusive_jets[1], ref_plane, 0., true);
+ }
+
+ // a typedef to save typing below
+ typedef LundEEDeclustering LD;
+ // sort so that declusterings are returned in order of decreasing
+ // kt (if result of the lambda is true, then first object appears
+ // before the second one in the final sorted list)
+ sort(declusterings.begin(), declusterings.end(),
+ [](const LD & d1, LD & d2){return d1.kt() > d2.kt();});
+
+ return declusterings;
+ }
+
+ private:
+
+ /// internal routine to recursively carry out the declusterings,
+ /// adding each one to the declusterings vector; the primary
+ /// ones are dealt with first (from large to small angle),
+ /// and then secondary ones take place.
+ void append_to_vector(std::vector<LundEEDeclustering> & declusterings,
+ const PseudoJet & jet, int depth,
+ int iplane, int & max_iplane_sofar,
+ const Matrix3 & rotmat, int sign_s,
+ const PseudoJet & harder,
+ const PseudoJet & softer,
+ const PseudoJet & psibar_ref_plane,
+ const double & last_psibar, bool first_time) const {
+ PseudoJet j1, j2;
+ if (!jet.has_parents(j1, j2)) return;
+ if (j1.modp2() < j2.modp2()) std::swap(j1,j2);
+
+ // calculation of azimuth psi
+ Matrix3 new_rotmat;
+ if (dynamical_psi_ref_) {
+ new_rotmat = Matrix3::from_direction(rotmat.transpose()*(sign_s*jet)) * rotmat;
+ } else {
+ new_rotmat = rotmat;
+ }
+ PseudoJet rx = new_rotmat * nx_;
+ PseudoJet ry = new_rotmat * ny_;
+ PseudoJet u1 = j1/j1.modp(), u2 = j2/j2.modp();
+ PseudoJet du = u2 - u1;
+ double x = du.px() * rx.px() + du.py() * rx.py() + du.pz() * rx.pz();
+ double y = du.px() * ry.px() + du.py() * ry.py() + du.pz() * ry.pz();
+ double psi = atan2(y,x);
+
+ // calculation of psibar
+ double psibar = 0.;
+ PseudoJet n1, n2;
+
+ // First psibar for this jet
+ if (first_time) {
+
+ // Compute the angle between the planes spanned by (some axis,j1) and by (j1,j2)
+ n1 = cross_product(psibar_ref_plane,j1);
+ n2 = cross_product(j1,j2);
+
+ double signed_angle = 0.;
+ n2 /= n2.modp();
+ if (n1.modp() != 0) {
+ n1 /= n1.modp();
+ signed_angle = signed_angle_between_planes(n1,n2,j1);
+ }
+
+ psibar = map_to_pi(j1.phi() + signed_angle);
+ }
+ // Else take the value of psibar_i and the plane from the last splitting to define psibar_{i+1}
+ else {
+ n2 = cross_product(j1,j2);
+ n2 /= n2.modp();
+ psibar = map_to_pi(last_psibar + signed_angle_between_planes(psibar_ref_plane, n2, j1));
+ }
+
+ int leaf_iplane = -1;
+ // we will recurse into the softer "parent" only if the depth is
+ // not yet at its limit or if there is no limit on the depth (max_depth<0)
+ bool recurse_into_softer = (depth < max_depth_ || max_depth_ < 0);
+ if (recurse_into_softer) {
+ max_iplane_sofar += 1;
+ leaf_iplane = max_iplane_sofar;
+ }
+
+ LundEEDeclustering declust(jet, j1, j2, iplane, psi, psibar, depth, leaf_iplane, sign_s);
+ declusterings.push_back(declust);
+
+ // now recurse
+ // for the definition of psibar, we recursively pass the last splitting plane (normal to n2) and the last value
+ // of psibar
+ append_to_vector(declusterings, j1, depth, iplane, max_iplane_sofar, new_rotmat, sign_s, u1, u2, n2, psibar, false);
+ if (recurse_into_softer) {
+ append_to_vector(declusterings, j2, depth+1, leaf_iplane, max_iplane_sofar, new_rotmat, sign_s, u1, u2, n2, psibar, false);
+ }
+ }
+
+ int max_depth_ = 0;
+ /// vectors used to help define psi
+ PseudoJet nx_;
+ PseudoJet ny_;
+ bool dynamical_psi_ref_;
+};
+
+//----------------------------------------------------------------------
+/// \class LundEEGenerator
+/// Generates vector of LundEEDeclustering for a given jet
+/// corresponding to its LundEE primary plane.
+class LundEEGenerator : public FunctionOfPseudoJet< std::vector<LundEEDeclustering> > {
+public:
+ LundEEGenerator() {}
+
+ /// destructor
+ virtual ~LundEEGenerator() {}
+
+ // definitions needed for comparison of declusterings
+ struct CompareDeclustWithKt {
+ bool operator ()(const LundEEDeclustering& d1, const LundEEDeclustering& d2) const {
+ return d1.kt() < d2.kt();
+ }
+ };
+
+ /// return a vector of the declusterings of the primary plane of the
+ /// jet, registering the supplied information (iplane) about how to label
+ /// the plane
+ virtual std::vector<LundEEDeclustering> result_iplane(const PseudoJet& jet,
+ int iplane) const;
+
+ /// create the primary declustering sequence of a jet (with a default plane
+ /// label of -1)
+ virtual std::vector<LundEEDeclustering> result(const PseudoJet& jet) const override{
+ return this->result_iplane(jet, -1);
+ }
+
+protected:
+ /// create a declustering from a pseudojet and its parents
+ LundEEDeclustering single_declustering(const PseudoJet& pair,
+ const PseudoJet& j1, const PseudoJet& j2,
+ PseudoJet& cross, int iplane) const;
+};
+
+//----------------------------------------------------------------------
+class LundEEGeneratorOrdered : public LundEEGenerator {
+public:
+ LundEEGeneratorOrdered() {}
+ virtual ~LundEEGeneratorOrdered() {}
+
+ /// return vector of declusterings ordered according to the defined measure
+ virtual std::vector<LundEEDeclustering> result_iplane(const PseudoJet& jet,
+ int iplane) const override;
+
+ /// create an ordered declustering sequence of two jets
+ virtual std::vector<LundEEDeclustering> result_twojets(const PseudoJet& jet1,
+ const PseudoJet& jet2) const;
+
+ /// create an ordered declustering sequence of multiple jets and n secondary planes
+ virtual std::vector<LundEEDeclustering> result_jets(const std::vector<PseudoJet>& jets,
+ int n = 0) const;
+
+protected:
+ /// measure to use for ordering
+ virtual double ordering_measure(const LundEEDeclustering& d) const = 0;
+
+ /// fill a priority queue with ordered declusterings
+ virtual void fill_pq(const PseudoJet& jet, int iplane,
+ std::priority_queue< std::pair<double,LundEEDeclustering> >& pq) const;
+
+ virtual std::vector<LundEEDeclustering> pq_to_vector(std::priority_queue< std::pair<double,
+ LundEEDeclustering> >& pq) const;
+
+};
+
+class LundEEGeneratorKtOrdered : public LundEEGeneratorOrdered {
+protected:
+ /// measure to use for ordering
+ virtual double ordering_measure(const LundEEDeclustering& d) const override {return d.lnkt();};
+};
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
+
+/// for output of declustering information
+std::ostream & operator<<(std::ostream & ostr, const fastjet::contrib::LundEEDeclustering & d);
+
+
+
+#endif // __FASTJET_CONTRIB_LUNDEEGENERATOR_HH__
+
Index: contrib/contribs/LundPlane/trunk/AUTHORS
===================================================================
--- contrib/contribs/LundPlane/trunk/AUTHORS (revision 1285)
+++ contrib/contribs/LundPlane/trunk/AUTHORS (revision 1286)
@@ -1,12 +1,30 @@
The LundPlane FastJet contrib is developed and maintained by:
Frederic Dreyer <frederic.dreyer@physics.ox.ac.uk>
+ Alexander Karlberg <alexander.karlberg@physics.ox.ac.uk>
Gavin P. Salam <gavin.salam@cern.ch>
+ Ludovic Scyboz <ludovic.scyboz@physics.ox.ac.uk>
Gregory Soyez <soyez@fastjet.fr>
The physics is based on:
The Lund Jet Plane.
Frederic A. Dreyer, Gavin P. Salam, and Gregory Soyez
arXiv:1807.04758
+The definition of azimuthal angles, and examples of
+all-order observables sensitive to spin correlations
+(example_dpsi_collinear and example_dpsi_slice), are from:
+
+ Spin correlations in final-state parton showers and
+ jet observables
+ A. Karlberg, G. P. Salam, L. Scyboz, and R. Verheyen
+ Eur. Phys. J. C 81, 681 (2021)
+ https://doi.org/10.1140/epjc/s10052-021-09378-0
+
+and
+
+ Soft spin correlations in final-state parton showers
+ K. Hamilton, A. Karlberg, G. P. Salam, L. Scyboz,
+ and R. Verheyen
+ arXiv:2111.01161
\ No newline at end of file
Index: contrib/contribs/LundPlane/trunk/VERSION
===================================================================
--- contrib/contribs/LundPlane/trunk/VERSION (revision 1285)
+++ contrib/contribs/LundPlane/trunk/VERSION (revision 1286)
@@ -1 +1 @@
-1.0.3
+1.0.4
Index: contrib/contribs/LundPlane/trunk/example_dpsi_collinear.cc
===================================================================
--- contrib/contribs/LundPlane/trunk/example_dpsi_collinear.cc (revision 0)
+++ contrib/contribs/LundPlane/trunk/example_dpsi_collinear.cc (revision 1286)
@@ -0,0 +1,145 @@
+//----------------------------------------------------------------------
+/// \file example_dpsi_collinear.cc
+///
+/// This example program is meant to illustrate how the
+/// fastjet::contrib::LundEEGenerator class is used.
+///
+/// Run this example with
+///
+/// \verbatim
+/// ./example_dpsi_collinear < ../data/single-ee-event.dat
+/// \endverbatim
+
+//----------------------------------------------------------------------
+// $Id: example_dpsi_collinear.cc 1164 2018-08-23 10:06:45Z gsalam $
+//
+// Copyright (c) 2018-, Frederic A. Dreyer, A. Karlberg, Gavin P. Salam,
+// Ludovic Scyboz, Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/EECambridgePlugin.hh"
+#include <string>
+#include "LundEEGenerator.hh" // In external code, this should be fastjet/contrib/LundEEGenerator.hh
+using namespace std;
+using namespace fastjet;
+
+// Definitions for the collinear observable
+double z1_cut = 0.1;
+double z2_cut = 0.1;
+
+// forward declaration to make things clearer
+void read_event(vector<PseudoJet> &event);
+
+//----------------------------------------------------------------------
+int main(){
+
+ //----------------------------------------------------------
+ // read in input particles
+ vector<PseudoJet> event;
+ read_event(event);
+
+ cout << "# read an event with " << event.size() << " particles" << endl;
+ //----------------------------------------------------------
+ // create an instance of RecursiveLundEEGenerator, with default options
+ int depth = -1;
+ bool dynamic_psi_reference = true;
+ fastjet::contrib::RecursiveLundEEGenerator lund(depth, dynamic_psi_reference);
+
+ // first get some C/A jets
+ double y3_cut = 1.0;
+ JetDefinition::Plugin* ee_plugin = new EECambridgePlugin(y3_cut);
+ JetDefinition jet_def(ee_plugin);
+ ClusterSequence cs(event, jet_def);
+
+ // Get the list of primary declusterings
+ const vector<contrib::LundEEDeclustering> declusts = lund.result(cs);
+
+ // Find the highest-kt primary declustering (ordered in kt by default)
+ int i_primary = -1;
+ double psi_1;
+ for (int i=0; i<declusts.size(); i++) {
+ if (declusts[i].depth() == 0 && declusts[i].z() > z1_cut) {
+ i_primary = i;
+ psi_1 = declusts[i].psibar();
+ break;
+ }
+ }
+ if (i_primary < 0) return 0;
+
+ // Find the highest-kt secondary associated to that Lund leaf
+ int iplane_to_follow = declusts[i_primary].leaf_iplane();
+ vector<const contrib::LundEEDeclustering *> secondaries;
+ for (const auto & declust: declusts){
+ if (declust.iplane() == iplane_to_follow) secondaries.push_back(&declust);
+ }
+ if(secondaries.size() < 1) return 0;
+
+ int i_secondary = -1;
+ double dpsi;
+ for (int i=0; i<secondaries.size(); i++) {
+ if (secondaries[i]->z() > z2_cut) {
+ i_secondary = i;
+ double psi_2 = secondaries[i]->psibar();
+ dpsi = contrib::map_to_pi(psi_2-psi_1);
+ break;
+ }
+ }
+ if (i_secondary < 0) return 0;
+
+ cout << "Primary that passes the zcut of "
+ << z1_cut << ", with Lund coordinates ( ln 1/Delta, ln kt, psibar ):" << endl;
+ pair<double,double> coords = declusts[i_primary].lund_coordinates();
+ cout << "index [" << i_primary << "](" << coords.first << ", " << coords.second << ", "
+ << declusts[i_primary].psibar() << ")" << endl;
+ cout << endl << "with Lund coordinates for the secondary plane that passes the zcut of "
+ << z2_cut << endl;
+ coords = secondaries[i_secondary]->lund_coordinates();
+ cout << "index [" << i_secondary << "](" << coords.first << ", " << coords.second << ", "
+ << secondaries[i_secondary]->psibar() << ")";
+
+ cout << " --> delta_psi = " << dpsi << endl;
+
+ // Delete the EECambridge plugin
+ delete ee_plugin;
+
+ return 0;
+}
+
+// read in input particles
+void read_event(vector<PseudoJet> &event){
+ string line;
+ while (getline(cin, line)) {
+ istringstream linestream(line);
+ // take substrings to avoid problems when there is extra "pollution"
+ // characters (e.g. line-feed).
+ if (line.substr(0,4) == "#END") {return;}
+ if (line.substr(0,1) == "#") {continue;}
+ double px,py,pz,E;
+ linestream >> px >> py >> pz >> E;
+ PseudoJet particle(px,py,pz,E);
+
+ // push event onto back of full_event vector
+ event.push_back(particle);
+ }
+}
Index: contrib/contribs/LundPlane/trunk/README
===================================================================
--- contrib/contribs/LundPlane/trunk/README (revision 1285)
+++ contrib/contribs/LundPlane/trunk/README (revision 1286)
@@ -1,46 +1,62 @@
------------------------------------------------------------------------
LundPlane FastJet contrib
------------------------------------------------------------------------
The LundPlane FastJet contrib provides tools necessary to construct
the Lund Plane of a jet.
It is based on arXiv:1807.04758 by Frederic Dreyer, Gavin Salam, and
Gregory Soyez.
+Azimuthal-angle definitions are taken from arXiv:2103.16526, by
+Alexander Karlberg, Gavin Salam, Ludovic Scyboz and Rob Verheyen, and
+arXiv:2111.01161 by the authors above and Keith Hamilton.
+
It provides the following C++ classes:
- LundDeclustering
Contains the declustering variables associated with a node on
the Lund plane.
- LundGenerator
A tool to generate a vector of LundDeclustering for a given jet
corresponding to its primary Lund plane.
+- LundEEGenerator
+ A recursive tool to extract declusterings for a given jet in
+ e+e- collisions, i.e. its full Lund structure down to a user-given
+ depth
+
- LundWithSecondary
A tool to generate primary, and secondary, lund planes of a jet
according to the definition given as input.
- SecondaryLund, SecondaryLund_{mMDT|dotmMDT|Mass}
Provides a definition for the leading emission.
-There are two C++ examples which can be compiled with
+There are four C++ examples which can be compiled with
> make example example_secondary
The example program can be run using
> ./example < ../data/single-event.dat
and will output the primary lund plane declusterings as well as
generating a jets.json file, which can be read by a python script:
> python3 ./example.py
Some python classes to assist with reading and processing the json file
are provided in the read_lund_json.py module.
The example_secondary program outputs both the primary and secondary
Lund plane declusterings to screen, and can be run with:
-> ./example_secondary < ../data/single-event.dat
\ No newline at end of file
+> ./example_secondary < ../data/single-event.dat
+
+The example_dpsi_collinear and example_dpsi_slice programs compute the
+contribution to the collinear azimuthal delta_psi observable from
+2103.16526, and to the slice observable delta_psi_slice from 2111.01161,
+respectively. It can be run with
+
+> ./example_dpsi_collinear < ../data/single-ee-event.dat
Index: contrib/contribs/LundPlane/trunk/example_dpsi_slice.ref
===================================================================
--- contrib/contribs/LundPlane/trunk/example_dpsi_slice.ref (revision 0)
+++ contrib/contribs/LundPlane/trunk/example_dpsi_slice.ref (revision 1286)
@@ -0,0 +1,19 @@
+# read an event with 70 particles
+#--------------------------------------------------------------------------
+# FastJet release 3.3.2
+# M. Cacciari, G.P. Salam and G. Soyez
+# A software package for jet finding and analysis at colliders
+# http://fastjet.fr
+#
+# Please cite EPJC72(2012)1896 [arXiv:1111.6097] if you use this package
+# for scientific work and optionally PLB641(2006)57 [hep-ph/0512210].
+#
+# FastJet is provided without warranty under the terms of the GNU GPLv2.
+# It uses T. Chan's closest pair algorithm, S. Fortune's Voronoi code
+# and 3rd party plugin jet algorithms. See COPYING file for details.
+#--------------------------------------------------------------------------
+Primary in the central slice, with Lund coordinates ( ln 1/Delta, ln kt, psibar ):
+index [0](0.461518, 2.74826, 2.32912)
+
+with Lund coordinates for the (highest-kT) secondary plane that passes the zcut of 0.1
+index [0](0.860316, 1.51421, -2.65024) --> delta_psi,slice = 1.30383
Index: contrib/contribs/LundPlane/trunk/LundEEGenerator.cc
===================================================================
--- contrib/contribs/LundPlane/trunk/LundEEGenerator.cc (revision 0)
+++ contrib/contribs/LundPlane/trunk/LundEEGenerator.cc (revision 1286)
@@ -0,0 +1,222 @@
+// $Id: LundEEGenerator.cc 1153 2018-08-22 11:56:35Z frdreyer $
+//
+// Copyright (c) 2018-, Frederic A. Dreyer, A. Karlberg, Gavin P. Salam,
+// Ludovic Scyboz, Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include <sstream>
+#include "LundEEGenerator.hh"
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace contrib{
+
+LundEEDeclustering::LundEEDeclustering(const PseudoJet& pair,
+ const PseudoJet& j1, const PseudoJet& j2,
+ int iplane, double psi, double psibar,
+ int depth, int leaf_iplane, int sign_s)
+ : iplane_(iplane), psi_(psi), psibar_(psibar), m_(pair.m()), pair_(pair), depth_(depth), leaf_iplane_(leaf_iplane), sign_s_(sign_s) {
+
+ double omc = one_minus_costheta(j1,j2);
+
+ if (omc > sqrt(numeric_limits<double>::epsilon())) {
+ double cos_theta = 1.0 - omc;
+ double theta = acos(cos_theta);
+ sin_theta_ = sin(theta);
+ eta_ = -log(tan(theta/2.0));
+ } else {
+ // we are at small angles, so use small-angle formulas
+ double theta = sqrt(2. * omc);
+ sin_theta_ = theta;
+ eta_ = -log(theta/2);
+ }
+
+ // establish which of j1 and j2 is softer
+ if (j1.modp2() > j2.modp2()) {
+ harder_ = j1;
+ softer_ = j2;
+ } else {
+ harder_ = j2;
+ softer_ = j1;
+ }
+
+ // now work out the various LundEE declustering variables
+ double softer_modp = softer_.modp();
+ z_ = softer_modp / (softer_modp + harder_.modp());
+ kt_ = softer_modp * sin_theta_;
+ lnkt_ = log(kt_);
+ kappa_ = z_ * sin_theta_;
+}
+
+//----------------------------------------------------------------------
+/// return a vector of the declusterings of the primary plane of the
+/// jet, registering information about the plane from which this
+/// comes
+std::vector<LundEEDeclustering> LundEEGenerator::result_iplane(const PseudoJet& jet, int iplane) const {
+ std::vector<LundEEDeclustering> result;
+ PseudoJet j = jet;
+ PseudoJet pair, j1, j2, cross;
+ pair = j;
+ while (pair.has_parents(j1, j2)) {
+ // order the jets in their 3-mom norm
+ if (j1.modp2() < j2.modp2()) std::swap(j1,j2);
+ // on the first invocation cross has its default value of 0;
+ result.push_back(single_declustering(pair, j1, j2, cross, iplane));
+ pair = j1;
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------
+/// get declustering corresponding to a given pseudojet and its parents.
+///
+/// If cross is a null vector, then the psi value for the declustering
+/// will be set to zero and the cross vector will be defined as
+/// j1 x j2.
+///
+/// If cross is non-zero, then the psi value is determined as the
+/// angle between this j1 x j2 and the existing cross.
+LundEEDeclustering LundEEGenerator::single_declustering(const PseudoJet& pair,
+ const PseudoJet& j1,
+ const PseudoJet& j2,
+ PseudoJet& cross,
+ int iplane) const {
+ // get the angle between current declustering plane and previous one
+ PseudoJet j1xj2 = cross_product(j1,j2,false);
+ // the first time one encounters the next line cross == 0
+ // (default PJ initialisation), so one simply defines the direction
+ // meant by psi=0
+ double psi;
+ if (cross == double(0)) {
+ psi = 0;
+ cross = j1xj2;
+ // normalise it
+ cross /= cross.modp();
+ } else {
+ psi = theta(cross, j1xj2);
+ }
+
+ // prepare for next iteration
+ // return declustering element
+ return LundEEDeclustering(pair, j1, j2, iplane, psi);
+}
+
+//----------------------------------------------------------------------
+/// create an ordered declustering sequence for one jet
+std::vector<LundEEDeclustering> LundEEGeneratorOrdered::result_iplane(const PseudoJet& jet,
+ int iplane) const {
+ std::priority_queue< std::pair<double, LundEEDeclustering> > pq_declusts;
+ this->fill_pq(jet, iplane, pq_declusts);
+ return this->pq_to_vector(pq_declusts);
+}
+
+//----------------------------------------------------------------------
+/// create an ordered declustering sequence for two jets
+std::vector<LundEEDeclustering> LundEEGeneratorOrdered::result_twojets(const PseudoJet& jet1,
+ const PseudoJet& jet2) const {
+ std::priority_queue< std::pair<double, LundEEDeclustering> > pq_declusts;
+ this->fill_pq(jet1, 0, pq_declusts);
+ this->fill_pq(jet2, 1, pq_declusts);
+ return this->pq_to_vector(pq_declusts);
+}
+
+//----------------------------------------------------------------------
+/// create an ordered declustering sequence for multiple jets, along with n secondary planes
+std::vector<LundEEDeclustering> LundEEGeneratorOrdered::result_jets(const std::vector<PseudoJet>& jets,
+ int n) const{
+ std::priority_queue< std::pair<double, LundEEDeclustering> > pq_declusts;
+ unsigned int i=0;
+ for(; i < jets.size(); ++i)
+ this->fill_pq(jets[i], i, pq_declusts);
+ std::vector< std::pair<double, LundEEDeclustering> > tmp;
+ // get the n elements from which we want secondary planes
+ for(int isec=0; isec < n; ++isec) {
+ tmp.push_back(pq_declusts.top());
+ pq_declusts.pop();
+ }
+ // get the n secondary declustering sequences and insert them into priority queue
+ for(int isec=0; isec < n; ++isec) {
+ this->fill_pq(tmp[isec].second.softer(), isec+i, pq_declusts);
+ pq_declusts.push(tmp[isec]);
+ }
+ // return sorted vector of all the declusterings
+ return this->pq_to_vector(pq_declusts);
+}
+
+//----------------------------------------------------------------------
+/// fill a priority queue with ordered declusterings
+void LundEEGeneratorOrdered::fill_pq(const PseudoJet& jet, int iplane,
+ std::priority_queue< std::pair<double,LundEEDeclustering> >& pq) const {
+
+ PseudoJet j = jet;
+ PseudoJet pair, j1, j2, cross;
+ pair = j;
+ while (pair.has_parents(j1, j2)) {
+ // order the jets in their 3-mom norm
+ if (j1.modp2() < j2.modp2()) std::swap(j1,j2);
+ LundEEDeclustering d = single_declustering(pair, j1, j2, cross, iplane);
+ pq.push(std::make_pair(this->ordering_measure(d), d));
+ pair = j1;
+ }
+}
+
+//----------------------------------------------------------------------
+/// turn a priority queue to an ordered vector
+std::vector<LundEEDeclustering> LundEEGeneratorOrdered::pq_to_vector(std::priority_queue< std::pair<double,
+ LundEEDeclustering> >& pq) const {
+ std::vector<LundEEDeclustering> result;
+ PseudoJet cross;
+ while (!pq.empty()) {
+ LundEEDeclustering d = pq.top().second;
+ // update the psi angle according to the new ordering
+ PseudoJet newcross = PseudoJet(d.harder().py()*d.softer().pz()
+ - d.harder().pz()*d.softer().py(),
+ d.harder().pz()*d.softer().px()
+ - d.harder().px()*d.softer().pz(),
+ d.harder().px()*d.softer().py()
+ - d.harder().py()*d.softer().px(), 0.0);
+ if (cross != double(0)) d.set_psi(theta(cross, newcross));
+ cross = newcross;
+ // add declustering to result vector
+ result.push_back(d);
+ pq.pop();
+ }
+ return result;
+}
+
+} // namespace contrib
+
+
+FASTJET_END_NAMESPACE
+
+std::ostream & operator<<(std::ostream & ostr, const fastjet::contrib::LundEEDeclustering & d) {
+ ostr << "kt = " << d.kt()
+ << " z = " << d.z()
+ << " eta = " << d.eta()
+ << " psi = " << d.psi()
+ << " psibar = " << d.psibar()
+ << " m = " << d.m()
+ << " iplane = " << d.iplane()
+ << " depth = " << d.depth()
+ << " leaf_iplane = " << d.leaf_iplane();
+ return ostr;
+}
+
Index: contrib/contribs/LundPlane/trunk/EEHelpers.hh
===================================================================
--- contrib/contribs/LundPlane/trunk/EEHelpers.hh (revision 0)
+++ contrib/contribs/LundPlane/trunk/EEHelpers.hh (revision 1286)
@@ -0,0 +1,262 @@
+// $Id: EEHelpers.hh 1153 2018-08-22 11:56:35Z akarlberg, lscyboz $
+//
+// Copyright (c) 2018-, Frederic A. Dreyer, A. Karlberg, Gavin P. Salam,
+// Ludovic Scyboz, Gregory Soyez
+//
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#ifndef __FASTJET_CONTRIB_EEHELPERS_HH__
+#define __FASTJET_CONTRIB_EEHELPERS_HH__
+
+#include "fastjet/PseudoJet.hh"
+#include <array>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace contrib{
+
+//----------------------------------------------------------------------
+/// Returns the 3-vector cross-product of p1 and p2. If lightlike is false
+/// then the energy component is zero; if it's true the the energy component
+/// is arranged so that the vector is lighlike
+inline PseudoJet cross_product(const PseudoJet & p1, const PseudoJet & p2, bool lightlike=false) {
+ double px = p1.py() * p2.pz() - p2.py() * p1.pz();
+ double py = p1.pz() * p2.px() - p2.pz() * p1.px();
+ double pz = p1.px() * p2.py() - p2.px() * p1.py();
+
+ double E;
+ if (lightlike) {
+ E = sqrt(px*px + py*py + pz*pz);
+ } else {
+ E = 0.0;
+ }
+ return PseudoJet(px, py, pz, E);
+}
+
+/// Map angles to [-pi, pi]
+inline const double map_to_pi(const double &phi) {
+ if (phi < -M_PI) return phi + 2 * M_PI;
+ else if (phi > M_PI) return phi - 2 * M_PI;
+ else return phi;
+}
+
+inline double dot_product_3d(const PseudoJet & a, const PseudoJet & b) {
+ return a.px()*b.px() + a.py()*b.py() + a.pz()*b.pz();
+}
+
+/// Returns (1-cos theta) where theta is the angle between p1 and p2
+inline double one_minus_costheta(const PseudoJet & p1, const PseudoJet & p2) {
+
+ if (p1.m2() == 0 && p2.m2() == 0) {
+ // use the 4-vector dot product.
+ // For massless particles it gives us E1*E2*(1-cos theta)
+ return dot_product(p1,p2) / (p1.E() * p2.E());
+ } else {
+ double p1mod = p1.modp();
+ double p2mod = p2.modp();
+ double p1p2mod = p1mod*p2mod;
+ double dot = dot_product_3d(p1,p2);
+
+ if (dot > (1-std::numeric_limits<double>::epsilon()) * p1p2mod) {
+ PseudoJet cross_result = cross_product(p1, p2, false);
+ // the mass^2 of cross_result is equal to
+ // -(px^2 + py^2 + pz^2) = (p1mod*p2mod*sintheta_ab)^2
+ // so we can get
+ return -cross_result.m2()/(p1p2mod * (p1p2mod+dot));
+ }
+
+ return 1.0 - dot/p1p2mod;
+
+ }
+}
+
+// Get the angle between two planes defined by normalized vectors
+// n1, n2. The sign is decided by the direction of a vector n.
+inline double signed_angle_between_planes(const PseudoJet& n1,
+ const PseudoJet& n2, const PseudoJet& n) {
+
+ // Two vectors passed as arguments should be normalised to 1.
+ assert(fabs(n1.modp()-1) < sqrt(std::numeric_limits<double>::epsilon()) && fabs(n2.modp()-1) < sqrt(std::numeric_limits<double>::epsilon()));
+
+ double omcost = one_minus_costheta(n1,n2);
+ double theta;
+
+ // If theta ~ pi, we return pi.
+ if(fabs(omcost-2) < sqrt(std::numeric_limits<double>::epsilon())) {
+ theta = M_PI;
+ } else if (omcost > sqrt(std::numeric_limits<double>::epsilon())) {
+ double cos_theta = 1.0 - omcost;
+ theta = acos(cos_theta);
+ } else {
+ // we are at small angles, so use small-angle formulas
+ theta = sqrt(2. * omcost);
+ }
+
+ PseudoJet cp = cross_product(n1,n2);
+ double sign = dot_product_3d(cp,n);
+
+ if (sign > 0) return theta;
+ else return -theta;
+}
+
+class Matrix3 {
+public:
+ /// constructs an empty matrix
+ Matrix3() : matrix_({{{{0,0,0}}, {{0,0,0}}, {{0,0,0}}}}) {}
+
+ /// constructs a diagonal matrix with "unit" along each diagonal entry
+ Matrix3(double unit) : matrix_({{{{unit,0,0}}, {{0,unit,0}}, {{0,0,unit}}}}) {}
+
+ /// constructs a matrix from the array<array<...,3>,3> object
+ Matrix3(const std::array<std::array<double,3>,3> & mat) : matrix_(mat) {}
+
+ /// returns the entry at row i, column j
+ inline double operator()(int i, int j) const {
+ return matrix_[i][j];
+ }
+
+ /// returns a matrix for carrying out azimuthal rotation
+ /// around the z direction by an angle phi
+ static Matrix3 azimuthal_rotation(double phi) {
+ double cos_phi = cos(phi);
+ double sin_phi = sin(phi);
+ Matrix3 phi_rot( {{ {{cos_phi, sin_phi, 0}},
+ {{-sin_phi, cos_phi, 0}},
+ {{0,0,1}}}});
+ return phi_rot;
+ }
+
+ /// returns a matrix for carrying out a polar-angle
+ /// rotation, in the z-x plane, by an angle theta
+ static Matrix3 polar_rotation(double theta) {
+ double cos_theta = cos(theta);
+ double sin_theta = sin(theta);
+ Matrix3 theta_rot( {{ {{cos_theta, 0, sin_theta}},
+ {{0,1,0}},
+ {{-sin_theta, 0, cos_theta}}}});
+ return theta_rot;
+ }
+
+ /// This provides a rotation matrix that takes the z axis to the
+ /// direction of p. With skip_pre_rotation = false (the default), it
+ /// has the characteristic that if p is close to the z axis then the
+ /// azimuthal angle of anything at much larger angle is conserved.
+ ///
+ /// If skip_pre_rotation is true, then the azimuthal angles are not
+ /// when p is close to the z axis.
+ template<class T>
+ static Matrix3 from_direction(const T & p, bool skip_pre_rotation = false) {
+ double pt = p.pt();
+ double modp = p.modp();
+ double cos_theta = p.pz() / modp;
+ double sin_theta = pt / modp;
+ double cos_phi, sin_phi;
+ if (pt > 0.0) {
+ cos_phi = p.px()/pt;
+ sin_phi = p.py()/pt;
+ } else {
+ cos_phi = 1.0;
+ sin_phi = 0.0;
+ }
+
+ Matrix3 phi_rot({{ {{ cos_phi,-sin_phi, 0 }},
+ {{ sin_phi, cos_phi, 0 }},
+ {{ 0, 0, 1 }} }});
+ Matrix3 theta_rot( {{ {{ cos_theta, 0, sin_theta }},
+ {{ 0, 1, 0 }},
+ {{-sin_theta, 0, cos_theta }} }});
+
+ // since we have orthogonal matrices, the inverse and transpose
+ // are identical; we use the transpose for the frontmost rotation
+ // because
+ if (skip_pre_rotation) {
+ return phi_rot * theta_rot;
+ } else {
+ return phi_rot * (theta_rot * phi_rot.transpose());
+ }
+ }
+
+ template<class T>
+ static Matrix3 from_direction_no_pre_rotn(const T & p) {
+ return from_direction(p,true);
+ }
+
+
+
+ /// returns the transposed matrix
+ Matrix3 transpose() const {
+ // 00 01 02
+ // 10 11 12
+ // 20 21 22
+ Matrix3 result = *this;
+ std::swap(result.matrix_[0][1],result.matrix_[1][0]);
+ std::swap(result.matrix_[0][2],result.matrix_[2][0]);
+ std::swap(result.matrix_[1][2],result.matrix_[2][1]);
+ return result;
+ }
+
+ // returns the product with another matrix
+ Matrix3 operator*(const Matrix3 & other) const {
+ Matrix3 result;
+ // r_{ij} = sum_k this_{ik} & other_{kj}
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ for (int k = 0; k < 3; k++) {
+ result.matrix_[i][j] += this->matrix_[i][k] * other.matrix_[k][j];
+ }
+ }
+ }
+ return result;
+ }
+
+ friend std::ostream & operator<<(std::ostream & ostr, const Matrix3 & mat);
+private:
+ std::array<std::array<double,3>,3> matrix_;
+};
+
+inline std::ostream & operator<<(std::ostream & ostr, const Matrix3 & mat) {
+ ostr << mat.matrix_[0][0] << " " << mat.matrix_[0][1] << " " << mat.matrix_[0][2] << std::endl;
+ ostr << mat.matrix_[1][0] << " " << mat.matrix_[1][1] << " " << mat.matrix_[1][2] << std::endl;
+ ostr << mat.matrix_[2][0] << " " << mat.matrix_[2][1] << " " << mat.matrix_[2][2] << std::endl;
+ return ostr;
+}
+
+/// returns the project of this matrix with the PseudoJet,
+/// maintaining the 4th component of the PseudoJet unchanged
+inline PseudoJet operator*(const Matrix3 & mat, const PseudoJet & p) {
+ // r_{i} = m_{ij} p_j
+ std::array<double,3> res3{{0,0,0}};
+ for (unsigned i = 0; i < 3; i++) {
+ for (unsigned j = 0; j < 3; j++) {
+ res3[i] += mat(i,j) * p[j];
+ }
+ }
+ // return a jet that maintains all internal pointers by
+ // initialising the result from the input jet and
+ // then resetting the momentum.
+ PseudoJet result(p);
+ // maintain the energy component as it was
+ result.reset_momentum(res3[0], res3[1], res3[2], p[3]);
+ return result;
+}
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CONTRIB_EEHELPERS_HH__
+
Index: contrib/contribs/LundPlane/trunk/NEWS
===================================================================
--- contrib/contribs/LundPlane/trunk/NEWS (revision 1285)
+++ contrib/contribs/LundPlane/trunk/NEWS (revision 1286)
@@ -1,4 +1,7 @@
+2021/11/08: release of version 1.0.4
+- Recursive e+e- generator with
+ spin-correlation observables
2020/02/23: release of version 1.0.3
- fixes issue with C++98 compatibility
2018/10/29: release of version 1.0.2
2018/08/30: release of version 1.0.1
Index: contrib/contribs/LundPlane/trunk/Makefile
===================================================================
--- contrib/contribs/LundPlane/trunk/Makefile (revision 1285)
+++ contrib/contribs/LundPlane/trunk/Makefile (revision 1286)
@@ -1,84 +1,88 @@
# If you are using this Makefile standalone and fastjet-config is not
# in your path, edit this line to specify the full path
FASTJETCONFIG=fastjet-config
PREFIX=`$(FASTJETCONFIG) --prefix`
CXX=g++
CXXFLAGS= -O3 -Wall -g
install_script = $(SHELL) ../utils/install-sh
check_script = ../utils/check.sh
# global contrib-wide Makefile include may override some of the above
# variables (leading "-" means don't give an error if you can't find
# the file)
-include ../.Makefile.inc
#------------------------------------------------------------------------
# things that are specific to this contrib
NAME=LundPlane
-SRCS=LundGenerator.cc LundWithSecondary.cc SecondaryLund.cc
-EXAMPLES=example example_secondary
-INSTALLED_HEADERS=LundGenerator.hh LundWithSecondary.hh SecondaryLund.hh LundJSON.hh
+SRCS=LundGenerator.cc LundWithSecondary.cc SecondaryLund.cc LundEEGenerator.cc
+EXAMPLES=example example_secondary example_dpsi_collinear example_dpsi_slice
+INSTALLED_HEADERS=LundGenerator.hh LundWithSecondary.hh SecondaryLund.hh LundEEGenerator.hh LundJSON.hh
#------------------------------------------------------------------------
CXXFLAGS+= $(shell $(FASTJETCONFIG) --cxxflags)
-LDFLAGS += -lm $(shell $(FASTJETCONFIG) --libs)
+LDFLAGS += -lm $(shell $(FASTJETCONFIG) --libs) -lfastjetplugins
OBJS = $(SRCS:.cc=.o)
EXAMPLES_SRCS = $(EXAMPLES:=.cc)
install_HEADER = $(install_script) -c -m 644
install_LIB = $(install_script) -c -m 644
install_DIR = $(install_script) -d
install_DATA = $(install_script) -c -m 644
install_PROGRAM = $(install_script) -c -s
install_SCRIPT = $(install_script) -c
.PHONY: clean distclean examples check install
# compilation of the code (default target)
all: lib$(NAME).a
lib$(NAME).a: $(OBJS)
ar cru lib$(NAME).a $(OBJS)
ranlib lib$(NAME).a
# building the examples
examples: $(EXAMPLES)
# the following construct makes it possible to automatically build
# each of the examples listed in $EXAMPLES
$(EXAMPLES): % : %.o all
$(CXX) $(CXXFLAGS) -o $@ $< -L. -l$(NAME) $(LDFLAGS)
# check that everything went fine
check: examples
@for prog in $(EXAMPLES); do\
- $(check_script) $${prog} ../data/single-event.dat || exit 1; \
+ if [ "$${prog}" = "example_dpsi_collinear" ] || [ "$${prog}" = "example_dpsi_slice" ]; then \
+ $(check_script) $${prog} ../data/single-ee-event.dat || exit 1; \
+ else \
+ $(check_script) $${prog} ../data/single-event.dat || exit 1; \
+ fi; \
done
@echo "All tests successful"
# cleaning the directory
clean:
rm -f *~ *.o
distclean: clean
rm -f lib$(NAME).a $(EXAMPLES)
# install things in PREFIX/...
install: all
$(install_DIR) $(PREFIX)/include/fastjet/contrib
for header in $(INSTALLED_HEADERS); do\
$(install_HEADER) $$header $(PREFIX)/include/fastjet/contrib/;\
done
$(install_DIR) $(PREFIX)/lib
$(install_LIB) lib$(NAME).a $(PREFIX)/lib
depend:
makedepend -Y -- -- $(SRCS) $(EXAMPLES_SRCS)
# DO NOT DELETE
LundGenerator.o: LundGenerator.hh
LundWithSecondary.o: LundWithSecondary.hh LundGenerator.hh SecondaryLund.hh
SecondaryLund.o: SecondaryLund.hh LundGenerator.hh
example.o: LundGenerator.hh SecondaryLund.hh LundJSON.hh
example_secondary.o: LundWithSecondary.hh LundGenerator.hh SecondaryLund.hh
Index: contrib/contribs/LundPlane/trunk/example_dpsi_collinear.ref
===================================================================
--- contrib/contribs/LundPlane/trunk/example_dpsi_collinear.ref (revision 0)
+++ contrib/contribs/LundPlane/trunk/example_dpsi_collinear.ref (revision 1286)
@@ -0,0 +1,19 @@
+# read an event with 70 particles
+#--------------------------------------------------------------------------
+# FastJet release 3.3.2
+# M. Cacciari, G.P. Salam and G. Soyez
+# A software package for jet finding and analysis at colliders
+# http://fastjet.fr
+#
+# Please cite EPJC72(2012)1896 [arXiv:1111.6097] if you use this package
+# for scientific work and optionally PLB641(2006)57 [hep-ph/0512210].
+#
+# FastJet is provided without warranty under the terms of the GNU GPLv2.
+# It uses T. Chan's closest pair algorithm, S. Fortune's Voronoi code
+# and 3rd party plugin jet algorithms. See COPYING file for details.
+#--------------------------------------------------------------------------
+Primary that passes the zcut of 0.1, with Lund coordinates ( ln 1/Delta, ln kt, psibar ):
+index [0](0.461518, 2.74826, 2.32912)
+
+with Lund coordinates for the secondary plane that passes the zcut of 0.1
+index [0](0.860316, 1.51421, -2.65024) --> delta_psi = 1.30383
Index: contrib/contribs/LundPlane/trunk/example_dpsi_slice.cc
===================================================================
--- contrib/contribs/LundPlane/trunk/example_dpsi_slice.cc (revision 0)
+++ contrib/contribs/LundPlane/trunk/example_dpsi_slice.cc (revision 1286)
@@ -0,0 +1,173 @@
+//----------------------------------------------------------------------
+/// \file example_dpsi_slice.cc
+///
+/// This example program is meant to illustrate how the
+/// fastjet::contrib::LundEEGenerator class is used.
+///
+/// Run this example with
+///
+/// \verbatim
+/// ./example_dpsi_slice < ../data/single-ee-event.dat
+/// \endverbatim
+
+//----------------------------------------------------------------------
+// $Id: example_dpsi_slice.cc 1164 2018-08-23 10:06:45Z gsalam $
+//
+// Copyright (c) 2018-, Frederic A. Dreyer, A. Karlberg, Gavin P. Salam,
+// Ludovic Scyboz, Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/EECambridgePlugin.hh"
+#include <string>
+#include "LundEEGenerator.hh" // In external code, this should be fastjet/contrib/LundEEGenerator.hh
+using namespace std;
+using namespace fastjet;
+
+// Definitions for the slice observable (ymax = 1, zcut = 0.1)
+double abs_rap_slice = 1;
+double z2_cut = 0.1;
+
+// forward declaration to make things clearer
+void read_event(vector<PseudoJet> &event);
+
+// returns true if PseudoJet p is in the central slice of half-width abs_rap_slice
+// w.r.t. the event axis pref
+bool in_slice(const PseudoJet & p, const PseudoJet & pref) {
+
+ // Rotate p, and use the rapidity to determine if p is in the slice
+ contrib::Matrix3 rotmat = contrib::Matrix3::from_direction(pref).transpose();
+ const PseudoJet p_rot = rotmat*p;
+
+ return fabs(p_rot.rap()) < abs_rap_slice;
+}
+
+//----------------------------------------------------------------------
+int main(){
+
+ //----------------------------------------------------------
+ // read in input particles
+ vector<PseudoJet> event;
+ read_event(event);
+
+ cout << "# read an event with " << event.size() << " particles" << endl;
+ //----------------------------------------------------------
+ // create an instance of RecursiveLundEEGenerator, with default options
+ int depth = -1;
+ bool dynamic_psi_reference = true;
+ fastjet::contrib::RecursiveLundEEGenerator lund(depth, dynamic_psi_reference);
+
+ // first get some C/A jets
+ double y3_cut = 1.0;
+ JetDefinition::Plugin* ee_plugin = new EECambridgePlugin(y3_cut);
+ JetDefinition jet_def(ee_plugin);
+ ClusterSequence cs(event, jet_def);
+
+ // Get the event axis (to be used for the slice)
+ std::vector<PseudoJet> excl = cs.exclusive_jets(2);
+ assert(excl.size() == 2);
+ // order the two jets according to momentum along z axis
+ if (excl[0].pz() < excl[1].pz()) {
+ std::swap(excl[0],excl[1]);
+ }
+ const PseudoJet ev_axis = excl[0]-excl[1];
+
+ // Get the list of primary declusterings
+ const vector<contrib::LundEEDeclustering> declusts = lund.result(cs);
+
+ // find the declustering that throws something into a fixed slice
+ // (from a parent that was not in the slice) and that throws the
+ // largest pt (relative to the z axis) into that slice
+
+ int index_of_max_pt_in_slice = -1;
+ double max_pt_in_slice = 0.0;
+ double psi_1;
+ for (unsigned i = 0; i < declusts.size(); i++) {
+ const auto & decl = declusts[i];
+ if (!in_slice(decl.harder(), ev_axis) && in_slice(decl.softer(), ev_axis)) {
+ if (decl.softer().pt() > max_pt_in_slice) {
+ index_of_max_pt_in_slice = i;
+ max_pt_in_slice = decl.softer().pt();
+ psi_1 = decl.psibar();
+ }
+ }
+ }
+ if (index_of_max_pt_in_slice < 0) return 0;
+
+ // establish what we need to follow and the reference psi_1
+ int iplane_to_follow = declusts[index_of_max_pt_in_slice].leaf_iplane();
+
+ vector<const contrib::LundEEDeclustering *> secondaries;
+ for (const auto & declust: declusts){
+ if (declust.iplane() == iplane_to_follow) secondaries.push_back(&declust);
+ }
+
+ int index_of_max_kt_secondary = -1;
+ double dpsi;
+ for (uint i_secondary=0; i_secondary<secondaries.size(); i_secondary++) {
+ if (secondaries[i_secondary]->z() > z2_cut) {
+
+ index_of_max_kt_secondary = i_secondary;
+ double psi_2 = secondaries[i_secondary]->psibar();
+ dpsi = contrib::map_to_pi(psi_2 - psi_1);
+
+ break;
+ }
+ }
+ if (index_of_max_kt_secondary < 0) return 0;
+
+ cout << "Primary in the central slice, with Lund coordinates ( ln 1/Delta, ln kt, psibar ):" << endl;
+ pair<double,double> coords = declusts[index_of_max_pt_in_slice].lund_coordinates();
+ cout << "index [" << index_of_max_pt_in_slice << "](" << coords.first << ", " << coords.second << ", "
+ << declusts[index_of_max_pt_in_slice].psibar() << ")" << endl;
+ cout << endl << "with Lund coordinates for the (highest-kT) secondary plane that passes the zcut of "
+ << z2_cut << endl;
+ coords = secondaries[index_of_max_kt_secondary]->lund_coordinates();
+ cout << "index [" << index_of_max_kt_secondary << "](" << coords.first << ", " << coords.second << ", "
+ << secondaries[index_of_max_kt_secondary]->psibar() << ")";
+
+ cout << " --> delta_psi,slice = " << dpsi << endl;
+
+ // Delete the EECambridge plugin
+ delete ee_plugin;
+
+ return 0;
+}
+
+// read in input particles
+void read_event(vector<PseudoJet> &event){
+ string line;
+ while (getline(cin, line)) {
+ istringstream linestream(line);
+ // take substrings to avoid problems when there is extra "pollution"
+ // characters (e.g. line-feed).
+ if (line.substr(0,4) == "#END") {return;}
+ if (line.substr(0,1) == "#") {continue;}
+ double px,py,pz,E;
+ linestream >> px >> py >> pz >> E;
+ PseudoJet particle(px,py,pz,E);
+
+ // push event onto back of full_event vector
+ event.push_back(particle);
+ }
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 21, 4:15 PM (21 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4023409
Default Alt Text
(54 KB)
Attached To
rFASTJETSVN fastjetsvn
Event Timeline
Log In to Comment