CMS 3D CMS Logo

FastPrunePlugin.cc
Go to the documentation of this file.
1 //
3 // Implements the FastPrunePlugin class. See FastPrunePlugin.hh for a
4 // description.
5 //
7 
8 #include "RecoJets/JetAlgorithms/interface/FastPrunePlugin.hh"
9 
10 #include <sstream>
11 #include <cmath>
12 #include <vector>
13 #include <algorithm>
14 using namespace std;
15 
16 using namespace fastjet;
17 
18 FastPrunePlugin::FastPrunePlugin(const JetDefinition& find_definition,
19  const JetDefinition& prune_definition,
20  const double& zcut,
21  const double& Rcut_factor)
22  : _find_definition(find_definition),
23  _prune_definition(prune_definition),
24  _minpT(20.),
25  _unpruned_seq(nullptr),
26  _pruned_recombiner(nullptr),
27  _cut_setter(new DefaultCutSetter(zcut, Rcut_factor)) {
28  // If the passed prune_definition (copied into _prune_def) has an external
29  // recombiner, use it. Otherwise, create our own DefaultRecombiner. We
30  // could just point to _prune_definition's DefaultRecombiner, but FastJet
31  // actually sets this to use external_scheme later when we set
32  // _prune_definition's Recombiner to be a PrunedRecombiner. (Calling
33  // JetDefinition::set_recombiner() also calls jetdef._default_recombiner =
34  // DefaultRecombiner(external_scheme) as a sanity check to keep you from
35  // using it.)
36  RecombinationScheme scheme = _prune_definition.recombination_scheme();
37  if (scheme == external_scheme)
38  _pruned_recombiner = new PrunedRecombiner(_prune_definition.recombiner(), zcut, 0.0);
39  else
40  _pruned_recombiner = new PrunedRecombiner(scheme, zcut, 0.0);
41 }
42 
43 FastPrunePlugin::FastPrunePlugin(const JetDefinition& find_definition,
44  const JetDefinition& prune_definition,
45  const JetDefinition::Recombiner* recomb,
46  const double& zcut,
47  const double& Rcut_factor)
48  : _find_definition(find_definition),
49  _prune_definition(prune_definition),
50  _minpT(20.),
51  _unpruned_seq(nullptr),
52  _pruned_recombiner(new PrunedRecombiner(recomb, zcut, 0.0)),
53  _cut_setter(new DefaultCutSetter(zcut, Rcut_factor)) {}
54 
55 FastPrunePlugin::FastPrunePlugin(const JetDefinition& find_definition,
56  const JetDefinition& prune_definition,
57  CutSetter* const cut_setter)
58  : _find_definition(find_definition),
59  _prune_definition(prune_definition),
60  _minpT(20.),
61  _unpruned_seq(nullptr),
62  _pruned_recombiner(nullptr),
63  _cut_setter(cut_setter) {
64  // See comments in first constructor
65  RecombinationScheme scheme = _prune_definition.recombination_scheme();
66  if (scheme == external_scheme)
67  _pruned_recombiner = new PrunedRecombiner(_prune_definition.recombiner());
68  else
69  _pruned_recombiner = new PrunedRecombiner(scheme);
70 }
71 
72 FastPrunePlugin::FastPrunePlugin(const JetDefinition& find_definition,
73  const JetDefinition& prune_definition,
74  CutSetter* const cut_setter,
75  const JetDefinition::Recombiner* recomb)
76  : _find_definition(find_definition),
77  _prune_definition(prune_definition),
78  _minpT(20.),
79  _unpruned_seq(nullptr),
80  _pruned_recombiner(new PrunedRecombiner(recomb)),
81  _cut_setter(cut_setter) {}
82 
83 string FastPrunePlugin::description() const {
84  ostringstream desc;
85 
86  desc << "Pruned jet algorithm \n"
87  << "----------------------- \n"
88  << "Jet finder: " << _find_definition.description() << "\n----------------------- \n"
89  << "Prune jets with: " << _prune_definition.description() << "\n----------------------- \n"
90  << "Pruning parameters: "
91  << "zcut = " << _cut_setter->zcut << ", "
92  << "Rcut_factor = ";
93  if (DefaultCutSetter* cs = dynamic_cast<DefaultCutSetter*>(_cut_setter))
94  desc << cs->Rcut_factor;
95  else
96  desc << "[dynamic]";
97  desc << "\n"
98  << "----------------------- \n";
99 
100  return desc.str();
101 }
102 
103 // Meat of the plugin. This function takes the input particles from input_seq
104 // and calls plugin_record_{ij, iB}_recombination repeatedly such that
105 // input_seq holds a cluster sequence corresponding to pruned jets
106 // This function first creates unpruned jets using _find_definition, then uses
107 // the prune_definition, along with the PrunedRecombiner, on each jet to
108 // produce a pruned jet. For each of these jets, output_mergings() is called,
109 // which reads the history of the pruned sequence and calls the
110 // plugin_record functions of input_seq to match this history.
111 // Branches that are pruned appear in the history as PseudoJets with no
112 // children. For this reason, only inclusive_jets() is sensible to use with
113 // the final ClusterSequence. The substructure, e.g., constituents() of a
114 // pruned jet will not include the pruned away branchings.
115 void FastPrunePlugin::run_clustering(ClusterSequence& input_seq) const {
116  // this will be filled in the output_mergings() step
117  _pruned_subjets.clear();
118 
119  vector<PseudoJet> inputs = input_seq.jets();
120  // Record user_index's so we can match PJ's in pruned jets to PJ's in
121  // input_seq.
122  // Use i+1 to distinguish from the default, which in some places appears to
123  // be 0.
124  // Note that we're working with a local copy of the input jets, so we don't
125  // change the indices in input_seq.
126  for (unsigned int i = 0; i < inputs.size(); i++)
127  inputs[i].set_user_index(i + 1);
128 
129  // ClusterSequence for initial (unpruned) jet finding
130  if (_unpruned_seq)
131  delete _unpruned_seq;
132  _unpruned_seq = new ClusterSequence(inputs, _find_definition);
133 
134  // now, for each jet, construct a pruned version:
135  vector<PseudoJet> unpruned_jets = sorted_by_pt(_unpruned_seq->inclusive_jets(_minpT));
136 
137  for (unsigned int i = 0; i < unpruned_jets.size(); i++) {
138  _cut_setter->SetCuts(unpruned_jets[i], *_unpruned_seq);
139  _pruned_recombiner->reset(_cut_setter->zcut, _cut_setter->Rcut);
140  _prune_definition.set_recombiner(_pruned_recombiner);
141 
142  // temp way to get constituents, to compare to new version
143  vector<PseudoJet> constituents;
144  for (size_t j = 0; j < inputs.size(); ++j)
145  if (_unpruned_seq->object_in_jet(inputs[j], unpruned_jets[i])) {
146  constituents.push_back(inputs[j]);
147  }
148  ClusterSequence pruned_seq(constituents, _prune_definition);
149 
150  vector<int> pruned_PJs = _pruned_recombiner->pruned_pseudojets();
151  _output_mergings(pruned_seq, pruned_PJs, input_seq);
152  }
153 }
154 
155 // Takes the merging structure of "in_seq" and feeds this into "out_seq" using
156 // _plugin_record_{ij,iB}_recombination().
157 // PJ's in the input CS should have user_index's that are their (index+1) in
158 // _jets() in the output CS (the output CS should be the input CS to
159 // run_clustering()).
160 // This allows us to build up the same jet in out_seq as already exists in
161 // in_seq.
162 void FastPrunePlugin::_output_mergings(ClusterSequence& in_seq,
163  vector<int>& pruned_pseudojets,
164  ClusterSequence& out_seq) const {
165  // vector to store the pruned subjets for this jet
166  vector<PseudoJet> temp_pruned_subjets;
167 
168  vector<PseudoJet> p = in_seq.jets();
169 
170  // sort this vector so we can binary search it
171  sort(pruned_pseudojets.begin(), pruned_pseudojets.end());
172 
173  // get the history from in_seq
174  const vector<ClusterSequence::history_element>& hist = in_seq.history();
175  vector<ClusterSequence::history_element>::const_iterator iter = hist.begin();
176 
177  // skip particle input elements
178  while (iter->parent1 == ClusterSequence::InexistentParent)
179  iter++;
180 
181  // Walk through history. PseudoJets in in_seq should have a user_index
182  // corresponding to their index in out_seq. Note that when we create a
183  // new PJ via record_ij we need to set the user_index of our local copy.
184  for (; iter != hist.end(); iter++) {
185  int new_jet_index = -1;
186  int jet_index = iter->jetp_index;
187  int parent1 = iter->parent1;
188  int parent2 = iter->parent2;
189  int parent1_index = p[hist[iter->parent1].jetp_index].user_index() - 1;
190 
191  if (parent2 == ClusterSequence::BeamJet) {
192  out_seq.plugin_record_iB_recombination(parent1_index, iter->dij);
193  } else {
194  int parent2_index = p[hist[parent2].jetp_index].user_index() - 1;
195 
196  // Check if either parent is stored in pruned_pseudojets
197  // Note that it is the history index that is stored
198  if (binary_search(pruned_pseudojets.begin(), pruned_pseudojets.end(), parent2)) {
199  // pruned away parent2 -- just give child parent1's index
200  p[jet_index].set_user_index(p[hist[parent1].jetp_index].user_index());
201  temp_pruned_subjets.push_back(out_seq.jets()[parent2_index]);
202  } else if (binary_search(pruned_pseudojets.begin(), pruned_pseudojets.end(), parent1)) {
203  // pruned away parent1 -- just give child parent2's index
204  p[jet_index].set_user_index(p[hist[parent2].jetp_index].user_index());
205  temp_pruned_subjets.push_back(out_seq.jets()[parent1_index]);
206  } else {
207  // no pruning -- record combination and index for child
208  out_seq.plugin_record_ij_recombination(parent1_index, parent2_index, iter->dij, new_jet_index);
209  p[jet_index].set_user_index(new_jet_index + 1);
210  }
211  }
212  }
213 
214  _pruned_subjets.push_back(temp_pruned_subjets);
215 }