Selector.cc

00001 #include <sstream>
00002 #include <algorithm>
00003 #include "fastjet/tools/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 // selector and workers for operators
00063 //----------------------------------------------------------------------
00064 
00065 //----------------------------------------------------------------------
00067 class SW_Not : public SelectorWorker {
00068 public:
00070   SW_Not(const Selector & s) : _s(s) {}
00071 
00073   virtual SelectorWorker* copy(){ return new SW_Not(*this);}
00074 
00077   virtual bool pass(const PseudoJet & jet) const {
00078     // make sure that the "pass" can be applied on both selectors
00079     if (!applies_jet_by_jet())
00080       throw Error("Cannot apply this selector worker to an individual jet");
00081     
00082     return ! _s.pass(jet);
00083   } 
00084 
00086   virtual bool applies_jet_by_jet() const {return _s.applies_jet_by_jet();}
00087 
00089   virtual void terminator(vector<const PseudoJet *> & jets) const {
00090     // if we can apply the selector jet-by-jet, call the base selector
00091     // that does exactly that
00092     if (applies_jet_by_jet()){
00093       SelectorWorker::terminator(jets);
00094       return;
00095     }
00096 
00097     // check the effect of the selector we want to negate
00098     vector<const PseudoJet *> s_jets = jets;
00099     _s.worker()->terminator(s_jets);
00100 
00101     // now apply the negation: all the jets that pass the base
00102     // selector (i.e. are not NULL) have to be set to NULL
00103     for (unsigned int i=0; i<s_jets.size(); i++){
00104       if (s_jets[i]) jets[i] = NULL;
00105     }
00106   }
00107 
00109   virtual string description() const {
00110     ostringstream ostr;
00111     ostr << "!(" << _s.description() << ")";
00112     return ostr.str();
00113   }
00114 
00116   virtual bool is_relocatable() const { return _s.is_relocatable();}
00117 
00118 protected:
00119   Selector _s;
00120 };
00121 
00122 
00123 // logical not applied on a selector
00124 Selector operator!(const Selector & s) {
00125   return Selector(new SW_Not(s));
00126 }
00127 
00128 
00129 //----------------------------------------------------------------------
00131 class SW_BinaryOperator: public SelectorWorker {
00132 public:
00134   SW_BinaryOperator(const Selector & s1, const Selector & s2) : _s1(s1), _s2(s2) {
00135     // stores info for more efficient access to the selector's properties
00136 
00137     // we can apply jet by jet only if this is the case for both sub-selectors
00138     _applies_jet_by_jet = _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
00139 
00140     // the selector is relocatable if any of the sub-selectors is
00141     _is_relocatable = _s1.is_relocatable() || _s2.is_relocatable();
00142 
00143     // we have a well-defined area provided the two objects have one
00144     _has_area = _s1.has_area() && _s2.has_area();
00145   }
00146 
00148   virtual bool applies_jet_by_jet() const {return _applies_jet_by_jet;}
00149 
00151   virtual bool is_relocatable() const{ 
00152     return _is_relocatable;
00153   }
00154 
00156   virtual void relocate(const PseudoJet &centre){
00157     _s1.relocate(centre);
00158     _s2.relocate(centre);
00159   }
00160 
00162   virtual bool has_area() const { return _has_area;} 
00163 
00164 protected:
00165   Selector _s1, _s2;
00166   bool _applies_jet_by_jet;
00167   bool _is_relocatable;
00168   bool _has_area;
00169 };
00170 
00171 
00172 
00173 //----------------------------------------------------------------------
00175 class SW_And: public SW_BinaryOperator {
00176 public:
00178   SW_And(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2){}
00179 
00181   virtual SelectorWorker* copy(){ return new SW_And(*this);}
00182 
00185   virtual bool pass(const PseudoJet & jet) const {
00186     // make sure that the "pass" can be applied on both selectors
00187     if (!applies_jet_by_jet())
00188       throw Error("Cannot apply this selector worker to an individual jet");
00189     
00190     return _s1.pass(jet) && _s2.pass(jet);
00191   }
00192 
00194   virtual void terminator(vector<const PseudoJet *> & jets) const {
00195     // if we can apply the selector jet-by-jet, call the base selector
00196     // that does exactly that
00197     if (applies_jet_by_jet()){
00198       SelectorWorker::terminator(jets);
00199       return;
00200     }
00201 
00202     // check the effect of the first selector
00203     vector<const PseudoJet *> s1_jets = jets;
00204     _s1.worker()->terminator(s1_jets);
00205 
00206     // apply the second
00207     _s2.worker()->terminator(jets);
00208 
00209     // terminate the jets that wiuld be terminated by _s1
00210     for (unsigned int i=0; i<jets.size(); i++){
00211       if (! s1_jets[i]) jets[i] = NULL;
00212     }
00213   }
00214 
00216   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
00217     double s1min, s1max, s2min, s2max;
00218     _s1.get_rapidity_extent(s1min, s1max);
00219     _s2.get_rapidity_extent(s2min, s2max);
00220     rapmax = min(s1max, s2max);
00221     rapmin = max(s1min, s2min);
00222   }
00223 
00225   virtual string description() const {
00226     ostringstream ostr;
00227     ostr << "(" << _s1.description() << " && " << _s2.description() << ")";
00228     return ostr.str();
00229   }
00230 };
00231 
00232 
00233 // logical and between two selectors
00234 Selector operator&&(const Selector & s1, const Selector & s2) {
00235   return Selector(new SW_And(s1,s2));
00236 }
00237 
00238 
00239 
00240 //----------------------------------------------------------------------
00242 class SW_Or: public SW_BinaryOperator {
00243 public:
00245   SW_Or(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2) {}
00246 
00248   virtual SelectorWorker* copy(){ return new SW_Or(*this);}
00249 
00252   virtual bool pass(const PseudoJet & jet) const {
00253     // make sure that the "pass" can be applied on both selectors
00254     if (!applies_jet_by_jet())
00255       throw Error("Cannot apply this selector worker to an individual jet");
00256     
00257     return _s1.pass(jet) || _s2.pass(jet);
00258   }
00259 
00261   virtual bool applies_jet_by_jet() const {
00262     // watch out, even though it's the "OR" selector, to be applied jet
00263     // by jet, both the base selectors need to be jet-by-jet-applicable,
00264     // so the use of a && in the line below
00265     return _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
00266   }
00267 
00269   virtual void terminator(vector<const PseudoJet *> & jets) const {
00270     // if we can apply the selector jet-by-jet, call the base selector
00271     // that does exactly that
00272     if (applies_jet_by_jet()){
00273       SelectorWorker::terminator(jets);
00274       return;
00275     }
00276 
00277     // check the effect of the first selector
00278     vector<const PseudoJet *> s1_jets = jets;
00279     _s1.worker()->terminator(s1_jets);
00280 
00281     // apply the second
00282     _s2.worker()->terminator(jets);
00283 
00284     // resurrect any jet that has been terminated by the second one
00285     // and not by the first one
00286     for (unsigned int i=0; i<jets.size(); i++){
00287       if (s1_jets[i]) jets[i] = s1_jets[i];
00288     }
00289   }
00290 
00292   virtual string description() const {
00293     ostringstream ostr;
00294     ostr << "(" << _s1.description() << " || " << _s2.description() << ")";
00295     return ostr.str();
00296   }
00297 
00299   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
00300     double s1min, s1max, s2min, s2max;
00301     _s1.get_rapidity_extent(s1min, s1max);
00302     _s2.get_rapidity_extent(s2min, s2max);
00303     rapmax = max(s1max, s2max);
00304     rapmin = min(s1min, s2min);
00305   }
00306 };
00307 
00308 
00309 // logical or between two selectors
00310 Selector operator ||(const Selector & s1, const Selector & s2) {
00311   return Selector(new SW_Or(s1,s2));
00312 }
00313 
00314 //----------------------------------------------------------------------
00316 class SW_Mult: public SW_And {
00317 public:
00319   SW_Mult(const Selector & s1, const Selector & s2) : SW_And(s1,s2) {}
00320 
00322   virtual SelectorWorker* copy(){ return new SW_Mult(*this);}
00323 
00325   virtual void terminator(vector<const PseudoJet *> & jets) const {
00326     // if we can apply the selector jet-by-jet, call the base selector
00327     // that does exactly that
00328     if (applies_jet_by_jet()){
00329       SelectorWorker::terminator(jets);
00330       return;
00331     }
00332 
00333     // first apply _s2
00334     _s2.worker()->terminator(jets);
00335 
00336     // then apply _s1
00337     _s1.worker()->terminator(jets);
00338   }
00339 
00341   virtual string description() const {
00342     ostringstream ostr;
00343     ostr << "(" << _s1.description() << " * " << _s2.description() << ")";
00344     return ostr.str();
00345   }
00346 };
00347 
00348 
00349 // logical and between two selectors
00350 Selector operator*(const Selector & s1, const Selector & s2) {
00351   return Selector(new SW_Mult(s1,s2));
00352 }
00353 
00354 
00355 //----------------------------------------------------------------------
00356 // selector and workers for kinematic cuts
00357 //----------------------------------------------------------------------
00358 
00359 //----------------------------------------------------------------------
00360 // a series of basic classes that allow easy implementations of
00361 // min, max and ranges on a quantity-to-be-defined
00362 
00363 // generic holder for a quantity
00364 class QuantityBase{
00365 public:
00366   QuantityBase(double q) : _q(q){}
00367   virtual double operator()(const PseudoJet & jet ) const =0;
00368   virtual string description() const =0;
00369   virtual double comparison_value() const {return _q;}
00370   virtual double description_value() const {return comparison_value();}
00371 protected:
00372   double _q;
00373 };  
00374 
00375 // generic holder for a squared quantity
00376 class QuantitySquareBase : public QuantityBase{
00377 public:
00378   QuantitySquareBase(double sqrtq) : QuantityBase(sqrtq*sqrtq), _sqrtq(sqrtq){}
00379   virtual double description_value() const {return _sqrtq;}
00380 protected:
00381   double _sqrtq;
00382 };  
00383 
00384 // generic_quantity >= minimum
00385 template<typename QuantityType>
00386 class SW_QuantityMin : public SelectorWorker{
00387 public:
00389   SW_QuantityMin(double qmin) : _qmin(qmin) {}
00390 
00392   virtual bool pass(const PseudoJet & jet) const {return _qmin(jet) >= _qmin.comparison_value();}
00393 
00395   virtual string description() const {
00396     ostringstream ostr;
00397     ostr << _qmin.description() << " >= " << _qmin.description_value();
00398     return ostr.str();
00399   }
00400 
00401 protected:
00402   QuantityType _qmin;     
00403 };
00404 
00405 
00406 // generic_quantity <= maximum
00407 template<typename QuantityType>
00408 class SW_QuantityMax : public SelectorWorker {
00409 public:
00411   SW_QuantityMax(double qmax) : _qmax(qmax) {}
00412 
00414   virtual bool pass(const PseudoJet & jet) const {return _qmax(jet) <= _qmax.comparison_value();}
00415 
00417   virtual string description() const {
00418     ostringstream ostr;
00419     ostr << _qmax.description() << " <= " << _qmax.description_value();
00420     return ostr.str();
00421   }
00422 
00423 protected:
00424   QuantityType _qmax;   
00425 };
00426 
00427 
00428 // generic quantity in [minimum:maximum]
00429 template<typename QuantityType>
00430 class SW_QuantityRange : public SelectorWorker {
00431 public:
00433   SW_QuantityRange(double qmin, double qmax) : _qmin(qmin), _qmax(qmax) {}
00434 
00436   virtual bool pass(const PseudoJet & jet) const {
00437     double q = _qmin(jet); // we could identically use _qmax
00438     return (q >= _qmin.comparison_value()) && (q <= _qmax.comparison_value());
00439   }
00440 
00442   virtual string description() const {
00443     ostringstream ostr;
00444     ostr << _qmin.description_value() << " <= " << _qmin.description() << " <= " << _qmax.description_value();
00445     return ostr.str();
00446   }
00447 
00448 protected:
00449   QuantityType _qmin;   // the lower cut 
00450   QuantityType _qmax;   // the upper cut
00451 };
00452 
00453 
00454 //----------------------------------------------------------------------
00456 class QuantityPt2 : public QuantitySquareBase{
00457 public:
00458   QuantityPt2(double pt) : QuantitySquareBase(pt){}
00459   virtual double operator()(const PseudoJet & jet ) const { return jet.perp2();}
00460   virtual string description() const {return "pt";}
00461 };  
00462 
00463 // returns a selector for a minimum pt
00464 Selector SelectorPtMin(double ptmin) {
00465   return Selector(new SW_QuantityMin<QuantityPt2>(ptmin));
00466 }
00467 
00468 // returns a selector for a maximum pt
00469 Selector SelectorPtMax(double ptmax) {
00470   return Selector(new SW_QuantityMax<QuantityPt2>(ptmax));
00471 }
00472 
00473 // returns a selector for a pt range
00474 Selector SelectorPtRange(double ptmin, double ptmax) {
00475   return Selector(new SW_QuantityRange<QuantityPt2>(ptmin, ptmax));
00476 }
00477 
00478 
00479 //----------------------------------------------------------------------
00481 class QuantityEt2 : public QuantitySquareBase{
00482 public:
00483   QuantityEt2(double Et) : QuantitySquareBase(Et){}
00484   virtual double operator()(const PseudoJet & jet ) const { return jet.Et2();}
00485   virtual string description() const {return "Et";}
00486 };  
00487 
00488 // returns a selector for a minimum Et
00489 Selector SelectorEtMin(double Etmin) {
00490   return Selector(new SW_QuantityMin<QuantityEt2>(Etmin*Etmin));
00491 }
00492 
00493 // returns a selector for a maximum Et
00494 Selector SelectorEtMax(double Etmax) {
00495   return Selector(new SW_QuantityMax<QuantityEt2>(Etmax*Etmax));
00496 }
00497 
00498 // returns a selector for a Et range
00499 Selector SelectorEtRange(double Etmin, double Etmax) {
00500   return Selector(new SW_QuantityRange<QuantityEt2>(Etmin*Etmin, Etmax*Etmax));
00501 }
00502 
00503 
00504 //----------------------------------------------------------------------
00506 class QuantityE : public QuantityBase{
00507 public:
00508   QuantityE(double E) : QuantityBase(E){}
00509   virtual double operator()(const PseudoJet & jet ) const { return jet.E();}
00510   virtual string description() const {return "E";}
00511 };  
00512 
00513 // returns a selector for a minimum E
00514 Selector SelectorEMin(double Emin) {
00515   return Selector(new SW_QuantityMin<QuantityE>(Emin));
00516 }
00517 
00518 // returns a selector for a maximum E
00519 Selector SelectorEMax(double Emax) {
00520   return Selector(new SW_QuantityMax<QuantityE>(Emax));
00521 }
00522 
00523 // returns a selector for a E range
00524 Selector SelectorERange(double Emin, double Emax) {
00525   return Selector(new SW_QuantityRange<QuantityE>(Emin, Emax));
00526 }
00527 
00528 
00529 //----------------------------------------------------------------------
00531 class QuantityM2 : public QuantitySquareBase{
00532 public:
00533   QuantityM2(double m) : QuantitySquareBase(m){}
00534   virtual double operator()(const PseudoJet & jet ) const { return jet.m2();}
00535   virtual string description() const {return "m";}
00536 };  
00537 
00538 // returns a selector for a minimum m
00539 Selector SelectorMMin(double mmin) {
00540   return Selector(new SW_QuantityMin<QuantityM2>(mmin*mmin));
00541 }
00542 
00543 // returns a selector for a maximum m
00544 Selector SelectorMMax(double mmax) {
00545   return Selector(new SW_QuantityMax<QuantityM2>(mmax*mmax));
00546 }
00547 
00548 // returns a selector for a m range
00549 Selector SelectorMRange(double mmin, double mmax) {
00550   return Selector(new SW_QuantityRange<QuantityM2>(mmin*mmin, mmax*mmax));
00551 }
00552 
00553 
00554 
00555 //----------------------------------------------------------------------
00557 class QuantityRap : public QuantityBase{
00558 public:
00559   QuantityRap(double rap) : QuantityBase(rap){}
00560   virtual double operator()(const PseudoJet & jet ) const { return jet.rap();}
00561   virtual string description() const {return "rap";}
00562 };  
00563 
00564 
00566 class SW_RapMin : public SW_QuantityMin<QuantityRap>{
00567 public:
00568   SW_RapMin(double rapmin) : SW_QuantityMin<QuantityRap>(rapmin){}
00569   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
00570     rapmax = std::numeric_limits<double>::max();     
00571     rapmin = _qmin.comparison_value();
00572   }
00573 };
00574 
00576 class SW_RapMax : public SW_QuantityMax<QuantityRap>{
00577 public:
00578   SW_RapMax(double rapmax) : SW_QuantityMax<QuantityRap>(rapmax){}
00579   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
00580     rapmax = _qmax.comparison_value(); 
00581     rapmin = -std::numeric_limits<double>::max();
00582   }
00583 };
00584 
00586 class SW_RapRange : public SW_QuantityRange<QuantityRap>{
00587 public:
00588   SW_RapRange(double rapmin, double rapmax) : SW_QuantityRange<QuantityRap>(rapmin, rapmax){
00589     assert(rapmin<=rapmax);
00590   }
00591   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
00592     rapmax = _qmax.comparison_value();      
00593     rapmin = _qmin.comparison_value(); 
00594   }
00595   virtual bool has_area() const { return true;}   
00596   virtual bool has_known_area() const { return true;}   
00597   virtual double known_area() const { 
00598     return twopi * (_qmax.comparison_value()-_qmin.comparison_value());
00599   }
00600 };
00601 
00602 // returns a selector for a minimum rapidity
00603 Selector SelectorRapMin(double rapmin) {
00604   return Selector(new SW_RapMin(rapmin));
00605 }
00606 
00607 // returns a selector for a maximum rapidity
00608 Selector SelectorRapMax(double rapmax) {
00609   return Selector(new SW_RapMax(rapmax));
00610 }
00611 
00612 // returns a selector for a rapidity range
00613 Selector SelectorRapRange(double rapmin, double rapmax) {
00614   return Selector(new SW_RapRange(rapmin, rapmax));
00615 }
00616 
00617 
00618 //----------------------------------------------------------------------
00620 class QuantityAbsRap : public QuantityBase{
00621 public:
00622   QuantityAbsRap(double absrap) : QuantityBase(absrap){}
00623   virtual double operator()(const PseudoJet & jet ) const { return abs(jet.rap());}
00624   virtual string description() const {return "|rap|";}
00625 };  
00626 
00627 
00629 class SW_AbsRapMax : public SW_QuantityMax<QuantityAbsRap>{
00630 public:
00631   SW_AbsRapMax(double absrapmax) : SW_QuantityMax<QuantityAbsRap>(absrapmax){}
00632   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
00633     rapmax =  _qmax.comparison_value(); 
00634     rapmin = -_qmax.comparison_value();
00635   }
00636   virtual bool has_area() const { return true;}              
00637   virtual bool has_known_area() const { return true;}   
00638   virtual double known_area() const { 
00639     return twopi * 2 * _qmax.comparison_value();
00640   }
00641 };
00642 
00644 class SW_AbsRapRange : public SW_QuantityRange<QuantityAbsRap>{
00645 public:
00646   SW_AbsRapRange(double absrapmin, double absrapmax) : SW_QuantityRange<QuantityAbsRap>(absrapmin, absrapmax){}
00647   virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
00648     rapmax =  _qmax.comparison_value(); 
00649     rapmin = -_qmax.comparison_value();
00650   }
00651   virtual bool has_area() const { return true;}   
00652   virtual bool has_known_area() const { return true;}   
00653   virtual double known_area() const { 
00654     return twopi * 2 * (_qmax.comparison_value()-max(_qmin.comparison_value(),0.0)); // this shold handle properly absrapmin<0
00655   }
00656 };
00657 
00658 // returns a selector for a minimum |rapidity|
00659 Selector SelectorAbsRapMin(double absrapmin) {
00660   return Selector(new SW_QuantityMin<QuantityAbsRap>(absrapmin));
00661 }
00662 
00663 // returns a selector for a maximum |rapidity|
00664 Selector SelectorAbsRapMax(double absrapmax) {
00665   return Selector(new SW_AbsRapMax(absrapmax));
00666 }
00667 
00668 // returns a selector for a |rapidity| range
00669 Selector SelectorAbsRapRange(double rapmin, double rapmax) {
00670   return Selector(new SW_AbsRapRange(rapmin, rapmax));
00671 }
00672 
00673 
00674 //----------------------------------------------------------------------
00676 class QuantityEta : public QuantityBase{
00677 public:
00678   QuantityEta(double eta) : QuantityBase(eta){}
00679   virtual double operator()(const PseudoJet & jet ) const { return jet.eta();}
00680   virtual string description() const {return "eta";}
00681 };  
00682 
00683 // returns a selector for a pseudo-minimum rapidity
00684 Selector SelectorEtaMin(double etamin) {
00685   return Selector(new SW_QuantityMin<QuantityEta>(etamin));
00686 }
00687 
00688 // returns a selector for a pseudo-maximum rapidity
00689 Selector SelectorEtaMax(double etamax) {
00690   return Selector(new SW_QuantityMax<QuantityEta>(etamax));
00691 }
00692 
00693 // returns a selector for a pseudo-rapidity range
00694 Selector SelectorEtaRange(double etamin, double etamax) {
00695   return Selector(new SW_QuantityRange<QuantityEta>(etamin, etamax));
00696 }
00697 
00698 
00699 //----------------------------------------------------------------------
00701 class QuantityAbsEta : public QuantityBase{
00702 public:
00703   QuantityAbsEta(double abseta) : QuantityBase(abseta){}
00704   virtual double operator()(const PseudoJet & jet ) const { return abs(jet.eta());}
00705   virtual string description() const {return "|eta|";}
00706 };  
00707 
00708 // returns a selector for a minimum |pseudo-rapidity|
00709 Selector SelectorAbsEtaMin(double absetamin) {
00710   return Selector(new SW_QuantityMin<QuantityAbsEta>(absetamin));
00711 }
00712 
00713 // returns a selector for a maximum |pseudo-rapidity|
00714 Selector SelectorAbsEtaMax(double absetamax) {
00715   return Selector(new SW_QuantityMax<QuantityAbsEta>(absetamax));
00716 }
00717 
00718 // returns a selector for a |pseudo-rapidity| range
00719 Selector SelectorAbsEtaRange(double absetamin, double absetamax) {
00720   return Selector(new SW_QuantityRange<QuantityAbsEta>(absetamin, absetamax));
00721 }
00722 
00723 
00724 //----------------------------------------------------------------------
00730 class SW_PhiRange : public SelectorWorker {
00731 public:
00733   SW_PhiRange(double phimin, double phimax) : _phimin(phimin), _phimax(phimax){
00734     assert(_phimin<_phimax);
00735     assert(_phimin>-twopi);
00736     assert(_phimax<2*twopi);
00737 
00738     _phispan = _phimax - _phimin;
00739   }
00740 
00742   virtual bool pass(const PseudoJet & jet) const {
00743     double dphi=jet.phi()-_phimin;
00744     if (dphi >= twopi) dphi -= twopi;
00745     if (dphi < 0)      dphi += twopi;
00746     return (dphi <= _phispan);
00747   }
00748 
00750   virtual string description() const {
00751     ostringstream ostr;
00752     ostr << _phimin << " <= phi <= " << _phimax;
00753     return ostr.str();
00754   }
00755 
00756 protected:
00757   double _phimin;   // the lower cut 
00758   double _phimax;   // the upper cut
00759   double _phispan;  // the span of the range
00760 };
00761 
00762 
00763 // returns a selector for a phi range
00764 Selector SelectorPhiRange(double phimin, double phimax) {
00765   return Selector(new SW_PhiRange(phimin, phimax));
00766 }
00767 
00768 //----------------------------------------------------------------------
00770 class SW_RapPhiRange : public SW_And{
00771 public:
00772   SW_RapPhiRange(double rapmin, double rapmax, double phimin, double phimax)
00773     : SW_And(SelectorRapRange(rapmin, rapmax), SelectorPhiRange(phimin, phimax)){
00774     _known_area = ((phimax-phimin > twopi) ? twopi : phimax-phimin) * (rapmax-rapmin);
00775   }
00776 
00778   virtual bool has_area() const { return true;}
00779 
00781   virtual bool has_known_area() const { return true;}
00782   
00784   virtual double known_area() const{
00785     return _known_area;
00786   }
00787 
00788 protected:
00789   double _known_area;
00790 };
00791 
00792 Selector SelectorRapPhiRange(double rapmin, double rapmax, double phimin, double phimax) {
00793   return Selector(new SW_RapPhiRange(rapmin, rapmax, phimin, phimax));
00794 }
00795 
00796 
00797 //----------------------------------------------------------------------
00799 class SW_NHardest : public SelectorWorker {
00800 public:
00802   SW_NHardest(unsigned int n) : _n(n) {};
00803 
00807   virtual bool pass(const PseudoJet & jet) const {
00808     if (!applies_jet_by_jet())
00809       throw Error("Cannot apply this selector worker to an individual jet");
00810     return false;
00811   }
00812 
00815   virtual void terminator(vector<const PseudoJet *> & jets) const {
00816     // do we want to first chech if things are already ordered before
00817     // going through the ordering process?
00818 
00819     vector<double> minus_pt2(jets.size());
00820     vector<unsigned int> indices(jets.size());
00821 
00822     for (unsigned int i=0; i<jets.size(); i++){
00823       indices[i] = i;
00824 
00825       // we need to make sure that the object has not already been
00826       // nullified.  Note that if we have less than _n jets, this
00827       // whole n-hardest selection will not have any effect.
00828       minus_pt2[i] = jets[i] ? -jets[i]->perp2() : 0.0;
00829     }
00830     
00831     IndexedSortHelper sort_helper(& minus_pt2);
00832     
00833     partial_sort(indices.begin(), indices.begin()+_n, indices.end(), sort_helper);
00834     
00835     for (unsigned int i=_n; i<jets.size(); i++)
00836       jets[indices[i]] = NULL;
00837   }
00838   
00840   virtual bool applies_jet_by_jet() const {return false;}
00841   
00843   virtual string description() const {
00844     ostringstream ostr;
00845     ostr << _n << " hardest";
00846     return ostr.str();
00847   }
00848   
00849 protected:
00850   unsigned int _n;
00851 };
00852 
00853 
00854 // returns a selector for the n hardest jets
00855 Selector SelectorNHardest(unsigned int n) {
00856   return Selector(new SW_NHardest(n));
00857 }
00858 
00859 
00860 
00861 //----------------------------------------------------------------------
00862 // selector and workers for geometric ranges
00863 //----------------------------------------------------------------------
00864 
00865 //----------------------------------------------------------------------
00867 class SW_Relocatable : public SelectorWorker{
00868 public:
00870   SW_Relocatable() : _is_initialised(false){};
00871 
00873   virtual bool is_relocatable() const { return true;}
00874 
00876   virtual void relocate(const PseudoJet &centre){
00877     _is_initialised = true;
00878     _centre = centre;
00879   }
00880 
00881 protected:
00882   PseudoJet _centre;
00883   bool _is_initialised;
00884 };
00885 
00886 //----------------------------------------------------------------------
00888 class SW_Circle : public SW_Relocatable {
00889 public:
00890   SW_Circle(const double &radius) : _radius2(radius*radius) {}
00891 
00893   virtual SelectorWorker* copy(){ return new SW_Circle(*this);}
00894 
00897   virtual bool pass(const PseudoJet & jet) const {
00898     // make sure the centre is initialised
00899     if (! _is_initialised)
00900       throw Error("To use a SelectorCircle (or any relocatable selector), you first have to call relocate()");
00901     
00902     return jet.squared_distance(_centre) <= _radius2;
00903   } 
00904 
00906   virtual string description() const {
00907     ostringstream ostr;
00908     ostr << "distance from the centre <= " << sqrt(_radius2);
00909     return ostr.str();
00910   }
00911 
00913   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
00914     // make sure the centre is initialised
00915     if (! _is_initialised)
00916       throw Error("To use a SelectorCircle (or any relocatable selector), you first have to call relocate()");
00917     
00918     rapmax = _centre.rap()+sqrt(_radius2);
00919     rapmin = _centre.rap()-sqrt(_radius2);
00920   }
00921 
00922   virtual bool has_area() const { return true;}   
00923   virtual bool has_known_area() const { return true;}   
00924   virtual double known_area() const { 
00925     return pi * _radius2;
00926   }
00927 
00928 protected:
00929   double _radius2;
00930 };
00931 
00932 
00933 // select on objets within a distance 'radius' of a variable location
00934 Selector SelectorCircle(const double & radius) {
00935   return Selector(new SW_Circle(radius));
00936 }
00937 
00938 
00939 //----------------------------------------------------------------------
00942 class SW_Doughnut : public SW_Relocatable {
00943 public:
00944   SW_Doughnut(const double &radius_in, const double &radius_out)
00945     : _radius_in2(radius_in*radius_in), _radius_out2(radius_out*radius_out) {}
00946 
00948   virtual SelectorWorker* copy(){ return new SW_Doughnut(*this);}
00949 
00952   virtual bool pass(const PseudoJet & jet) const {
00953     // make sure the centre is initialised
00954     if (! _is_initialised)
00955       throw Error("To use a SelectorDoughnut (or any relocatable selector), you first have to call relocate()");
00956 
00957     double distance2 = jet.squared_distance(_centre);
00958 
00959     return (distance2 <= _radius_out2) && (distance2 >= _radius_in2);
00960   } 
00961 
00963   virtual string description() const {
00964     ostringstream ostr;
00965     ostr << sqrt(_radius_in2) << " <= distance from the centre <= " << sqrt(_radius_out2);
00966     return ostr.str();
00967   }
00968 
00970   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
00971     // make sure the centre is initialised
00972     if (! _is_initialised)
00973       throw Error("To use a SelectorDoughnut (or any relocatable selector), you first have to call relocate()");
00974 
00975     rapmax = _centre.rap()+sqrt(_radius_out2);
00976     rapmin = _centre.rap()-sqrt(_radius_out2);
00977   }
00978 
00979   virtual bool has_area() const { return true;}   
00980   virtual bool has_known_area() const { return true;}   
00981   virtual double known_area() const { 
00982     return pi * (_radius_out2-_radius_in2);
00983   }
00984 
00985 protected:
00986   double _radius_in2, _radius_out2;
00987 };
00988 
00989 
00990 
00991 // select on objets with distance from the centre is between 'radius_in' and 'radius_out' 
00992 Selector SelectorDoughnut(const double & radius_in, const double & radius_out) {
00993   return Selector(new SW_Doughnut(radius_in, radius_out));
00994 }
00995 
00996 
00997 //----------------------------------------------------------------------
00999 class SW_Strip : public SW_Relocatable {
01000 public:
01001   SW_Strip(const double &delta) : _delta(delta) {}
01002 
01004   virtual SelectorWorker* copy(){ return new SW_Strip(*this);}
01005 
01008   virtual bool pass(const PseudoJet & jet) const {
01009     // make sure the centre is initialised
01010     if (! _is_initialised)
01011       throw Error("To use a SelectorStrip (or any relocatable selector), you first have to call relocate()");
01012     
01013     return abs(jet.rap()-_centre.rap()) <= _delta;
01014   } 
01015 
01017   virtual string description() const {
01018     ostringstream ostr;
01019     ostr << "|rap - rap_centre| <= " << _delta;
01020     return ostr.str();
01021   }
01022 
01024   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
01025     // make sure the centre is initialised
01026     if (! _is_initialised)
01027       throw Error("To use a SelectorStrip (or any relocatable selector), you first have to call relocate()");
01028     
01029     rapmax = _centre.rap()+_delta;
01030     rapmin = _centre.rap()-_delta;
01031   }
01032 
01033   virtual bool has_area() const { return true;}   
01034   virtual bool has_known_area() const { return true;}   
01035   virtual double known_area() const { 
01036     return twopi * 2 * _delta;
01037   }
01038 
01039 protected:
01040   double _delta;
01041 };
01042 
01043 
01044 // select on objets within a distance 'radius' of a variable location
01045 Selector SelectorStrip(const double & half_width) {
01046   return Selector(new SW_Strip(half_width));
01047 }
01048 
01049 
01050 //----------------------------------------------------------------------
01054 class SW_Rectangle : public SW_Relocatable {
01055 public:
01056   SW_Rectangle(const double &delta_rap, const double &delta_phi)
01057     : _delta_rap(delta_rap),  _delta_phi(delta_phi) {}
01058 
01060   virtual SelectorWorker* copy(){ return new SW_Rectangle(*this);}
01061 
01064   virtual bool pass(const PseudoJet & jet) const {
01065     // make sure the centre is initialised
01066     if (! _is_initialised)
01067       throw Error("To use a SelectorRectangle (or any relocatable selector), you first have to call relocate()");
01068 
01069     return (abs(jet.rap()-_centre.rap()) <= _delta_rap) && (abs(jet.delta_phi_to(_centre)) <= _delta_phi);
01070   } 
01071 
01073   virtual string description() const {
01074     ostringstream ostr;
01075     ostr << "|rap - rap_centre| <= " << _delta_rap << " && |phi - phi_centre| <= " << _delta_phi ;
01076     return ostr.str();
01077   }
01078 
01080   virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
01081     // make sure the centre is initialised
01082     if (! _is_initialised)
01083       throw Error("To use a SelectorRectangle (or any relocatable selector), you first have to call relocate()");
01084 
01085     rapmax = _centre.rap()+_delta_rap;
01086     rapmin = _centre.rap()-_delta_rap;
01087   }
01088 
01089   virtual bool has_area() const { return true;}   
01090   virtual bool has_known_area() const { return true;}   
01091   virtual double known_area() const { 
01092     return 4 * _delta_rap * _delta_phi;
01093   }
01094 
01095 protected:
01096   double _delta_rap, _delta_phi;
01097 };
01098 
01099 
01100 // select on objets within a distance 'radius' of a variable location
01101 Selector SelectorRectangle(const double & half_rap_width, const double & half_phi_width) {
01102   return Selector(new SW_Rectangle(half_rap_width, half_phi_width));
01103 }
01104 
01105 
01106 
01107 FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh