31 #include "fastjet/PseudoJet.hh"
32 #include "fastjet/ClusterSequence.hh"
33 #include "fastjet/ClusterSequenceActiveArea.hh"
34 #include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
42 FASTJET_BEGIN_NAMESPACE
53 void ClusterSequenceActiveArea::_initialise_and_run_AA (
56 const bool & writeout_combinations) {
58 bool continue_running;
59 _initialise_AA(jet_def_in, ghost_spec, writeout_combinations, continue_running);
60 if (continue_running) {
62 _postprocess_AA(ghost_spec);
67 void ClusterSequenceActiveArea::_resize_and_zero_AA () {
69 _average_area.resize(2*_jets.size()); _average_area = 0.0;
70 _average_area2.resize(2*_jets.size()); _average_area2 = 0.0;
71 _average_area_4vector.resize(2*_jets.size());
72 _average_area_4vector =
PseudoJet(0.0,0.0,0.0,0.0);
73 _non_jet_area = 0.0; _non_jet_area2 = 0.0; _non_jet_number=0.0;
77 void ClusterSequenceActiveArea::_initialise_AA (
78 const JetDefinition & jet_def_in,
79 const GhostedAreaSpec & ghost_spec,
80 const bool & writeout_combinations,
81 bool & continue_running)
85 _ghost_spec_repeat = ghost_spec.repeat();
88 _resize_and_zero_AA();
91 _maxrap_for_area = ghost_spec.ghost_maxrap();
92 _safe_rap_for_area = _maxrap_for_area - jet_def_in.R();
101 if (ghost_spec.repeat() <= 0) {
102 _initialise_and_run(jet_def_in, writeout_combinations);
103 continue_running =
false;
108 _decant_options(jet_def_in, writeout_combinations);
112 _fill_initial_history();
115 _has_dangerous_particles =
false;
117 continue_running =
true;
122 void ClusterSequenceActiveArea::_run_AA (
const GhostedAreaSpec & ghost_spec) {
124 vector<PseudoJet> input_jets(_jets);
127 vector<int> unique_tree;
130 for (
int irepeat = 0; irepeat < ghost_spec.repeat(); irepeat++) {
132 ClusterSequenceActiveAreaExplicitGhosts clust_seq(input_jets,
133 jet_def(), ghost_spec);
135 _has_dangerous_particles |= clust_seq.has_dangerous_particles();
139 _transfer_ghost_free_history(clust_seq);
141 unique_tree = unique_history_order();
145 _transfer_areas(unique_tree, clust_seq);
152 void ClusterSequenceActiveArea::_postprocess_AA (
const GhostedAreaSpec & ghost_spec) {
153 _average_area /= ghost_spec.repeat();
154 _average_area2 /= ghost_spec.repeat();
155 if (ghost_spec.repeat() > 1) {
158 const double tmp = ghost_spec.repeat()-1;
159 _average_area2 = sqrt(abs(_average_area2 - _average_area*_average_area)/tmp);
161 _average_area2 = 0.0;
164 _non_jet_area /= ghost_spec.repeat();
165 _non_jet_area2 /= ghost_spec.repeat();
166 _non_jet_area2 = sqrt(abs(_non_jet_area2 - _non_jet_area*_non_jet_area)/
167 ghost_spec.repeat());
168 _non_jet_number /= ghost_spec.repeat();
173 for (
unsigned i = 0; i < _average_area_4vector.size(); i++) {
174 _average_area_4vector[i] = (1.0/ghost_spec.repeat()) * _average_area_4vector[i];
276 double ClusterSequenceActiveArea::pt_per_unit_area(
279 vector<PseudoJet> incl_jets = inclusive_jets();
280 vector<double> pt_over_areas;
282 for (
unsigned i = 0; i < incl_jets.size(); i++) {
283 if (abs(incl_jets[i].rap()) < _safe_rap_for_area) {
285 if ( strat == median_4vector ) {
286 this_area = area_4vector(incl_jets[i]).perp();
288 this_area = area(incl_jets[i]);
290 pt_over_areas.push_back(incl_jets[i].perp()/this_area);
295 if (pt_over_areas.size() == 0) {
return 0.0;}
300 sort(pt_over_areas.begin(), pt_over_areas.end());
301 double non_ghost_median_ratio = pt_over_areas[pt_over_areas.size()/2];
306 double nj_median_pos = (pt_over_areas.size()-1 - _non_jet_number)/2.0;
307 double nj_median_ratio;
308 if (nj_median_pos >= 0 && pt_over_areas.size() > 1) {
309 int int_nj_median = int(nj_median_pos);
311 pt_over_areas[int_nj_median] * (int_nj_median+1-nj_median_pos)
312 + pt_over_areas[int_nj_median+1] * (nj_median_pos - int_nj_median);
314 nj_median_ratio = 0.0;
319 double pt_sum = 0.0, pt_sum_with_cut = 0.0;
320 double area_sum = _non_jet_area, area_sum_with_cut = _non_jet_area;
321 double ratio_sum = 0.0;
322 double ratio_n = _non_jet_number;
323 for (
unsigned i = 0; i < incl_jets.size(); i++) {
324 if (abs(incl_jets[i].rap()) < _safe_rap_for_area) {
326 if ( strat == median_4vector ) {
327 this_area = area_4vector(incl_jets[i]).perp();
329 this_area = area(incl_jets[i]);
331 pt_sum += incl_jets[i].perp();
332 area_sum += this_area;
333 double ratio = incl_jets[i].perp()/this_area;
334 if (ratio < range*nj_median_ratio) {
335 pt_sum_with_cut += incl_jets[i].perp();
336 area_sum_with_cut += this_area;
337 ratio_sum += ratio; ratio_n++;
343 double trunc_sum = 0, trunc_sumsqr = 0;
344 vector<double> means(pt_over_areas.size()), sd(pt_over_areas.size());
345 for (
unsigned i = 0; i < pt_over_areas.size() ; i++ ) {
346 double ratio = pt_over_areas[i];
348 trunc_sumsqr += ratio*ratio;
349 means[i] = trunc_sum / (i+1);
350 sd[i] = sqrt(abs(means[i]*means[i] - trunc_sumsqr/(i+1)));
351 cerr <<
"i, means, sd: " <<i<<
", "<< means[i] <<
", "<<sd[i]<<
", "<<
352 sd[i]/sqrt(i+1.0)<<endl;
354 cout <<
"-----------------------------------"<<endl;
355 for (
unsigned i = 0; i <= pt_over_areas.size()/2 ; i++ ) {
356 cout <<
"Median "<< i <<
" = " << pt_over_areas[i]<<endl;
358 cout <<
"Number of non-jets: "<<_non_jet_number<<endl;
359 cout <<
"Area of non-jets: "<<_non_jet_area<<endl;
360 cout <<
"Default median position: " << (pt_over_areas.size()-1)/2.0<<endl;
361 cout <<
"NJ median position: " << nj_median_pos <<endl;
362 cout <<
"NJ median value: " << nj_median_ratio <<endl;
369 return nj_median_ratio;
370 case non_ghost_median:
371 return non_ghost_median_ratio;
372 case pttot_over_areatot:
373 return pt_sum / area_sum;
374 case pttot_over_areatot_cut:
375 return pt_sum_with_cut / area_sum_with_cut;
377 return ratio_sum/ratio_n;
379 return nj_median_ratio;
445 double ClusterSequenceActiveArea::empty_area(
const Selector & selector)
const {
448 throw Error(
"ClusterSequenceActiveArea: empty area can only be computed from selectors applying jet by jet");
453 for (
unsigned i = 0; i < _ghost_jets.size(); i++) {
454 if (selector.
pass(_ghost_jets[i])) {
455 empty += _ghost_jets[i].area;
459 for (
unsigned i = 0; i < _unclustered_ghosts.size(); i++) {
460 if (selector.
pass(_unclustered_ghosts[i])) {
461 empty += _unclustered_ghosts[i].area;
464 empty /= _ghost_spec_repeat;
469 double ClusterSequenceActiveArea::n_empty_jets(
const Selector & selector)
const {
470 _check_selector_good_for_median(selector);
473 for (
unsigned i = 0; i < _ghost_jets.size(); i++) {
474 if (selector.
pass(_ghost_jets[i])) inrange++;
476 inrange /= _ghost_spec_repeat;
483 void ClusterSequenceActiveArea::_transfer_ghost_free_history(
486 const vector<history_element> & gs_history = ghosted_seq.
history();
487 vector<int> gs2self_hist_map(gs_history.size());
496 while (igs < gs_history.size() && gs_history[igs].parent1 == InexistentParent) {
499 gs2self_hist_map[igs] = iself++;
501 gs2self_hist_map[igs] = Invalid;
508 assert(iself == _history.size());
514 if (igs == gs_history.size())
return;
520 gs2self_hist_map[igs] = Invalid;
526 bool parent1_is_ghost = ghosted_seq.
is_pure_ghost(gs_hist_el.parent1);
532 if (parent1_is_ghost && !parent2_is_ghost && gs_hist_el.
parent2 >= 0) {
533 gs2self_hist_map[igs] = gs2self_hist_map[gs_hist_el.
parent2];
536 if (!parent1_is_ghost && parent2_is_ghost) {
537 gs2self_hist_map[igs] = gs2self_hist_map[gs_hist_el.parent1];
544 gs2self_hist_map[igs] = _history.size();
547 int jet_i = _history[gs2self_hist_map[gs_hist_el.parent1]].jetp_index;
548 int jet_j = _history[gs2self_hist_map[gs_hist_el.
parent2]].jetp_index;
550 _do_ij_recombination_step(jet_i, jet_j, gs_hist_el.
dij, newjet_k);
553 assert(gs_history[igs].parent2 == BeamJet);
555 gs2self_hist_map[igs] = _history.size();
557 _do_iB_recombination_step(
558 _history[gs2self_hist_map[gs_hist_el.parent1]].jetp_index,
561 }
while (++igs < gs_history.size());
566 void ClusterSequenceActiveArea::_transfer_areas(
567 const vector<int> & unique_hist_order,
570 const vector<history_element> & gs_history = ghosted_seq.
history();
571 const vector<PseudoJet> & gs_jets = ghosted_seq.
jets();
574 const double tolerance = 1e-11;
579 valarray<double> our_areas(_history.size());
582 valarray<PseudoJet> our_area_4vectors(_history.size());
583 our_area_4vectors =
PseudoJet(0.0,0.0,0.0,0.0);
585 for (
unsigned i = 0; i < gs_history.size(); i++) {
587 unsigned gs_hist_index = gs_unique_hist_order[i];
588 if (gs_hist_index < ghosted_seq.
n_particles())
continue;
590 int parent1 = gs_hist.parent1;
593 if (parent2 == BeamJet) {
596 gs_jets[gs_history[parent1].jetp_index];
597 double area_local = ghosted_seq.
area(jet);
602 _ghost_jets.push_back(GhostJet(jet,area_local));
603 if (abs(jet.
rap()) < _safe_rap_for_area) {
604 _non_jet_area += area_local;
605 _non_jet_area2 += area_local*area_local;
606 _non_jet_number += 1;
613 while (++j <
int(_history.size())) {
614 hist_index = unique_hist_order[j];
615 if (hist_index >= _initial_n)
break;}
618 if (j >=
int(_history.size()))
throw Error(
"ClusterSequenceActiveArea: overran reference array in diB matching");
622 int refjet_index = _history[_history[hist_index].parent1].jetp_index;
623 assert(refjet_index >= 0 && refjet_index <
int(_jets.size()));
624 const PseudoJet & refjet = _jets[refjet_index];
634 _throw_unless_jets_have_same_perp_or_E(jet, refjet, tolerance,
638 our_areas[hist_index] = area_local;
639 our_area_4vectors[hist_index] = ext_area;
645 our_areas[_history[hist_index].parent1] = area_local;
646 our_area_4vectors[_history[hist_index].parent1] = ext_area;
654 while (++j <
int(_history.size())) {
655 hist_index = unique_hist_order[j];
656 if (hist_index >= _initial_n)
break;}
659 if (j >=
int(_history.size()))
throw Error(
"ClusterSequenceActiveArea: overran reference array in dij matching");
664 if (_history[hist_index].parent2 == BeamJet)
throw Error(
"ClusterSequenceActiveArea: could not match clustering sequences (encountered dij matched with diB)");
671 const PseudoJet & refjet = _jets[_history[hist_index].jetp_index];
674 _throw_unless_jets_have_same_perp_or_E(jet, refjet, tolerance,
679 double area_local = ghosted_seq.
area(jet);
680 our_areas[hist_index] += area_local;
699 _jet_def.recombiner()->plus_equal(our_area_4vectors[hist_index], ext_area);
707 const PseudoJet & jet1 = gs_jets[gs_history[parent1].jetp_index];
708 int our_parent1 = _history[hist_index].parent1;
709 our_areas[our_parent1] = ghosted_seq.
area(jet1);
710 our_area_4vectors[our_parent1] = ghosted_seq.
area_4vector(jet1);
712 const PseudoJet & jet2 = gs_jets[gs_history[parent2].jetp_index];
713 int our_parent2 = _history[hist_index].parent2;
714 our_areas[our_parent2] = ghosted_seq.
area(jet2);
715 our_area_4vectors[our_parent2] = ghosted_seq.
area_4vector(jet2);
723 for (
unsigned iu = 0; iu < unclust.size(); iu++) {
725 double area_local = ghosted_seq.
area(unclust[iu]);
726 _unclustered_ghosts.push_back(GhostJet(unclust[iu],area_local));
738 for (
unsigned int area_index = 0; area_index<our_areas.size(); area_index++){
739 _average_area[area_index] += our_areas[area_index];
740 _average_area2[area_index] += our_areas[area_index]*our_areas[area_index];
746 for (
unsigned i = 0; i < our_area_4vectors.size(); i++) {
747 _jet_def.recombiner()->plus_equal(_average_area_4vector[i],
748 our_area_4vectors[i]);
756 void ClusterSequenceActiveArea::_throw_unless_jets_have_same_perp_or_E(
765 && abs(jet.E()-refjet.E()) > tolerance*max(jet.E(),refjet.E())) {
767 ostr <<
"Could not match clustering sequence for an inclusive/exclusive jet when reconstructing areas. See FAQ for possible explanations." << endl;
769 << refjet.px() <<
" "
770 << refjet.py() <<
" "
771 << refjet.pz() <<
" "
772 << refjet.E() << endl;
779 ostr <<
" NB: some particles have pt too low wrt ghosts -- this may be the cause" << endl;}
782 throw Error(ostr.str());
786 FASTJET_END_NAMESPACE