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