Selector.cc

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