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