FastJet 3.0beta1
|
00001 //STARTHEADER 00002 // $Id: Selector.cc 2493 2011-08-03 15:48:16Z salam $ 00003 // 00004 // Copyright (c) 2005-2011, Matteo Cacciari, Gavin Salam and Gregory Soyez 00005 // 00006 //---------------------------------------------------------------------- 00007 // This file is part of FastJet. 00008 // 00009 // FastJet is free software; you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation; either version 2 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // The algorithms that underlie FastJet have required considerable 00015 // development and are described in hep-ph/0512210. If you use 00016 // FastJet as part of work towards a scientific publication, please 00017 // include a citation to the FastJet paper. 00018 // 00019 // FastJet is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 // GNU General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with FastJet; if not, write to the Free Software 00026 // Foundation, Inc.: 00027 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00028 //---------------------------------------------------------------------- 00029 //ENDHEADER 00030 00031 00032 #include <sstream> 00033 #include <algorithm> 00034 #include "fastjet/Selector.hh" 00035 #include "fastjet/GhostedAreaSpec.hh" // for area support 00036 00037 using namespace std; 00038 00039 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh 00040 00041 //---------------------------------------------------------------------- 00042 // implementations of some of the more complex bits of Selector 00043 //---------------------------------------------------------------------- 00044 00045 // implementation of the operator() acting on a vector of jets 00046 std::vector<PseudoJet> Selector::operator()(const std::vector<PseudoJet> & jets) const { 00047 std::vector<PseudoJet> result; 00048 const SelectorWorker * worker = validated_worker(); 00049 if (worker->applies_jet_by_jet()) { 00050 //if (false) { 00051 // for workers that apply jet by jet, this is more efficient 00052 for (std::vector<PseudoJet>::const_iterator jet = jets.begin(); 00053 jet != jets.end(); jet++) { 00054 if (worker->pass(*jet)) result.push_back(*jet); 00055 } 00056 } else { 00057 // for workers that can only be applied to entire vectors, 00058 // go through the following 00059 std::vector<const PseudoJet *> jetptrs(jets.size()); 00060 for (unsigned i = 0; i < jets.size(); i++) { 00061 jetptrs[i] = & jets[i]; 00062 } 00063 worker->terminator(jetptrs); 00064 for (unsigned i = 0; i < jetptrs.size(); i++) { 00065 if (jetptrs[i]) result.push_back(jets[i]); 00066 } 00067 } 00068 return result; 00069 } 00070 00071 00072 //---------------------------------------------------------------------- 00073 // count the number of jets that pass the cuts 00074 unsigned int Selector::count(const std::vector<PseudoJet> & jets) const { 00075 unsigned n = 0; 00076 const SelectorWorker * worker = validated_worker(); 00077 00078 // separate strategies according to whether the worker applies jet by jet 00079 if (worker->applies_jet_by_jet()) { 00080 for (unsigned i = 0; i < jets.size(); i++) { 00081 if (worker->pass(jets[i])) n++; 00082 } 00083 } else { 00084 std::vector<const PseudoJet *> jetptrs(jets.size()); 00085 for (unsigned i = 0; i < jets.size(); i++) { 00086 jetptrs[i] = & jets[i]; 00087 } 00088 _worker->terminator(jetptrs); 00089 for (unsigned i = 0; i < jetptrs.size(); i++) { 00090 if (jetptrs[i]) n++; 00091 } 00092 } 00093 00094 return n; 00095 } 00096 00097 00098 //---------------------------------------------------------------------- 00099 // sift the input jets into two vectors -- those that pass the selector 00100 // and those that do not 00101 void Selector::sift(const std::vector<PseudoJet> & jets, 00102 std::vector<PseudoJet> & jets_that_pass, 00103 std::vector<PseudoJet> & jets_that_fail 00104 ) const { 00105 const SelectorWorker * worker = validated_worker(); 00106 00107 jets_that_pass.clear(); 00108 jets_that_fail.clear(); 00109 00110 // separate strategies according to whether the worker applies jet by jet 00111 if (worker->applies_jet_by_jet()) { 00112 for (unsigned i = 0; i < jets.size(); i++) { 00113 if (worker->pass(jets[i])) { 00114 jets_that_pass.push_back(jets[i]); 00115 } else { 00116 jets_that_fail.push_back(jets[i]); 00117 } 00118 } 00119 } else { 00120 std::vector<const PseudoJet *> jetptrs(jets.size()); 00121 for (unsigned i = 0; i < jets.size(); i++) { 00122 jetptrs[i] = & jets[i]; 00123 } 00124 _worker->terminator(jetptrs); 00125 for (unsigned i = 0; i < jetptrs.size(); i++) { 00126 if (jetptrs[i]) { 00127 jets_that_pass.push_back(jets[i]); 00128 } else { 00129 jets_that_fail.push_back(jets[i]); 00130 } 00131 } 00132 } 00133 } 00134 00135 // area using default ghost area 00136 double Selector::area() const{ 00137 return area(gas::def_ghost_area); 00138 } 00139 00140 // implementation of the Selector's area function 00141 double Selector::area(double ghost_area) const{ 00142 if (! is_geometric()) throw InvalidArea(); 00143 00144 // has area will already check we've got a valid worker 00145 if (_worker->has_known_area()) return _worker->known_area(); 00146 00147 // generate a set of "ghosts" 00148 double rapmin, rapmax; 00149 get_rapidity_extent(rapmin, rapmax); 00150 GhostedAreaSpec ghost_spec(rapmin, rapmax, 1, ghost_area); 00151 std::vector<PseudoJet> ghosts; 00152 ghost_spec.add_ghosts(ghosts); 00153 00154 // check what passes the selection 00155 return ghost_spec.ghost_area() * ((*this)(ghosts)).size(); 00156 } 00157 00158 00159 //---------------------------------------------------------------------- 00160 // implementations of some of the more complex bits of SelectorWorker 00161 //---------------------------------------------------------------------- 00162 // check if it has a finite area 00163 bool SelectorWorker::has_finite_area() const { 00164 if (! is_geometric()) return false; 00165 double rapmin, rapmax; 00166 get_rapidity_extent(rapmin, rapmax); 00167 return (rapmax != std::numeric_limits<double>::infinity()) 00168 && (-rapmin != std::numeric_limits<double>::infinity()); 00169 } 00170 00171 00172 00173 //---------------------------------------------------------------------- 00174 // very basic set of selectors (at the moment just the identity!) 00175 //---------------------------------------------------------------------- 00176 00177 //---------------------------------------------------------------------- 00178 /// helper for selecting the n hardest jets 00179 class SW_Identity : public SelectorWorker { 00180 public: 00181 /// ctor with specification of the number of objects to keep 00182 SW_Identity(){} 00183 00184 /// just let everything pass 00185 virtual bool pass(const PseudoJet & jet) const { 00186 return true; 00187 } 00188 00189 /// For each jet that does not pass the cuts, this routine sets the 00190 /// pointer to 0. 00191 virtual void terminator(vector<const PseudoJet *> & jets) const { 00192 // everyything passes, hence nothing to nullify 00193 return; 00194 } 00195 00196 /// returns a description of the worker 00197 virtual string description() const { return "Identity";} 00198 00199 /// strictly speaking, this is geometric 00200 virtual bool is_geometric() const { return true;} 00201 }; 00202 00203 00204 // returns an "identity" selector that lets everything pass 00205 Selector SelectorIdentity() { 00206 return Selector(new SW_Identity); 00207 } 00208 00209 00210 //---------------------------------------------------------------------- 00211 // selector and workers for operators 00212 //---------------------------------------------------------------------- 00213 00214 //---------------------------------------------------------------------- 00215 /// helper for combining selectors with a logical not 00216 class SW_Not : public SelectorWorker { 00217 public: 00218 /// ctor 00219 SW_Not(const Selector & s) : _s(s) {} 00220 00221 /// return a copy of the current object 00222 virtual SelectorWorker* copy(){ return new SW_Not(*this);} 00223 00224 /// returns true if a given object passes the selection criterium 00225 /// this has to be overloaded by derived workers 00226 virtual bool pass(const PseudoJet & jet) const { 00227 // make sure that the "pass" can be applied on both selectors 00228 if (!applies_jet_by_jet()) 00229 throw Error("Cannot apply this selector worker to an individual jet"); 00230 00231 return ! _s.pass(jet); 00232 } 00233 00234 /// returns true if this can be applied jet by jet 00235 virtual bool applies_jet_by_jet() const {return _s.applies_jet_by_jet();} 00236 00237 /// select the jets in the list that pass both selectors 00238 virtual void terminator(vector<const PseudoJet *> & jets) const { 00239 // if we can apply the selector jet-by-jet, call the base selector 00240 // that does exactly that 00241 if (applies_jet_by_jet()){ 00242 SelectorWorker::terminator(jets); 00243 return; 00244 } 00245 00246 // check the effect of the selector we want to negate 00247 vector<const PseudoJet *> s_jets = jets; 00248 _s.worker()->terminator(s_jets); 00249 00250 // now apply the negation: all the jets that pass the base 00251 // selector (i.e. are not NULL) have to be set to NULL 00252 for (unsigned int i=0; i<s_jets.size(); i++){ 00253 if (s_jets[i]) jets[i] = NULL; 00254 } 00255 } 00256 00257 /// returns a description of the worker 00258 virtual string description() const { 00259 ostringstream ostr; 00260 ostr << "!(" << _s.description() << ")"; 00261 return ostr.str(); 00262 } 00263 00264 /// is geometric if the underlying selector is 00265 virtual bool is_geometric() const { return _s.is_geometric();} 00266 00267 /// returns true if the worker can be set_referenced 00268 virtual bool takes_reference() const { return _s.takes_reference();} 00269 00270 /// set the reference jet for this selector 00271 virtual void set_reference(const PseudoJet &ref) { _s.set_reference(ref);} 00272 00273 protected: 00274 Selector _s; 00275 }; 00276 00277 00278 // logical not applied on a selector 00279 Selector operator!(const Selector & s) { 00280 return Selector(new SW_Not(s)); 00281 } 00282 00283 00284 //---------------------------------------------------------------------- 00285 /// Base class for binary operators 00286 class SW_BinaryOperator: public SelectorWorker { 00287 public: 00288 /// ctor 00289 SW_BinaryOperator(const Selector & s1, const Selector & s2) : _s1(s1), _s2(s2) { 00290 // stores info for more efficient access to the selector's properties 00291 00292 // we can apply jet by jet only if this is the case for both sub-selectors 00293 _applies_jet_by_jet = _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet(); 00294 00295 // the selector takes a reference if either of the sub-selectors does 00296 _takes_reference = _s1.takes_reference() || _s2.takes_reference(); 00297 00298 // we have a well-defined area provided the two objects have one 00299 _is_geometric = _s1.is_geometric() && _s2.is_geometric(); 00300 } 00301 00302 /// returns true if this can be applied jet by jet 00303 virtual bool applies_jet_by_jet() const {return _applies_jet_by_jet;} 00304 00305 /// returns true if this takes a reference jet 00306 virtual bool takes_reference() const{ 00307 return _takes_reference; 00308 } 00309 00310 /// sets the reference jet 00311 virtual void set_reference(const PseudoJet ¢re){ 00312 _s1.set_reference(centre); 00313 _s2.set_reference(centre); 00314 } 00315 00316 /// check if it has a finite area 00317 virtual bool is_geometric() const { return _is_geometric;} 00318 00319 protected: 00320 Selector _s1, _s2; 00321 bool _applies_jet_by_jet; 00322 bool _takes_reference; 00323 bool _is_geometric; 00324 }; 00325 00326 00327 00328 //---------------------------------------------------------------------- 00329 /// helper for combining selectors with a logical and 00330 class SW_And: public SW_BinaryOperator { 00331 public: 00332 /// ctor 00333 SW_And(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2){} 00334 00335 /// return a copy of this 00336 virtual SelectorWorker* copy(){ return new SW_And(*this);} 00337 00338 /// returns true if a given object passes the selection criterium 00339 /// this has to be overloaded by derived workers 00340 virtual bool pass(const PseudoJet & jet) const { 00341 // make sure that the "pass" can be applied on both selectors 00342 if (!applies_jet_by_jet()) 00343 throw Error("Cannot apply this selector worker to an individual jet"); 00344 00345 return _s1.pass(jet) && _s2.pass(jet); 00346 } 00347 00348 /// select the jets in the list that pass both selectors 00349 virtual void terminator(vector<const PseudoJet *> & jets) const { 00350 // if we can apply the selector jet-by-jet, call the base selector 00351 // that does exactly that 00352 if (applies_jet_by_jet()){ 00353 SelectorWorker::terminator(jets); 00354 return; 00355 } 00356 00357 // check the effect of the first selector 00358 vector<const PseudoJet *> s1_jets = jets; 00359 _s1.worker()->terminator(s1_jets); 00360 00361 // apply the second 00362 _s2.worker()->terminator(jets); 00363 00364 // terminate the jets that wiuld be terminated by _s1 00365 for (unsigned int i=0; i<jets.size(); i++){ 00366 if (! s1_jets[i]) jets[i] = NULL; 00367 } 00368 } 00369 00370 /// returns the rapidity range for which it may return "true" 00371 virtual void get_rapidity_extent(double & rapmin, double & rapmax) const { 00372 double s1min, s1max, s2min, s2max; 00373 _s1.get_rapidity_extent(s1min, s1max); 00374 _s2.get_rapidity_extent(s2min, s2max); 00375 rapmax = min(s1max, s2max); 00376 rapmin = max(s1min, s2min); 00377 } 00378 00379 /// returns a description of the worker 00380 virtual string description() const { 00381 ostringstream ostr; 00382 ostr << "(" << _s1.description() << " && " << _s2.description() << ")"; 00383 return ostr.str(); 00384 } 00385 }; 00386 00387 00388 // logical and between two selectors 00389 Selector operator&&(const Selector & s1, const Selector & s2) { 00390 return Selector(new SW_And(s1,s2)); 00391 } 00392 00393 00394 00395 //---------------------------------------------------------------------- 00396 /// helper for combining selectors with a logical or 00397 class SW_Or: public SW_BinaryOperator { 00398 public: 00399 /// ctor 00400 SW_Or(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2) {} 00401 00402 /// return a copy of this 00403 virtual SelectorWorker* copy(){ return new SW_Or(*this);} 00404 00405 /// returns true if a given object passes the selection criterium 00406 /// this has to be overloaded by derived workers 00407 virtual bool pass(const PseudoJet & jet) const { 00408 // make sure that the "pass" can be applied on both selectors 00409 if (!applies_jet_by_jet()) 00410 throw Error("Cannot apply this selector worker to an individual jet"); 00411 00412 return _s1.pass(jet) || _s2.pass(jet); 00413 } 00414 00415 /// returns true if this can be applied jet by jet 00416 virtual bool applies_jet_by_jet() const { 00417 // watch out, even though it's the "OR" selector, to be applied jet 00418 // by jet, both the base selectors need to be jet-by-jet-applicable, 00419 // so the use of a && in the line below 00420 return _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet(); 00421 } 00422 00423 /// select the jets in the list that pass both selectors 00424 virtual void terminator(vector<const PseudoJet *> & jets) const { 00425 // if we can apply the selector jet-by-jet, call the base selector 00426 // that does exactly that 00427 if (applies_jet_by_jet()){ 00428 SelectorWorker::terminator(jets); 00429 return; 00430 } 00431 00432 // check the effect of the first selector 00433 vector<const PseudoJet *> s1_jets = jets; 00434 _s1.worker()->terminator(s1_jets); 00435 00436 // apply the second 00437 _s2.worker()->terminator(jets); 00438 00439 // resurrect any jet that has been terminated by the second one 00440 // and not by the first one 00441 for (unsigned int i=0; i<jets.size(); i++){ 00442 if (s1_jets[i]) jets[i] = s1_jets[i]; 00443 } 00444 } 00445 00446 /// returns a description of the worker 00447 virtual string description() const { 00448 ostringstream ostr; 00449 ostr << "(" << _s1.description() << " || " << _s2.description() << ")"; 00450 return ostr.str(); 00451 } 00452 00453 /// returns the rapidity range for which it may return "true" 00454 virtual void get_rapidity_extent(double & rapmin, double & rapmax) const { 00455 double s1min, s1max, s2min, s2max; 00456 _s1.get_rapidity_extent(s1min, s1max); 00457 _s2.get_rapidity_extent(s2min, s2max); 00458 rapmax = max(s1max, s2max); 00459 rapmin = min(s1min, s2min); 00460 } 00461 }; 00462 00463 00464 // logical or between two selectors 00465 Selector operator ||(const Selector & s1, const Selector & s2) { 00466 return Selector(new SW_Or(s1,s2)); 00467 } 00468 00469 //---------------------------------------------------------------------- 00470 /// helper for multiplying two selectors (in an operator-like way) 00471 class SW_Mult: public SW_And { 00472 public: 00473 /// ctor 00474 SW_Mult(const Selector & s1, const Selector & s2) : SW_And(s1,s2) {} 00475 00476 /// return a copy of this 00477 virtual SelectorWorker* copy(){ return new SW_Mult(*this);} 00478 00479 /// select the jets in the list that pass both selectors 00480 virtual void terminator(vector<const PseudoJet *> & jets) const { 00481 // if we can apply the selector jet-by-jet, call the base selector 00482 // that does exactly that 00483 if (applies_jet_by_jet()){ 00484 SelectorWorker::terminator(jets); 00485 return; 00486 } 00487 00488 // first apply _s2 00489 _s2.worker()->terminator(jets); 00490 00491 // then apply _s1 00492 _s1.worker()->terminator(jets); 00493 } 00494 00495 /// returns a description of the worker 00496 virtual string description() const { 00497 ostringstream ostr; 00498 ostr << "(" << _s1.description() << " * " << _s2.description() << ")"; 00499 return ostr.str(); 00500 } 00501 }; 00502 00503 00504 // logical and between two selectors 00505 Selector operator*(const Selector & s1, const Selector & s2) { 00506 return Selector(new SW_Mult(s1,s2)); 00507 } 00508 00509 00510 //---------------------------------------------------------------------- 00511 // selector and workers for kinematic cuts 00512 //---------------------------------------------------------------------- 00513 00514 //---------------------------------------------------------------------- 00515 // a series of basic classes that allow easy implementations of 00516 // min, max and ranges on a quantity-to-be-defined 00517 00518 // generic holder for a quantity 00519 class QuantityBase{ 00520 public: 00521 QuantityBase(double q) : _q(q){} 00522 virtual ~QuantityBase(){} 00523 virtual double operator()(const PseudoJet & jet ) const =0; 00524 virtual string description() const =0; 00525 virtual bool is_geometric() const { return false;} 00526 virtual double comparison_value() const {return _q;} 00527 virtual double description_value() const {return comparison_value();} 00528 protected: 00529 double _q; 00530 }; 00531 00532 // generic holder for a squared quantity 00533 class QuantitySquareBase : public QuantityBase{ 00534 public: 00535 QuantitySquareBase(double sqrtq) : QuantityBase(sqrtq*sqrtq), _sqrtq(sqrtq){} 00536 virtual double description_value() const {return _sqrtq;} 00537 protected: 00538 double _sqrtq; 00539 }; 00540 00541 // generic_quantity >= minimum 00542 template<typename QuantityType> 00543 class SW_QuantityMin : public SelectorWorker{ 00544 public: 00545 /// detfault ctor (initialises the pt cut) 00546 SW_QuantityMin(double qmin) : _qmin(qmin) {} 00547 00548 /// returns true is the given object passes the selection pt cut 00549 virtual bool pass(const PseudoJet & jet) const {return _qmin(jet) >= _qmin.comparison_value();} 00550 00551 /// returns a description of the worker 00552 virtual string description() const { 00553 ostringstream ostr; 00554 ostr << _qmin.description() << " >= " << _qmin.description_value(); 00555 return ostr.str(); 00556 } 00557 00558 virtual bool is_geometric() const { return _qmin.is_geometric();} 00559 00560 protected: 00561 QuantityType _qmin; ///< the cut 00562 }; 00563 00564 00565 // generic_quantity <= maximum 00566 template<typename QuantityType> 00567 class SW_QuantityMax : public SelectorWorker { 00568 public: 00569 /// detfault ctor (initialises the pt cut) 00570 SW_QuantityMax(double qmax) : _qmax(qmax) {} 00571 00572 /// returns true is the given object passes the selection pt cut 00573 virtual bool pass(const PseudoJet & jet) const {return _qmax(jet) <= _qmax.comparison_value();} 00574 00575 /// returns a description of the worker 00576 virtual string description() const { 00577 ostringstream ostr; 00578 ostr << _qmax.description() << " <= " << _qmax.description_value(); 00579 return ostr.str(); 00580 } 00581 00582 virtual bool is_geometric() const { return _qmax.is_geometric();} 00583 00584 protected: 00585 QuantityType _qmax; ///< the cut 00586 }; 00587 00588 00589 // generic quantity in [minimum:maximum] 00590 template<typename QuantityType> 00591 class SW_QuantityRange : public SelectorWorker { 00592 public: 00593 /// detfault ctor (initialises the pt cut) 00594 SW_QuantityRange(double qmin, double qmax) : _qmin(qmin), _qmax(qmax) {} 00595 00596 /// returns true is the given object passes the selection pt cut 00597 virtual bool pass(const PseudoJet & jet) const { 00598 double q = _qmin(jet); // we could identically use _qmax 00599 return (q >= _qmin.comparison_value()) && (q <= _qmax.comparison_value()); 00600 } 00601 00602 /// returns a description of the worker 00603 virtual string description() const { 00604 ostringstream ostr; 00605 ostr << _qmin.description_value() << " <= " << _qmin.description() << " <= " << _qmax.description_value(); 00606 return ostr.str(); 00607 } 00608 00609 virtual bool is_geometric() const { return _qmin.is_geometric();} 00610 00611 protected: 00612 QuantityType _qmin; // the lower cut 00613 QuantityType _qmax; // the upper cut 00614 }; 00615 00616 00617 //---------------------------------------------------------------------- 00618 /// helper class for selecting on pt 00619 class QuantityPt2 : public QuantitySquareBase{ 00620 public: 00621 QuantityPt2(double pt) : QuantitySquareBase(pt){} 00622 virtual double operator()(const PseudoJet & jet ) const { return jet.perp2();} 00623 virtual string description() const {return "pt";} 00624 }; 00625 00626 // returns a selector for a minimum pt 00627 Selector SelectorPtMin(double ptmin) { 00628 return Selector(new SW_QuantityMin<QuantityPt2>(ptmin)); 00629 } 00630 00631 // returns a selector for a maximum pt 00632 Selector SelectorPtMax(double ptmax) { 00633 return Selector(new SW_QuantityMax<QuantityPt2>(ptmax)); 00634 } 00635 00636 // returns a selector for a pt range 00637 Selector SelectorPtRange(double ptmin, double ptmax) { 00638 return Selector(new SW_QuantityRange<QuantityPt2>(ptmin, ptmax)); 00639 } 00640 00641 00642 //---------------------------------------------------------------------- 00643 /// helper class for selecting on transverse energy 00644 class QuantityEt2 : public QuantitySquareBase{ 00645 public: 00646 QuantityEt2(double Et) : QuantitySquareBase(Et){} 00647 virtual double operator()(const PseudoJet & jet ) const { return jet.Et2();} 00648 virtual string description() const {return "Et";} 00649 }; 00650 00651 // returns a selector for a minimum Et 00652 Selector SelectorEtMin(double Etmin) { 00653 return Selector(new SW_QuantityMin<QuantityEt2>(Etmin)); 00654 } 00655 00656 // returns a selector for a maximum Et 00657 Selector SelectorEtMax(double Etmax) { 00658 return Selector(new SW_QuantityMax<QuantityEt2>(Etmax)); 00659 } 00660 00661 // returns a selector for a Et range 00662 Selector SelectorEtRange(double Etmin, double Etmax) { 00663 return Selector(new SW_QuantityRange<QuantityEt2>(Etmin, Etmax)); 00664 } 00665 00666 00667 //---------------------------------------------------------------------- 00668 /// helper class for selecting on energy 00669 class QuantityE : public QuantityBase{ 00670 public: 00671 QuantityE(double E) : QuantityBase(E){} 00672 virtual double operator()(const PseudoJet & jet ) const { return jet.E();} 00673 virtual string description() const {return "E";} 00674 }; 00675 00676 // returns a selector for a minimum E 00677 Selector SelectorEMin(double Emin) { 00678 return Selector(new SW_QuantityMin<QuantityE>(Emin)); 00679 } 00680 00681 // returns a selector for a maximum E 00682 Selector SelectorEMax(double Emax) { 00683 return Selector(new SW_QuantityMax<QuantityE>(Emax)); 00684 } 00685 00686 // returns a selector for a E range 00687 Selector SelectorERange(double Emin, double Emax) { 00688 return Selector(new SW_QuantityRange<QuantityE>(Emin, Emax)); 00689 } 00690 00691 00692 //---------------------------------------------------------------------- 00693 /// helper class for selecting on mass 00694 class QuantityM2 : public QuantitySquareBase{ 00695 public: 00696 QuantityM2(double m) : QuantitySquareBase(m){} 00697 virtual double operator()(const PseudoJet & jet ) const { return jet.m2();} 00698 virtual string description() const {return "mass";} 00699 }; 00700 00701 // returns a selector for a minimum mass 00702 Selector SelectorMassMin(double mmin) { 00703 return Selector(new SW_QuantityMin<QuantityM2>(mmin)); 00704 } 00705 00706 // returns a selector for a maximum mass 00707 Selector SelectorMassMax(double mmax) { 00708 return Selector(new SW_QuantityMax<QuantityM2>(mmax)); 00709 } 00710 00711 // returns a selector for a mass range 00712 Selector SelectorMassRange(double mmin, double mmax) { 00713 return Selector(new SW_QuantityRange<QuantityM2>(mmin, mmax)); 00714 } 00715 00716 00717 00718 //---------------------------------------------------------------------- 00719 /// helper for selecting on rapidities: quantity 00720 class QuantityRap : public QuantityBase{ 00721 public: 00722 QuantityRap(double rap) : QuantityBase(rap){} 00723 virtual double operator()(const PseudoJet & jet ) const { return jet.rap();} 00724 virtual string description() const {return "rap";} 00725 virtual bool is_geometric() const { return true;} 00726 }; 00727 00728 00729 /// helper for selecting on rapidities: min 00730 class SW_RapMin : public SW_QuantityMin<QuantityRap>{ 00731 public: 00732 SW_RapMin(double rapmin) : SW_QuantityMin<QuantityRap>(rapmin){} 00733 virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{ 00734 rapmax = std::numeric_limits<double>::max(); 00735 rapmin = _qmin.comparison_value(); 00736 } 00737 }; 00738 00739 /// helper for selecting on rapidities: max 00740 class SW_RapMax : public SW_QuantityMax<QuantityRap>{ 00741 public: 00742 SW_RapMax(double rapmax) : SW_QuantityMax<QuantityRap>(rapmax){} 00743 virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{ 00744 rapmax = _qmax.comparison_value(); 00745 rapmin = -std::numeric_limits<double>::max(); 00746 } 00747 }; 00748 00749 /// helper for selecting on rapidities: range 00750 class SW_RapRange : public SW_QuantityRange<QuantityRap>{ 00751 public: 00752 SW_RapRange(double rapmin, double rapmax) : SW_QuantityRange<QuantityRap>(rapmin, rapmax){ 00753 assert(rapmin<=rapmax); 00754 } 00755 virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{ 00756 rapmax = _qmax.comparison_value(); 00757 rapmin = _qmin.comparison_value(); 00758 } 00759 virtual bool has_known_area() const { return true;} ///< the area is analytically known 00760 virtual double known_area() const { 00761 return twopi * (_qmax.comparison_value()-_qmin.comparison_value()); 00762 } 00763 }; 00764 00765 // returns a selector for a minimum rapidity 00766 Selector SelectorRapMin(double rapmin) { 00767 return Selector(new SW_RapMin(rapmin)); 00768 } 00769 00770 // returns a selector for a maximum rapidity 00771 Selector SelectorRapMax(double rapmax) { 00772 return Selector(new SW_RapMax(rapmax)); 00773 } 00774 00775 // returns a selector for a rapidity range 00776 Selector SelectorRapRange(double rapmin, double rapmax) { 00777 return Selector(new SW_RapRange(rapmin, rapmax)); 00778 } 00779 00780 00781 //---------------------------------------------------------------------- 00782 /// helper for selecting on |rapidities| 00783 class QuantityAbsRap : public QuantityBase{ 00784 public: 00785 QuantityAbsRap(double absrap) : QuantityBase(absrap){} 00786 virtual double operator()(const PseudoJet & jet ) const { return abs(jet.rap());} 00787 virtual string description() const {return "|rap|";} 00788 virtual bool is_geometric() const { return true;} 00789 }; 00790 00791 00792 /// helper for selecting on |rapidities|: max 00793 class SW_AbsRapMax : public SW_QuantityMax<QuantityAbsRap>{ 00794 public: 00795 SW_AbsRapMax(double absrapmax) : SW_QuantityMax<QuantityAbsRap>(absrapmax){} 00796 virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{ 00797 rapmax = _qmax.comparison_value(); 00798 rapmin = -_qmax.comparison_value(); 00799 } 00800 virtual bool has_known_area() const { return true;} ///< the area is analytically known 00801 virtual double known_area() const { 00802 return twopi * 2 * _qmax.comparison_value(); 00803 } 00804 }; 00805 00806 /// helper for selecting on |rapidities|: max 00807 class SW_AbsRapRange : public SW_QuantityRange<QuantityAbsRap>{ 00808 public: 00809 SW_AbsRapRange(double absrapmin, double absrapmax) : SW_QuantityRange<QuantityAbsRap>(absrapmin, absrapmax){} 00810 virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{ 00811 rapmax = _qmax.comparison_value(); 00812 rapmin = -_qmax.comparison_value(); 00813 } 00814 virtual bool has_known_area() const { return true;} ///< the area is analytically known 00815 virtual double known_area() const { 00816 return twopi * 2 * (_qmax.comparison_value()-max(_qmin.comparison_value(),0.0)); // this should handle properly absrapmin<0 00817 } 00818 }; 00819 00820 // returns a selector for a minimum |rapidity| 00821 Selector SelectorAbsRapMin(double absrapmin) { 00822 return Selector(new SW_QuantityMin<QuantityAbsRap>(absrapmin)); 00823 } 00824 00825 // returns a selector for a maximum |rapidity| 00826 Selector SelectorAbsRapMax(double absrapmax) { 00827 return Selector(new SW_AbsRapMax(absrapmax)); 00828 } 00829 00830 // returns a selector for a |rapidity| range 00831 Selector SelectorAbsRapRange(double rapmin, double rapmax) { 00832 return Selector(new SW_AbsRapRange(rapmin, rapmax)); 00833 } 00834 00835 00836 //---------------------------------------------------------------------- 00837 /// helper for selecting on pseudo-rapidities 00838 class QuantityEta : public QuantityBase{ 00839 public: 00840 QuantityEta(double eta) : QuantityBase(eta){} 00841 virtual double operator()(const PseudoJet & jet ) const { return jet.eta();} 00842 virtual string description() const {return "eta";} 00843 // virtual bool is_geometric() const { return true;} // not strictly only y and phi-dependent 00844 }; 00845 00846 // returns a selector for a pseudo-minimum rapidity 00847 Selector SelectorEtaMin(double etamin) { 00848 return Selector(new SW_QuantityMin<QuantityEta>(etamin)); 00849 } 00850 00851 // returns a selector for a pseudo-maximum rapidity 00852 Selector SelectorEtaMax(double etamax) { 00853 return Selector(new SW_QuantityMax<QuantityEta>(etamax)); 00854 } 00855 00856 // returns a selector for a pseudo-rapidity range 00857 Selector SelectorEtaRange(double etamin, double etamax) { 00858 return Selector(new SW_QuantityRange<QuantityEta>(etamin, etamax)); 00859 } 00860 00861 00862 //---------------------------------------------------------------------- 00863 /// helper for selecting on |pseudo-rapidities| 00864 class QuantityAbsEta : public QuantityBase{ 00865 public: 00866 QuantityAbsEta(double abseta) : QuantityBase(abseta){} 00867 virtual double operator()(const PseudoJet & jet ) const { return abs(jet.eta());} 00868 virtual string description() const {return "|eta|";} 00869 virtual bool is_geometric() const { return true;} 00870 }; 00871 00872 // returns a selector for a minimum |pseudo-rapidity| 00873 Selector SelectorAbsEtaMin(double absetamin) { 00874 return Selector(new SW_QuantityMin<QuantityAbsEta>(absetamin)); 00875 } 00876 00877 // returns a selector for a maximum |pseudo-rapidity| 00878 Selector SelectorAbsEtaMax(double absetamax) { 00879 return Selector(new SW_QuantityMax<QuantityAbsEta>(absetamax)); 00880 } 00881 00882 // returns a selector for a |pseudo-rapidity| range 00883 Selector SelectorAbsEtaRange(double absetamin, double absetamax) { 00884 return Selector(new SW_QuantityRange<QuantityAbsEta>(absetamin, absetamax)); 00885 } 00886 00887 00888 //---------------------------------------------------------------------- 00889 /// helper for selecting on azimuthal angle 00890 /// 00891 /// Note that the bounds have to be specified as min<max 00892 /// phimin has to be > -2pi 00893 /// phimax has to be < 4pi 00894 class SW_PhiRange : public SelectorWorker { 00895 public: 00896 /// detfault ctor (initialises the pt cut) 00897 SW_PhiRange(double phimin, double phimax) : _phimin(phimin), _phimax(phimax){ 00898 assert(_phimin<_phimax); 00899 assert(_phimin>-twopi); 00900 assert(_phimax<2*twopi); 00901 00902 _phispan = _phimax - _phimin; 00903 } 00904 00905 /// returns true is the given object passes the selection pt cut 00906 virtual bool pass(const PseudoJet & jet) const { 00907 double dphi=jet.phi()-_phimin; 00908 if (dphi >= twopi) dphi -= twopi; 00909 if (dphi < 0) dphi += twopi; 00910 return (dphi <= _phispan); 00911 } 00912 00913 /// returns a description of the worker 00914 virtual string description() const { 00915 ostringstream ostr; 00916 ostr << _phimin << " <= phi <= " << _phimax; 00917 return ostr.str(); 00918 } 00919 00920 virtual bool is_geometric() const { return true;} 00921 00922 protected: 00923 double _phimin; // the lower cut 00924 double _phimax; // the upper cut 00925 double _phispan; // the span of the range 00926 }; 00927 00928 00929 // returns a selector for a phi range 00930 Selector SelectorPhiRange(double phimin, double phimax) { 00931 return Selector(new SW_PhiRange(phimin, phimax)); 00932 } 00933 00934 //---------------------------------------------------------------------- 00935 /// helper for selecting on both rapidity and azimuthal angle 00936 class SW_RapPhiRange : public SW_And{ 00937 public: 00938 SW_RapPhiRange(double rapmin, double rapmax, double phimin, double phimax) 00939 : SW_And(SelectorRapRange(rapmin, rapmax), SelectorPhiRange(phimin, phimax)){ 00940 _known_area = ((phimax-phimin > twopi) ? twopi : phimax-phimin) * (rapmax-rapmin); 00941 } 00942 00943 /// if it has a computable area, return it 00944 virtual double known_area() const{ 00945 return _known_area; 00946 } 00947 00948 protected: 00949 double _known_area; 00950 }; 00951 00952 Selector SelectorRapPhiRange(double rapmin, double rapmax, double phimin, double phimax) { 00953 return Selector(new SW_RapPhiRange(rapmin, rapmax, phimin, phimax)); 00954 } 00955 00956 00957 //---------------------------------------------------------------------- 00958 /// helper for selecting the n hardest jets 00959 class SW_NHardest : public SelectorWorker { 00960 public: 00961 /// ctor with specification of the number of objects to keep 00962 SW_NHardest(unsigned int n) : _n(n) {}; 00963 00964 /// pass makes no sense here normally the parent selector will throw 00965 /// an error but for internal use in the SW, we'll throw one from 00966 /// here by security 00967 virtual bool pass(const PseudoJet & jet) const { 00968 if (!applies_jet_by_jet()) 00969 throw Error("Cannot apply this selector worker to an individual jet"); 00970 return false; 00971 } 00972 00973 /// For each jet that does not pass the cuts, this routine sets the 00974 /// pointer to 0. 00975 virtual void terminator(vector<const PseudoJet *> & jets) const { 00976 // nothing to do if the size is too small 00977 if (jets.size() < _n) return; 00978 00979 // do we want to first chech if things are already ordered before 00980 // going through the ordering process? 00981 00982 vector<double> minus_pt2(jets.size()); 00983 vector<unsigned int> indices(jets.size()); 00984 00985 for (unsigned int i=0; i<jets.size(); i++){ 00986 indices[i] = i; 00987 00988 // we need to make sure that the object has not already been 00989 // nullified. Note that if we have less than _n jets, this 00990 // whole n-hardest selection will not have any effect. 00991 minus_pt2[i] = jets[i] ? -jets[i]->perp2() : 0.0; 00992 } 00993 00994 IndexedSortHelper sort_helper(& minus_pt2); 00995 00996 partial_sort(indices.begin(), indices.begin()+_n, indices.end(), sort_helper); 00997 00998 for (unsigned int i=_n; i<jets.size(); i++) 00999 jets[indices[i]] = NULL; 01000 } 01001 01002 /// returns true if this can be applied jet by jet 01003 virtual bool applies_jet_by_jet() const {return false;} 01004 01005 /// returns a description of the worker 01006 virtual string description() const { 01007 ostringstream ostr; 01008 ostr << _n << " hardest"; 01009 return ostr.str(); 01010 } 01011 01012 protected: 01013 unsigned int _n; 01014 }; 01015 01016 01017 // returns a selector for the n hardest jets 01018 Selector SelectorNHardest(unsigned int n) { 01019 return Selector(new SW_NHardest(n)); 01020 } 01021 01022 01023 01024 //---------------------------------------------------------------------- 01025 // selector and workers for geometric ranges 01026 //---------------------------------------------------------------------- 01027 01028 //---------------------------------------------------------------------- 01029 /// a generic class for objects that contain a position 01030 class SW_WithReference : public SelectorWorker{ 01031 public: 01032 /// ctor 01033 SW_WithReference() : _is_initialised(false){}; 01034 01035 /// returns true if the worker takes a reference jet 01036 virtual bool takes_reference() const { return true;} 01037 01038 /// sets the reference jet 01039 virtual void set_reference(const PseudoJet ¢re){ 01040 _is_initialised = true; 01041 _reference = centre; 01042 } 01043 01044 protected: 01045 PseudoJet _reference; 01046 bool _is_initialised; 01047 }; 01048 01049 //---------------------------------------------------------------------- 01050 /// helper for selecting on objects within a distance 'radius' of a reference 01051 class SW_Circle : public SW_WithReference { 01052 public: 01053 SW_Circle(const double &radius) : _radius2(radius*radius) {} 01054 01055 /// return a copy of the current object 01056 virtual SelectorWorker* copy(){ return new SW_Circle(*this);} 01057 01058 /// returns true if a given object passes the selection criterium 01059 /// this has to be overloaded by derived workers 01060 virtual bool pass(const PseudoJet & jet) const { 01061 // make sure the centre is initialised 01062 if (! _is_initialised) 01063 throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)"); 01064 01065 return jet.squared_distance(_reference) <= _radius2; 01066 } 01067 01068 /// returns a description of the worker 01069 virtual string description() const { 01070 ostringstream ostr; 01071 ostr << "distance from the centre <= " << sqrt(_radius2); 01072 return ostr.str(); 01073 } 01074 01075 /// returns the rapidity range for which it may return "true" 01076 virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{ 01077 // make sure the centre is initialised 01078 if (! _is_initialised) 01079 throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)"); 01080 01081 rapmax = _reference.rap()+sqrt(_radius2); 01082 rapmin = _reference.rap()-sqrt(_radius2); 01083 } 01084 01085 virtual bool is_geometric() const { return true;} ///< implies a finite area 01086 virtual bool has_finite_area() const { return true;} ///< regardless of the reference 01087 virtual bool has_known_area() const { return true;} ///< the area is analytically known 01088 virtual double known_area() const { 01089 return pi * _radius2; 01090 } 01091 01092 protected: 01093 double _radius2; 01094 }; 01095 01096 01097 // select on objets within a distance 'radius' of a variable location 01098 Selector SelectorCircle(const double & radius) { 01099 return Selector(new SW_Circle(radius)); 01100 } 01101 01102 01103 //---------------------------------------------------------------------- 01104 /// helper for selecting on objects with a distance to a reference 01105 /// betwene 'radius_in' and 'radius_out' 01106 class SW_Doughnut : public SW_WithReference { 01107 public: 01108 SW_Doughnut(const double &radius_in, const double &radius_out) 01109 : _radius_in2(radius_in*radius_in), _radius_out2(radius_out*radius_out) {} 01110 01111 /// return a copy of the current object 01112 virtual SelectorWorker* copy(){ return new SW_Doughnut(*this);} 01113 01114 /// returns true if a given object passes the selection criterium 01115 /// this has to be overloaded by derived workers 01116 virtual bool pass(const PseudoJet & jet) const { 01117 // make sure the centre is initialised 01118 if (! _is_initialised) 01119 throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)"); 01120 01121 double distance2 = jet.squared_distance(_reference); 01122 01123 return (distance2 <= _radius_out2) && (distance2 >= _radius_in2); 01124 } 01125 01126 /// returns a description of the worker 01127 virtual string description() const { 01128 ostringstream ostr; 01129 ostr << sqrt(_radius_in2) << " <= distance from the centre <= " << sqrt(_radius_out2); 01130 return ostr.str(); 01131 } 01132 01133 /// returns the rapidity range for which it may return "true" 01134 virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{ 01135 // make sure the centre is initialised 01136 if (! _is_initialised) 01137 throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)"); 01138 01139 rapmax = _reference.rap()+sqrt(_radius_out2); 01140 rapmin = _reference.rap()-sqrt(_radius_out2); 01141 } 01142 01143 virtual bool is_geometric() const { return true;} ///< implies a finite area 01144 virtual bool has_finite_area() const { return true;} ///< regardless of the reference 01145 virtual bool has_known_area() const { return true;} ///< the area is analytically known 01146 virtual double known_area() const { 01147 return pi * (_radius_out2-_radius_in2); 01148 } 01149 01150 protected: 01151 double _radius_in2, _radius_out2; 01152 }; 01153 01154 01155 01156 // select on objets with distance from the centre is between 'radius_in' and 'radius_out' 01157 Selector SelectorDoughnut(const double & radius_in, const double & radius_out) { 01158 return Selector(new SW_Doughnut(radius_in, radius_out)); 01159 } 01160 01161 01162 //---------------------------------------------------------------------- 01163 /// helper for selecting on objects with rapidity within a distance 'delta' of a reference 01164 class SW_Strip : public SW_WithReference { 01165 public: 01166 SW_Strip(const double &delta) : _delta(delta) {} 01167 01168 /// return a copy of the current object 01169 virtual SelectorWorker* copy(){ return new SW_Strip(*this);} 01170 01171 /// returns true if a given object passes the selection criterium 01172 /// this has to be overloaded by derived workers 01173 virtual bool pass(const PseudoJet & jet) const { 01174 // make sure the centre is initialised 01175 if (! _is_initialised) 01176 throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)"); 01177 01178 return abs(jet.rap()-_reference.rap()) <= _delta; 01179 } 01180 01181 /// returns a description of the worker 01182 virtual string description() const { 01183 ostringstream ostr; 01184 ostr << "|rap - rap_reference| <= " << _delta; 01185 return ostr.str(); 01186 } 01187 01188 /// returns the rapidity range for which it may return "true" 01189 virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{ 01190 // make sure the centre is initialised 01191 if (! _is_initialised) 01192 throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)"); 01193 01194 rapmax = _reference.rap()+_delta; 01195 rapmin = _reference.rap()-_delta; 01196 } 01197 01198 virtual bool is_geometric() const { return true;} ///< implies a finite area 01199 virtual bool has_finite_area() const { return true;} ///< regardless of the reference 01200 virtual bool has_known_area() const { return true;} ///< the area is analytically known 01201 virtual double known_area() const { 01202 return twopi * 2 * _delta; 01203 } 01204 01205 protected: 01206 double _delta; 01207 }; 01208 01209 01210 // select on objets within a distance 'radius' of a variable location 01211 Selector SelectorStrip(const double & half_width) { 01212 return Selector(new SW_Strip(half_width)); 01213 } 01214 01215 01216 //---------------------------------------------------------------------- 01217 /// helper for selecting on objects with rapidity within a distance 01218 /// 'delta_rap' of a reference and phi within a distanve delta_phi of 01219 /// a reference 01220 class SW_Rectangle : public SW_WithReference { 01221 public: 01222 SW_Rectangle(const double &delta_rap, const double &delta_phi) 01223 : _delta_rap(delta_rap), _delta_phi(delta_phi) {} 01224 01225 /// return a copy of the current object 01226 virtual SelectorWorker* copy(){ return new SW_Rectangle(*this);} 01227 01228 /// returns true if a given object passes the selection criterium 01229 /// this has to be overloaded by derived workers 01230 virtual bool pass(const PseudoJet & jet) const { 01231 // make sure the centre is initialised 01232 if (! _is_initialised) 01233 throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)"); 01234 01235 return (abs(jet.rap()-_reference.rap()) <= _delta_rap) && (abs(jet.delta_phi_to(_reference)) <= _delta_phi); 01236 } 01237 01238 /// returns a description of the worker 01239 virtual string description() const { 01240 ostringstream ostr; 01241 ostr << "|rap - rap_reference| <= " << _delta_rap << " && |phi - phi_reference| <= " << _delta_phi ; 01242 return ostr.str(); 01243 } 01244 01245 /// returns the rapidity range for which it may return "true" 01246 virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{ 01247 // make sure the centre is initialised 01248 if (! _is_initialised) 01249 throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)"); 01250 01251 rapmax = _reference.rap()+_delta_rap; 01252 rapmin = _reference.rap()-_delta_rap; 01253 } 01254 01255 virtual bool is_geometric() const { return true;} ///< implies a finite area 01256 virtual bool has_finite_area() const { return true;} ///< regardless of the reference 01257 virtual bool has_known_area() const { return true;} ///< the area is analytically known 01258 virtual double known_area() const { 01259 return 4 * _delta_rap * _delta_phi; 01260 } 01261 01262 protected: 01263 double _delta_rap, _delta_phi; 01264 }; 01265 01266 01267 // select on objets within a distance 'radius' of a variable location 01268 Selector SelectorRectangle(const double & half_rap_width, const double & half_phi_width) { 01269 return Selector(new SW_Rectangle(half_rap_width, half_phi_width)); 01270 } 01271 01272 01273 //---------------------------------------------------------------------- 01274 /// helper for selecting the jets that carry at least a given fraction 01275 /// of the reference jet 01276 class SW_PtFractionMin : public SW_WithReference { 01277 public: 01278 /// ctor with specification of the number of objects to keep 01279 SW_PtFractionMin(double fraction) : _fraction2(fraction*fraction){} 01280 01281 /// return a copy of the current object 01282 virtual SelectorWorker* copy(){ return new SW_PtFractionMin(*this);} 01283 01284 /// return true if the jet carries a large enough fraction of the reference. 01285 /// Throw an error if the reference is not initialised. 01286 virtual bool pass(const PseudoJet & jet) const { 01287 // make sure the centre is initialised 01288 if (! _is_initialised) 01289 throw Error("To use a SelectorPtFractionMin (or any selector that requires a reference), you first have to call set_reference(...)"); 01290 01291 // otherwise, just call that method on the jet 01292 return (jet.perp2() >= _fraction2*_reference.perp2()); 01293 } 01294 01295 /// returns a description of the worker 01296 virtual string description() const { 01297 ostringstream ostr; 01298 ostr << "pt >= " << sqrt(_fraction2) << "* pt_ref"; 01299 return ostr.str(); 01300 } 01301 01302 protected: 01303 double _fraction2; 01304 }; 01305 01306 01307 // select objects that carry at least a fraction "fraction" of the reference jet 01308 // (Note that this selectir takes a reference) 01309 Selector SelectorPtFractionMin(double fraction){ 01310 return Selector(new SW_PtFractionMin(fraction)); 01311 } 01312 01313 01314 //---------------------------------------------------------------------- 01315 // additional (mostly helper) selectors 01316 //---------------------------------------------------------------------- 01317 01318 //---------------------------------------------------------------------- 01319 /// helper for selecting the pure ghost 01320 class SW_IsPureGhost : public SelectorWorker { 01321 public: 01322 /// ctor with specification of the number of objects to keep 01323 SW_IsPureGhost(){} 01324 01325 /// return true if the jet is a pure-ghost jet 01326 virtual bool pass(const PseudoJet & jet) const { 01327 // if the jet has no area support then it's certainly not a ghost 01328 if (!jet.has_area()) return false; 01329 01330 // otherwise, just call that method on the jet 01331 return jet.is_pure_ghost(); 01332 } 01333 01334 /// returns a description of the worker 01335 virtual string description() const { return "pure ghost";} 01336 }; 01337 01338 01339 // select objects that are (or are only made of) ghosts 01340 Selector SelectorIsPureGhost(){ 01341 return Selector(new SW_IsPureGhost()); 01342 } 01343 01344 01345 //---------------------------------------------------------------------- 01346 // Selector and workers for obtaining a Selector from an old 01347 // RangeDefinition 01348 // 01349 // This is mostly intended for backward compatibility and is likely to 01350 // be removed in a future major release of FastJet 01351 //---------------------------------------------------------------------- 01352 01353 //---------------------------------------------------------------------- 01354 /// helper for selecting on both rapidity and azimuthal angle 01355 class SW_RangeDefinition : public SelectorWorker{ 01356 public: 01357 /// ctor from a RangeDefinition 01358 SW_RangeDefinition(const RangeDefinition &range) : _range(&range){} 01359 01360 /// transfer the selection creterium to the underlying RangeDefinition 01361 virtual bool pass(const PseudoJet & jet) const { 01362 return _range->is_in_range(jet); 01363 } 01364 01365 /// returns a description of the worker 01366 virtual string description() const { 01367 return _range->description(); 01368 } 01369 01370 /// returns the rapidity range for which it may return "true" 01371 virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{ 01372 _range->get_rap_limits(rapmin, rapmax); 01373 } 01374 01375 /// check if it has a finite area 01376 virtual bool is_geometric() const { return true;} 01377 01378 /// check if it has an analytically computable area 01379 virtual bool has_known_area() const { return true;} 01380 01381 /// if it has a computable area, return it 01382 virtual double known_area() const{ 01383 return _range->area(); 01384 } 01385 01386 protected: 01387 const RangeDefinition *_range; 01388 }; 01389 01390 01391 // ctor from a RangeDefinition 01392 //---------------------------------------------------------------------- 01393 // 01394 // This is provided for backward compatibility and will be removed in 01395 // a future major release of FastJet 01396 Selector::Selector(const RangeDefinition &range) { 01397 _worker.reset(new SW_RangeDefinition(range)); 01398 } 01399 01400 01401 // operators applying directly on a Selector 01402 //---------------------------------------------------------------------- 01403 01404 // operator &= 01405 // For 2 Selectors a and b, a &= b is eauivalent to a = a & b; 01406 Selector & Selector::operator &=(const Selector & b){ 01407 _worker.reset(new SW_And(*this, b)); 01408 return *this; 01409 } 01410 01411 // operator &= 01412 // For 2 Selectors a and b, a &= b is eauivalent to a = a & b; 01413 Selector & Selector::operator |=(const Selector & b){ 01414 _worker.reset(new SW_Or(*this, b)); 01415 return *this; 01416 } 01417 01418 FASTJET_END_NAMESPACE // defined in fastjet/internal/base.hh