31 #include "fastjet/tools/JetMedianBackgroundEstimator.hh"
32 #include <fastjet/ClusterSequenceArea.hh>
33 #include <fastjet/ClusterSequenceStructure.hh>
37 FASTJET_BEGIN_NAMESPACE
41 double BackgroundJetScalarPtDensity::result(
const PseudoJet & jet)
const {
46 for (
unsigned i = 0; i < constituents.size(); i++) {
47 scalar_pt += pow(constituents[i].perp(), _pt_power);
49 return scalar_pt / jet.
area();
53 std::string BackgroundJetScalarPtDensity::description()
const {
55 oss <<
"BackgroundScalarJetPtDensity";
56 if (_pt_power != 1.0) oss <<
" with pt_power = " << _pt_power;
62 double BackgroundRescalingYPolynomial::result(
const PseudoJet & jet)
const {
65 double rescaling = _a0 + _a1*y + _a2*y2 + _a3*y2*y + _a4*y2*y2;
72 LimitedWarning JetMedianBackgroundEstimator::_warnings_preliminary;
84 JetMedianBackgroundEstimator::JetMedianBackgroundEstimator(
const Selector &rho_range,
87 : _rho_range(rho_range), _jet_def(jet_def), _area_def(area_def){
93 _check_jet_alg_good_for_median();
120 throw Error(
"JetMedianBackgroundEstimator::set_particles can only be called if you set the jet (and area) definition explicitly through the class constructor");
166 _check_jet_alg_good_for_median();
170 throw Error(
"JetMedianBackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)");
187 throw Error(
"JetMedianBackgroundEstimator::JetMedianBackgroundEstimator: At least one jet is needed to compute the background properties");
192 if (! (jets[0].has_associated_cluster_sequence()) && (jets[0].has_area()))
193 throw Error(
"JetMedianBackgroundEstimator::JetMedianBackgroundEstimator: the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase");
195 _csi = jets[0].structure_shared_ptr();
199 for (
unsigned int i=1;i<jets.size(); i++){
200 if (! jets[i].has_associated_cluster_sequence())
201 throw Error(
"JetMedianBackgroundEstimator::set_jets(...): the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase");
203 if (jets[i].structure_shared_ptr().get() != _csi.get())
204 throw Error(
"JetMedianBackgroundEstimator::set_jets(...): all the jets used to estimate the background properties must share the same ClusterSequence");
208 _check_jet_alg_good_for_median();
211 if ((!csab->has_explicit_ghosts()) && (!_rho_range.
has_finite_area())){
212 throw Error(
"JetMedianBackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)");
217 _included_jets = jets;
231 throw Error(
"The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
232 _recompute_if_needed();
239 throw Error(
"The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
240 _recompute_if_needed();
251 _recompute_if_needed(jet);
252 double our_rho = _rho;
253 if (_rescaling_class != 0) {
254 our_rho *= (*_rescaling_class)(jet);
266 _recompute_if_needed(jet);
267 double our_sigma = _sigma;
268 if (_rescaling_class != 0) {
269 our_sigma *= (*_rescaling_class)(jet);
279 throw Error(
"JetMediamBackgroundEstimator: rho_m requested but rho_m calculation is disabled (either eplicitly or due to the presence of a jet density class).");
282 throw Error(
"The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
283 _recompute_if_needed();
294 throw Error(
"JetMediamBackgroundEstimator: sigma_m requested but rho_m/sigma_m calculation is disabled (either explicitly or due to the presence of a jet density class).");
297 throw Error(
"The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
298 _recompute_if_needed();
306 _recompute_if_needed(jet);
307 double our_rho = _rho_m;
308 if (_rescaling_class != 0) {
309 our_rho *= (*_rescaling_class)(jet);
319 _recompute_if_needed(jet);
320 double our_sigma = _sigma_m;
321 if (_rescaling_class != 0) {
322 our_sigma *= (*_rescaling_class)(jet);
338 _enable_rho_m =
true;
342 _rho_m = _sigma_m = 0.0;
343 _n_jets_used = _n_empty_jets = 0;
344 _empty_area = _mean_area = 0.0;
346 _included_jets.clear();
348 _jet_density_class = 0;
349 _rescaling_class = 0;
359 _warnings_preliminary.
warn(
"JetMedianBackgroundEstimator::set_jet_density_class: density classes are still preliminary in FastJet 3.1. Their interface may differ in future releases (without guaranteeing backward compatibility). Note that since FastJet 3.1, rho_m and sigma_m are accessible direclty in JetMedianBackgroundEstimator and GridMedianBackgroundEstimator(with no need for a density class).");
360 _jet_density_class = jet_density_class_in;
371 desc <<
"JetMedianBackgroundEstimator, using " << _jet_def.
description()
373 <<
" and selecting jets with " << _rho_range.
description();
385 void JetMedianBackgroundEstimator::_recompute_if_needed(
const PseudoJet &jet){
390 if (jet == _current_reference)
return;
398 _recompute_if_needed();
402 void JetMedianBackgroundEstimator::_compute()
const {
408 vector<double> vector_for_median_pt;
409 vector<double> vector_for_median_dt;
410 double total_area = 0.0;
414 vector<PseudoJet> selected_jets = _rho_range(_included_jets);
417 double median_input_pt, median_input_dt=0.0;
418 BackgroundJetPtMDensity m_density;
420 for (
unsigned i = 0; i < selected_jets.size(); i++) {
421 const PseudoJet & current_jet = selected_jets[i];
423 double this_area = (_use_area_4vector) ? current_jet.area_4vector().perp() : current_jet.area();
427 if (_jet_density_class == 0) {
428 median_input_pt = current_jet.perp()/this_area;
430 median_input_pt = (*_jet_density_class)(current_jet);
437 median_input_dt = m_density(current_jet);
440 if (_rescaling_class != 0) {
441 double resc = (*_rescaling_class)(current_jet);;
442 median_input_pt /= resc;
443 median_input_dt /= resc;
447 vector_for_median_pt.push_back(median_input_pt);
449 vector_for_median_dt.push_back(median_input_dt);
451 total_area += this_area;
454 _warnings_zero_area.
warn(
"JetMedianBackgroundEstimator::_compute(...): discarded jet with zero area. Zero-area jets may be due to (i) too large a ghost area (ii) a jet being outside the ghost range (iii) the computation not being done using an appropriate algorithm (kt;C/A).");
459 if (vector_for_median_pt.size() == 0) {
469 const ClusterSequenceAreaBase * csab = (dynamic_cast<ClusterSequenceStructure*>(_csi.get()))->validated_csab();
470 if (csab->has_explicit_ghosts()) {
474 _empty_area = csab->empty_area(_rho_range);
475 _n_empty_jets = csab->n_empty_jets(_rho_range);
478 double total_njets = _n_jets_used + _n_empty_jets;
479 total_area += _empty_area;
486 _mean_area = total_area / total_njets;
487 _sigma = stand_dev * sqrt(_mean_area);
493 _sigma_m = stand_dev * sqrt(_mean_area);
504 void JetMedianBackgroundEstimator::_check_csa_alive()
const{
505 ClusterSequenceStructure* csa = dynamic_cast<ClusterSequenceStructure*>(_csi.get());
507 throw Error(
"JetMedianBackgroundEstimator: there is no cluster sequence associated with the JetMedianBackgroundEstimator");
509 if (! dynamic_cast<ClusterSequenceStructure*>(_csi.get())->has_associated_cluster_sequence())
510 throw Error(
"JetMedianBackgroundEstimator: modifications are no longer possible as the underlying ClusterSequence has gone out of scope");
517 void JetMedianBackgroundEstimator::_check_jet_alg_good_for_median()
const{
518 const JetDefinition * jet_def = &_jet_def;
523 const ClusterSequence * cs = dynamic_cast<ClusterSequenceStructure*>(_csi.get())->validated_cs();
524 jet_def = &(cs->jet_def());
530 _warnings.
warn(
"JetMedianBackgroundEstimator: jet_def being used may not be suitable for estimating diffuse backgrounds (good alternatives are kt, cam)");
536 FASTJET_END_NAMESPACE