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