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