Index: external/fastjet/contribs/RecursiveTools/AUTHORS
===================================================================
--- external/fastjet/contribs/RecursiveTools/AUTHORS	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/AUTHORS	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,17 @@
+The RecursiveTools FastJet contrib is developed and maintained by:
+
+   Gavin P. Salam <gavin.salam@cern.ch>
+   Gregory Soyez <soyez@fastjet.fr>
+   Jesse Thaler <jthaler@jthaler.net>
+
+The physics is based on:
+
+   [ModifiedMassDropTagger]
+   Towards an understanding of jet substructure.
+   Mrinal Dasgupta, Alessandro Fregoso, Simone Marzani, and Gavin P. Salam.
+   JHEP 1309:029 (2013), arXiv:1307.0007.
+
+   [SoftDrop]
+   Soft Drop.
+   Andrew J. Larkoski, Simone Marzani, Gregory Soyez, and Jesse Thaler.
+   JHEP 1405:146 (2014), arXiv:1402.2657
Index: external/fastjet/contribs/RecursiveTools/COPYING
===================================================================
--- external/fastjet/contribs/RecursiveTools/COPYING	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/COPYING	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,359 @@
+The RecursiveTools contrib to FastJet is released 
+under the terms of the GNU General Public License v2 (GPLv2). 
+
+A copy of the GPLv2 is to be found at the end of this file.
+
+While the GPL license grants you considerable freedom, please bear in
+mind that this code's use falls under guidelines similar to those that
+are standard for Monte Carlo event generators
+(http://www.montecarlonet.org/GUIDELINES). In particular, if you use
+this code as part of work towards a scientific publication, whether
+directly or contained within another program you should include a
+citation to
+
+  arXiv:1307.0007
+  arXiv:1402.2657
+
+======================================================================
+======================================================================
+======================================================================
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: external/fastjet/contribs/RecursiveTools/ChangeLog
===================================================================
--- external/fastjet/contribs/RecursiveTools/ChangeLog	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/ChangeLog	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,280 @@
+2014-07-09  Gregory Soyez  <soyez@fastjet.fr> + Jesse
+
+	* NEWS:
+	release of RecursiveTools v1.0.0
+
+	* VERSION:
+	switched version number to 1.0.0
+
+2014-07-08  Gavin Salam  <gavin.salam@cern.ch>
+
+	* README (RecursionChoice): 
+	added ref to .hh for constness specs of virtual functions (to
+	reduce risk of failed overloading due to wrong constness).
+
+2014-07-08  Gregory Soyez  <soyez@fastjet.fr> + Jesse
+
+	* README:
+	partially rewrote the description of set_subtractor
+
+2014-07-07  Gregory Soyez  <soyez@fastjet.fr> + Jesse
+
+	* example_advanced_usage.cc:
+	* example_softdrop.cc:
+	a few small fixed in the header of the files
+
+	* VERSION:
+	switched over to 1.0.0-alpha2-devel
+
+	* README:
+	Reordered a few things and added a few details.
+
+	* Makefile (check):
+	Be quiter during "make check"
+
+	* Recluster.cc (contrib):
+	Documented the "single" ctor argument
+
+	* RecursiveSymmetryCutBase.cc (contrib):
+	If the user sets himself the reclustering, disable the "non-CA"
+	warning (we assume that he knows what he is doing). Mentioned in
+	the comments that non-CA reclustering has to be used at the user's
+	risk. Also throw when th input jet has no constituents or when
+	there is no cluster sequence after reclustering.
+
+	* Recluster.cc (contrib):
+	replaced a remaining mention to "filtering" by reclustering
+
+2014-07-04  Jesse Thaler  <jthaler@jthaler.net>
+	* VERSION
+	  . Ready for alpha release
+
+2014-06-17  Jesse Thaler  <jthaler@jthaler.net>
+	* example_advanced_usage.{cc,ref}  ** ADDED **
+	* Makefile
+	  . New example file to test a bunch of soft drop options
+	  . Put in makefile as well
+	  . Fixed nasty memory bug with pointers to Recluster
+
+	* RecursiveSymmetryCutBase.cc
+	* example_softdrop.ref 
+	  . description() now says Groomer vs. Tagger
+
+	* RecursiveSymmetryCutBase.{cc,hh}
+	  . Added optional verbose logging information about
+	    kinematics of dropped branches
+	
+	* example_softdrop.cc
+	* example_advanced_usage.cc
+	  . Fixed 
+
+
+2014-06-16  Gregory Soyez  <soyez@fastjet.fr>
+
+	* Makefile:
+	also install the RecursiveSymmetryuCutBase.hh header
+
+2014-06-13  Jesse Thaler  <jthaler@jthaler.net>
+	* AUTHORS
+	  . Added myself to author list
+          . Put complete bibliographic details on papers
+
+	* COPYING
+	  . Added boilerplate MC/GPLv2 statement 
+
+        * example.cc:  ** REMOVED **  renamed to...
+        * example_mmdt.cc   ** ADDED **
+        * Makefile
+          . Made name change for consistency
+	  . Made corresponding changes in Makefile
+
+	* example_mmdt_sub.cc:
+	* example_mmdt.cc:
+	* example_recluster.cc:
+	  . light editing of comments
+
+	* example_softdrop.cc:
+	  . light editing of comments
+          . added assert for sdjet != 0, since SoftDrop is a groomer
+
+	* ModifiedMassDropTagger.hh
+	* Recluster.{cc,hh}
+	* RecursiveSymmetryCutBase.{cc,hh}
+	* SoftDrop.hh
+	  . Updated some comments
+
+	* README
+	  . Updated to include basic usage description and some 
+	    technical details
+
+	* TODO:
+	  . Added some discussion points.
+          
+2014-06-13  Gregory Soyez  <soyez@fastjet.fr>
+
+	* example_softdrop.{cc,ref}:
+	added an example for SoftDrop
+
+	* SoftDrop.{hh,cc}:
+	* ModifiedMassDropTagger.{hh,cc}:
+	* RecursiveSymmetryCutBase.{hh,cc}:        *** ADDED ***
+	  . added a base class for both the mMDT and SoftDrop
+	  . made mMDT and SoftDrop inherit from RecursiveSymmetryCutBase
+	  . moved the reclustering to the base class. By default, both
+	    mMDT and SoftDrop now recluster the jet with C/A
+	  . added set_grooming_mode and set_tagging_mode methods to the
+	    base class
+
+	* Merging the development branch 1.0-beta1-softdrop-addition back
+	into the trunk (will correspond to revision 682)
+
+	* VERSION:
+	switched back to 1.0.0-devel
+
+	* SoftDrop.{hh,cc}:
+	added support for re-clustering through set_reclustering(bool,
+	Recluster*). By default, reclustering is done with
+	Cambridge/Aachen.
+
+	* example_recluster.{cc,ref}:              *** ADDED ***
+	added an example of reclustering
+
+	* Recluster.{hh,cc}:
+	added a 'single' ctor argument [true by default]. When true, the
+	hardest jet after reclustering is returned, otherwise, the result
+	is a composite jet with all the subjets as its pieces.
+
+2014-05-15  Gregory Soyez  <soyez@fastjet.fr>
+
+	* VERSION:
+	set version number to 1.0-alpha-PUWS14.1 in preparation for a
+	fastjet-contrib release for the pileup-workshop at CERN on May
+	2014.
+
+2014-04-25  Gregory Soyez  <soyez@fastjet.fr>
+
+	* ModifiedMassDropTagger.hh:
+	* ModifiedMassDropTagger.cc:
+	  Added comments at various places
+
+	* AUTHORS:
+	* README:
+	Updated info about what is now included in this contrib
+
+	* SoftDrop.hh:                *** ADDED ***
+	* SoftDrop.cc:	              *** ADDED ***
+	* Recluster.hh:	              *** ADDED ***
+	* Recluster.cc;               *** ADDED ***
+	Added tools for reclustering and softDrop
+
+2014-04-25  Gregory Soyez  <soyez@fastjet.fr>
+
+	branch started at revision 611 to start including SoftDrop in the
+	Recursivetols contrib
+
+2014-04-24  Gregory Soyez  <soyez@fastjet.fr>
+
+	* ModifiedMassDropTagger.hh:
+	added a mention of the fact that when result is called in the
+	presence of a subtractor, then the output is a subtracted
+	PseudoJet.
+
+	* ModifiedMassDropTagger.hh:
+	declared _symmetry_cut as protected (rather than provate) so it
+	can be accessed if symmetry_cut_description() is overloaded.
+
+	* example.cc:
+	trivial typo fixed in a comment
+
+2014-02-04  Gavin Salam  <gavin.salam@cern.ch>
+
+	* VERSION: 
+	upped it to 1.0-beta1
+
+	* example_mmdt_sub.cc (main): 
+	added an #if to make sure FJ3.1 features are only used if FJ3.1
+	is available. (Currently FJ3.1 is only available to FJ developers).
+
+2014-01-26  Gavin Salam  <gavin.salam@cern.ch>
+
+	* VERSION:
+	renamed to 1.0-beta0
+
+	* ModifiedMassDropTagger.hh:
+	* README:
+	added info on author names
+
+	* example_mmdt_sub.ref: *** ADDED ***
+	added reference output for the pileup test.
+
+2014-01-25  Gavin Salam  <gavin.salam@cern.ch>
+
+	* example_mmdt_sub.cc:
+	* Makefile:
+	added an extra example illustrating functionality with pileup
+	subtraction.
+
+2014-01-24  Gavin Salam  <gavin.salam@cern.ch>
+
+	* ModifiedMassDropTagger.cc:
+
+	Reorganised code so that (sub)jet.m2()>0 check is only used when
+	absolutely necessary: so if using a scalar_z symmetry measure,
+	whenever scalar_z < zcut, then there is no point checking the mu
+	condition. This means that there's no issue if the (sub)jet mass
+	is negative, and one simply recurses down into the jet. (Whereas
+	before it would bail out, reducing the tagging efficiency).
+
+	Also removed the verbose code.
+
+2014-01-23  Gavin Salam  <gavin.salam@cern.ch>
+
+	* ModifiedMassDropTagger.cc|hh:
+	* example.cc
+	replaced "asymmetry" with "symmetry" in a number of places;
+	implemented the structural information and added it to the example;
+	added a new simplified constructor;
+	improved doxygen documentation;
+	started renaming -> RecursiveTools
+
+	* README
+	some tidying
+
+	* VERSION
+	1.0-b0
+
+2014-01-22  Gavin Salam <gavin.salam@cern.ch>
+
+	* ModifiedMassDropTagger.cc (contrib):
+	-ve mass now bails out also when using the "y" asymmetry measure.
+	Also, default my is now infinite.
+
+2014-01-20  Gavin Salam <gavin.salam@cern.ch> + Gregory
+
+
+	* ModifiedMassDropTagger.cc|hh:
+	introduced a virtual asymmetry_cut_fn (essentially a
+	dummy function returning a constant), to allow for derived classes
+	to do fancier things.
+
+	added warning about non-C/A clustering.
+	explicitly labelled some (inherited) virtual functions as
+	virtual. 
+
+2014-01-20  Gavin Salam  <gavin.salam@cern.ch>
+
+	* example.ref:
+	* example.cc (main):
+	got a first working example and make check setup.
+
+	* ModifiedMassDropTagger.cc|hh:
+	improved doxygen comments;
+	added option whereby input jet is assumed already subtracted
+
+2014-01-19  Gavin Salam  <gavin.salam@cern.ch>
+
+	* ModifiedMassDropTagger.cc|hh:
+	* many other files
+
+        Initial creation, with basic code for MMDT
+
Index: external/fastjet/contribs/RecursiveTools/ModifiedMassDropTagger.cc
===================================================================
--- external/fastjet/contribs/RecursiveTools/ModifiedMassDropTagger.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/ModifiedMassDropTagger.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,43 @@
+// $Id: ModifiedMassDropTagger.cc 683 2014-06-13 14:38:38Z gsoyez $
+//
+// Copyright (c) 2014-, Gavin P. Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include "ModifiedMassDropTagger.hh"
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include <algorithm> 
+#include <cstdlib> 
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+namespace contrib{
+
+//----------------------------------------------------------------------
+string ModifiedMassDropTagger::symmetry_cut_description() const {
+  ostringstream ostr;
+  ostr << _symmetry_cut << " [ModifiedMassDropTagger]";
+  return ostr.str();
+}
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
Index: external/fastjet/contribs/RecursiveTools/ModifiedMassDropTagger.hh
===================================================================
--- external/fastjet/contribs/RecursiveTools/ModifiedMassDropTagger.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/ModifiedMassDropTagger.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,123 @@
+// $Id: ModifiedMassDropTagger.hh 688 2014-06-17 14:29:56Z jthaler $
+//
+// Copyright (c) 2014-, Gavin P. Salam
+// based on arXiv:1307.007 by Mrinal Dasgupta, Simone Marzani and Gavin P. Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#ifndef __FASTJET_CONTRIB_MODIFIEDMASSDROPTAGGER_HH__
+#define __FASTJET_CONTRIB_MODIFIEDMASSDROPTAGGER_HH__
+
+#include "RecursiveSymmetryCutBase.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+namespace contrib{
+
+//------------------------------------------------------------------------
+/// \class ModifiedMassDropTagger
+/// An implementation of the modified Mass-Drop Tagger from arXiv:1307.0007.
+///
+class ModifiedMassDropTagger : public RecursiveSymmetryCutBase {
+public:
+  
+  /// Simplified constructor, which takes just a symmetry cut (applied
+  /// on the scalar_z variable) and an optional subtractor.
+  ///
+  /// In this incarnation the ModifiedMassDropTagger is a bit of a
+  /// misnomer, because there is no mass-drop condition
+  /// applied. Recursion into the jet structure chooses the prong with
+  /// largest pt. (Results from arXiv:1307.0007 were based on the
+  /// largest mt, but this only makes a difference for values of the
+  /// symmetry_cut close to 1/2).
+  ///
+  /// If the (optional) pileup subtractor can be supplied, then see
+  /// also the documentation for the set_input_jet_is_subtracted() member
+  /// function.
+  ///
+  /// NB: The configuration of MMDT provided by this constructor is
+  /// probably the most robust for use with subtraction.
+  ModifiedMassDropTagger(double symmetry_cut, 
+                         const FunctionOfPseudoJet<PseudoJet> * subtractor = 0
+                         ) :
+    RecursiveSymmetryCutBase(scalar_z,  // the default SymmetryMeasure
+                             std::numeric_limits<double>::infinity(), // the default is no mass drop
+                             larger_pt, // the default RecursionChoice
+                             subtractor),
+    _symmetry_cut(symmetry_cut)
+  {}
+
+  /// Full constructor, which takes the following parameters:
+  ///
+  /// \param symmetry_cut       the value of the cut on the symmetry measure
+  /// \param symmetry_measure   the choice of measure to use to estimate the symmetry
+  /// \param mu_cut             the maximal allowed value of mass drop variable mu = m_heavy/m_parent 
+  /// \param recursion_choice   the strategy used to decide which subjet to recurse into
+  /// \param subtractor         an optional pointer to a pileup subtractor (ignored if zero)
+  ///
+  /// To obtain the mMDT as discussed in arXiv:1307.0007, use an
+  /// symmetry_measure that's one of the following
+  ///
+  /// - RecursiveSymmetryCutBase::y         (for a cut on y)
+  /// - RecursiveSymmetryCutBase::scalar_z  (for a cut on z)
+  ///
+  /// and use the default recursion choice of
+  /// RecursiveSymmetryCutBase::larger_pt (larger_mt will give something
+  /// very similar, while larger_m will give the behaviour of the
+  /// original, but now deprecated MassDropTagger)
+  ///
+  /// Notes: 
+  ///
+  /// - By default the ModifiedMassDropTagger will relcuster the jets
+  ///   with the C/A algorithm (if needed).
+  ///
+  /// - the mu_cut parameter is mostly irrelevant when it's taken
+  ///   larger than about 1/2: the tagger is then one that cuts
+  ///   essentially on the (a)symmetry of the jet's momentum
+  ///   sharing. The default value of infinity turns off its use
+  ///   entirely
+  ModifiedMassDropTagger(double           symmetry_cut, 
+                         SymmetryMeasure  symmetry_measure,
+                         double           mu_cut = std::numeric_limits<double>::infinity(), 
+                         RecursionChoice  recursion_choice = larger_pt,
+                         const FunctionOfPseudoJet<PseudoJet> * subtractor = 0
+                         ) : 
+    RecursiveSymmetryCutBase(symmetry_measure, mu_cut, recursion_choice, subtractor),
+    _symmetry_cut(symmetry_cut)
+  {}
+
+  /// default destructor
+  virtual ~ModifiedMassDropTagger(){}
+
+protected:
+
+  /// The symmetry cut function for MMDT returns just a constant, since the cut value
+  /// has no dependence on the subjet kinematics
+  virtual double symmetry_cut_fn(const PseudoJet & /* p1 */, 
+                                 const PseudoJet & /* p2 */
+                                 ) const {return _symmetry_cut;}
+  virtual std::string symmetry_cut_description() const;
+
+  double           _symmetry_cut;
+};
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
+
+#endif  // __FASTJET_CONTRIB_MODIFIEDMASSDROPTAGGER_HH__
Index: external/fastjet/contribs/RecursiveTools/NEWS
===================================================================
--- external/fastjet/contribs/RecursiveTools/NEWS	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/NEWS	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,2 @@
+2014/07/09: release of version 1.0.0 of RecursiveTools including
+            ModifiedMassDropTagger and SoftDrop (as well as Recluster)
Index: external/fastjet/contribs/RecursiveTools/README
===================================================================
--- external/fastjet/contribs/RecursiveTools/README	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/README	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,186 @@
+------------------------------------------------------------------------
+RecursiveTools FastJet contrib
+------------------------------------------------------------------------
+
+The RecursiveTools FastJet contrib aims to provide a common contrib
+for a number of tools that involve recursive reclustering/declustering
+of a jet for tagging or grooming purposes.
+
+Currently it contains:
+
+- ModifiedMassDropTagger
+  This corresponds to arXiv:1307.0007 by Mrinal Dasgupta, Alessandro
+  Fregoso, Simone Marzani and Gavin P. Salam
+
+- SoftDrop
+  This corresponds to arXiv:1402.2657 by Andrew J. Larkoski, Simone
+  Marzani, Gregory Soyez, Jesse Thaler
+
+- Recluster
+  A generic tool to recluster a given jet into subjets
+  Note: this is largely based on the Filter code in FastJet v3.0 and
+  ultimately, this tool will probably be moved into FastJet
+
+The interface for these tools is described in more detail below, with
+all of the available options documented in the header files.
+
+One note about nomenclature.  A groomer is a procedure that takes a
+PseudoJet and always returns another (non-zero) PseudoJet.  A tagger is
+a procedure that takes a PseudoJet, and either returns another PseudoJet
+(i.e. tags it) or returns an empty PseudoJet (i.e. doesn't tag it).
+
+------------------------------------------------------------------------
+ModifiedMassDropTagger
+------------------------------------------------------------------------
+
+The Modified Mass Drop Tagger (mMDT) recursively declusters a jet,
+following the largest pT subjet until a pair of subjets is found that
+satisfy the symmetry condition on the energy sharing
+
+   z > z_cut
+
+where z_cut is a predetermined value.  By default, z is calculated as
+the scalar pT fraction of the softest subjet.  Note that larger values
+of z_cut correspond to a more restrictive tagging criteria.
+
+By default, mMDT will first recluster the jet using the CA clustering
+algorithm, which means that mMDT can be called on any jet, regardless
+of the original jet finding measure.
+
+A default mMDT can be created via
+
+   double z_cut = 0.10;
+   ModifiedMassDropTagger mMDT(z_cut);
+
+More options are available in the full constructor.  To apply mMDT,
+one simply calls it on the jet of interest.
+
+   PseudoJet tagged_jet = mMDT(original_jet);
+
+Note that mMDT is a tagger, such that tagged_jet will only be non-zero
+if the symmetry cut z > z_cut is satisfied by some branching of the
+clustering tree.  
+
+To gain additional information about the mMDT procedure, one can use
+
+   tagged_jet.structure_of<ModifiedMassDropTagger>()
+
+which gives access to information about the delta_R between the tagged
+subjets, their z value, etc.
+
+------------------------------------------------------------------------
+SoftDrop
+------------------------------------------------------------------------
+
+The SoftDrop procedure is very similar to mMDT, albeit with a 
+generalized symmetry condition:
+ 
+   z > z_cut * (R / R0)^beta
+
+Note that larger z_cut and smaller beta correspond to more aggressive
+grooming of the jet.
+
+SoftDrop is intended to be used as a groomer (instead of as a tagger),
+such that if the symmetry condition fails throughout the whole
+clustering tree, SoftDrop will still return a single particle in the
+end.  Apart from the tagger/groomer distinction, SoftDrop with beta=0 is
+the same as mMDT.
+
+A default SoftDrop groomer can be created via:
+
+   double z_cut = 0.10;
+   double beta  = 2.0;
+   double R0    = 1.0; // this is the default value
+   SoftDrop sd(z_cut,beta,R0);
+
+and acts on a desired jet as
+
+   PseudoJet groomed_jet = sd(original_jet);
+
+and additional information can be obtained via
+
+   groomed_jet.structure_of<SoftDrop>()
+
+SoftDrop is typically called with beta > 0, though beta < 0 is still a
+viable option.  Because beta < 0 is infrared-collinear unsafe in
+grooming mode, one probably wants to switch to tagging mode for negative
+beta, via set_tagging_mode().
+
+------------------------------------------------------------------------
+Recluster
+------------------------------------------------------------------------
+
+The Recluster class allows the constituents of a jet to be reclustered
+with a different recursive clustering algorithm.  This is used
+internally in the mMDT/SoftDrop code in order to recluster the jet using
+the CA algorithm.  This is achieved via
+
+  Recluster ca_reclusterer(cambridge_algorithm,
+                        JetDefinition::max_allowable_R);
+  PseudoJet reclustered_jet = ca_reclusterer(original_jet);
+
+Note that reclustered_jet creates a new ClusterSequence that knows to
+delete_self_when_unused.
+
+
+------------------------------------------------------------------------
+Changing behaviour
+------------------------------------------------------------------------
+
+The behaviour of the ModifiedMassDropTagger and SoftDrop classes can
+be tweaked using the following options:
+
+SymmetryMeasure = {scalar_z,vector_z,y}  [constructor argument]
+  : The definition of the energy sharing between subjets, with 0
+    corresponding to the most asymmetric
+
+RecursionChoice = {larger_pt,larger_mt,larger_m}  [constructor argument]
+  : The path to recurse through the tree after the symmetry condition
+    fails
+
+mu_cut   [constructor argument]
+  : An optional mass drop condition
+
+set_subtractor(subtractor*) [or subtracter as a constructor argument]
+  : provide a subtractor. When a subtractor is supplied, the
+    kinematic constraints are applied on subtracted 4-vectors. In
+    this case, the result of the ModifiedMassDropTagger/SoftDrop is a
+    subtracted PseudoJet, and it is assumed that
+    ModifiedMassDropTagger/SoftDrop is applied to an unsubtracted jet.
+    The latter default can be changed by calling
+    set_input_jet_is_subtracted().
+
+set_reclustering(bool, Recluster*)
+  : An optional setting to recluster a jet with a different jet
+    recursive jet algorithm.  The code is only designed to give sensible
+    results with the CA algorithm, but other reclustering algorithm
+    (especially kT) may be appropriate in certain contexts. 
+    Use at your own risk.
+
+set_grooming_mode()/set_tagging_mode()
+  : In grooming mode, the algorithm will return a single particle if the
+    symmetry condition fails for the whole tree.  In tagging mode, the
+    algorithm will return an zero PseudoJet if no symmetry conditions
+    passes.  Note that ModifiedMassDropTagger defaults to tagging mode
+    and SoftDrop defaults to grooming mode.
+
+------------------------------------------------------------------------
+Technical Details
+------------------------------------------------------------------------
+
+Both ModifiedMassDropTagger and SoftDrop inherit from
+RecursiveSymmetryCutBase, which provides a common codebase for recursive
+declustering of a jet with a symmetry cut condition.  A generic 
+RecursiveSymmetryCutBase depends on the following (virtual) functions
+(see header file for exact full specs, including constness):
+
+double symmetry_cut_fn(PseudoJet &, PseudoJet &)
+  : The function that defines the symmetry cut. This is what actually 
+    defines different recursive declustering schemes, and all classes
+    that inherit from RecursiveSymmetryCutBase must define this
+    function.
+
+string symmetry_cut_description() 
+  : the string description of the symmetry cut.
+
+------------------------------------------------------------------------
Index: external/fastjet/contribs/RecursiveTools/Recluster.cc
===================================================================
--- external/fastjet/contribs/RecursiveTools/Recluster.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/Recluster.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,390 @@
+// $Id: Recluster.cc 699 2014-07-07 09:58:12Z gsoyez $
+//
+// Copyright (c) 2014-, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include "Recluster.hh"
+#include <fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh>
+#include <sstream>
+#include <typeinfo>
+
+using namespace std;
+
+// Comments:
+//
+//  - If the jet comes from a C/A clustering (or is a composite jet
+//    made of C/A clusterings) and we recluster it with a C/A
+//    algorithm, we just use exclusive jets instead of doing the
+//    clustering explicitly. In this specific case, we need to make
+//    sure that all the pieces share the same cluster sequence.
+//
+//  - If the recombiner has to be taken from the original jet and that
+//    jet is composite, we need to check that all the pieces were
+//    obtained with the same recombiner.
+//
+// TODO:
+//
+//  - check this actually works!!!
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+namespace contrib{
+
+LimitedWarning Recluster::_explicit_ghost_warning;
+
+// class description
+string Recluster::description() const {
+  ostringstream ostr;
+  ostr << "Recluster with subjet_def = ";
+  if (_use_full_def) {
+    ostr << _subjet_def.description();
+  } else {
+    if (_subjet_alg == kt_algorithm) {
+      ostr << "Longitudinally invariant kt algorithm with R = " << _subjet_radius;
+    } else if (_subjet_alg == cambridge_algorithm) {
+      ostr << "Longitudinally invariant Cambridge/Aachen algorithm with R = " << _subjet_radius;
+    } else if (_subjet_alg == antikt_algorithm) {
+      ostr << "Longitudinally invariant anti-kt algorithm with R = " << _subjet_radius;
+    } else if (_subjet_alg == genkt_algorithm) {
+      ostr << "Longitudinally invariant generalised kt algorithm with R = " << _subjet_radius
+           << ", p = " << _subjet_extra;
+    } else if (_subjet_alg == cambridge_for_passive_algorithm) {
+      ostr << "Longitudinally invariant Cambridge/Aachen algorithm with R = " << _subjet_radius
+           << " and a special hack whereby particles with kt < " 
+           << _subjet_extra << "are treated as passive ghosts";
+    } else if (_subjet_alg == ee_kt_algorithm) {
+      ostr << "e+e- kt (Durham) algorithm";
+    } else if (_subjet_alg == ee_genkt_algorithm) {
+      ostr << "e+e- generalised kt algorithm with R = " << _subjet_radius
+           << ", p = " << _subjet_extra;
+    } else if (_subjet_alg == undefined_jet_algorithm) {
+      ostr << "uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ;
+    } else {
+      ostr << "unrecognized jet_algorithm";
+    }
+    ostr << ", a recombiner obtained from the jet being reclustered";
+  }
+
+  if (_single)
+    ostr << " and keeping the hardest subjet";
+  else
+    ostr << " and joining all subjets in a composite jet";
+
+  return ostr.str();
+}
+
+// return a vector of subjets, which are the ones that would be kept
+// by the filtering
+PseudoJet Recluster::result(const PseudoJet &jet) const {
+  // generic sanity checks
+  //-------------------------------------------------------------------
+  // make sure that the jet has constituents
+  if (! jet.has_constituents())
+    throw Error("Filter can only be applied on jets having constituents");
+
+  // tests particular to certain configurations
+  //-------------------------------------------------------------------
+
+  // for a whole variety of checks, we shall need the "recursive"
+  // pieces of the jet (the jet itself or recursing down to its most
+  // fundamental pieces). So we do compute these once and for all.
+  //
+  // Note that the pieces are always needed (either for C/A or for the
+  // area checks)
+  vector<PseudoJet> all_pieces; //.clear();
+  if ((!_get_all_pieces(jet, all_pieces)) || (all_pieces.size()==0)){
+    throw Error("Recluster: failed to retrieve all the pieces composing the jet.");
+  }
+
+  // decide which jet definition to use
+  //-------------------------------------------------------------------
+  JetDefinition subjet_def;
+  if (_use_full_def){
+    subjet_def = _subjet_def;
+  } else {
+    _build_jet_def_with_recombiner(all_pieces, subjet_def);
+  }
+
+
+  // the vector that will ultimately hold the subjets
+  vector<PseudoJet> subjets;
+
+  // check if we can apply the simplification for C/A jets reclustered
+  // with C/A
+  //
+  // we apply C/A clustering iff
+  //  - the request subjet_def is C/A
+  //  - the jet is either directly coming from C/A or if it is a
+  //    superposition of C/A jets from the same cluster sequence
+  //  - the pieces agree with the recombination scheme of subjet_def
+  //
+  // Note that in this case area support will be automatically
+  // inherted so we can only worry about this later
+  //-------------------------------------------------------------------
+  if (_check_ca(all_pieces, subjet_def)){
+    _recluster_cafilt(all_pieces, subjets, subjet_def.R());
+    subjets = sorted_by_pt(subjets);
+    return _single
+      ? subjets[0]
+      : join(subjets, *(subjet_def.recombiner()));
+  }
+
+  // decide if area support has to be kept
+  //-------------------------------------------------------------------
+  bool include_area_support = jet.has_area();
+  if ((include_area_support) &&  (!_check_explicit_ghosts(all_pieces))){
+    _explicit_ghost_warning.warn("Recluster: the original cluster sequence is lacking explicit ghosts; area support will no longer be available after re-clustering");
+    include_area_support = false;
+  }
+
+  // extract the subjets
+  //-------------------------------------------------------------------
+  _recluster_generic(jet, subjets, subjet_def, include_area_support);
+  subjets = sorted_by_pt(subjets);
+
+  return _single
+    ? subjets[0]
+    : join(subjets, *(subjet_def.recombiner()));
+}
+
+//----------------------------------------------------------------------
+// the parts that really do the reclustering
+//----------------------------------------------------------------------
+
+// get the subjets in the simple case of C/A+C/A
+void Recluster::_recluster_cafilt(const vector<PseudoJet> & all_pieces, 
+                                  vector<PseudoJet> & subjets, 
+                                  double Rfilt) const{
+  subjets.clear();
+
+  // each individual piece should have a C/A cluster sequence
+  // associated to it. So a simple loop would do the job
+  for (vector<PseudoJet>::const_iterator piece_it = all_pieces.begin(); 
+       piece_it!=all_pieces.end(); piece_it++){
+    // just extract the exclusive subjets of 'jet'
+    const ClusterSequence *cs = piece_it->associated_cluster_sequence(); 
+    vector<PseudoJet> local_subjets;
+
+    double dcut = Rfilt / cs->jet_def().R();
+    if (dcut>=1.0){
+      local_subjets.push_back(*piece_it);
+    } else {
+      local_subjets = piece_it->exclusive_subjets(dcut*dcut);
+    }
+
+    copy(local_subjets.begin(), local_subjets.end(), back_inserter(subjets));
+  }
+}
+
+
+// set the filtered elements in the generic re-clustering case (w/o
+// subtraction)
+void Recluster::_recluster_generic(const PseudoJet & jet, 
+                                   vector<PseudoJet> & subjets,
+                                   const JetDefinition & subjet_def,
+                                   bool do_areas) const{
+  // create a new, internal, ClusterSequence from the jet constituents
+  // get the subjets directly from there
+  //
+  // If the jet has area support then we separate the ghosts from the
+  // "regular" particles so the subjets will also have area
+  // support. Note that we do this regardless of whether rho is zero
+  // or not.
+  //
+  // Note that to be able to separate the ghosts, one needs explicit
+  // ghosts!!
+  // ---------------------------------------------------------------
+  if (do_areas){
+    vector<PseudoJet> all_constituents = jet.constituents();
+    vector<PseudoJet> regular_constituents, ghosts;  
+
+    for (vector<PseudoJet>::iterator it = all_constituents.begin(); 
+         it != all_constituents.end(); it++){
+      if (it->is_pure_ghost())
+        ghosts.push_back(*it);
+      else
+        regular_constituents.push_back(*it);
+    }
+
+    // figure out the ghost area from the 1st ghost (if none, any value
+    // would probably do as the area will be 0 and subtraction will have
+    // no effect!)
+    double ghost_area = (ghosts.size()) ? ghosts[0].area() : 0.01;
+    ClusterSequenceActiveAreaExplicitGhosts * csa
+      = new ClusterSequenceActiveAreaExplicitGhosts(regular_constituents, 
+                                                    subjet_def, 
+                                                    ghosts, ghost_area);
+
+    subjets = csa->inclusive_jets();
+
+    // allow the cs to be deleted when it's no longer used
+    // 
+    // Note that there is at least one constituent in the jet so there
+    // is in principle at least one subjet But one may have used a
+    // nasty recombiner that left an empty set of subjets, so we'd
+    // rather play it safe
+    if (subjets.size())
+      csa->delete_self_when_unused();
+    else
+      delete csa;
+  } else {
+    ClusterSequence * cs = new ClusterSequence(jet.constituents(), subjet_def);
+    subjets = cs->inclusive_jets();
+    // allow the cs to be deleted when it's no longer used (again, we
+    // add an extra safety check)
+    if (subjets.size())
+      cs->delete_self_when_unused();
+    else 
+      delete cs;
+  }
+}
+
+
+//----------------------------------------------------------------------
+// various checks and internal constructs
+//----------------------------------------------------------------------
+
+// fundamental info for CompositeJets
+//----------------------------------------------------------------------
+ 
+// get the pieces down to the fundamental pieces
+// 
+// Note that this just checks that there is an associated CS to the
+// fundamental pieces, not that it is still valid
+bool Recluster::_get_all_pieces(const PseudoJet &jet, vector<PseudoJet> &all_pieces) const{
+  if (jet.has_associated_cluster_sequence()){
+    all_pieces.push_back(jet);
+    return true;
+  }
+
+  if (jet.has_pieces()){
+    const vector<PseudoJet> pieces = jet.pieces();
+    for (vector<PseudoJet>::const_iterator it=pieces.begin(); it!=pieces.end(); it++)
+      if (!_get_all_pieces(*it, all_pieces)) return false;
+    return true;
+  }
+
+  return false;
+}
+
+// treatment of recombiners
+//----------------------------------------------------------------------
+// get the common recombiner to all pieces (NULL if none)
+//
+// Note that if the jet has an associated cluster sequence that is no
+// longer valid, an error will be thrown (needed since it could be the
+// 1st check called after the enumeration of the pieces)
+const JetDefinition::Recombiner* Recluster::_get_common_recombiner(const vector<PseudoJet> &all_pieces) const{
+  const JetDefinition & jd_ref = all_pieces[0].validated_cs()->jet_def();
+  for (unsigned int i=1; i<all_pieces.size(); i++)
+    if (!all_pieces[i].validated_cs()->jet_def().has_same_recombiner(jd_ref)) return NULL;
+
+  return jd_ref.recombiner();
+}
+  
+void Recluster::_build_jet_def_with_recombiner(const vector<PseudoJet> &all_pieces, 
+                                               JetDefinition &subjet_def) const{
+  // the recombiner has to be guessed from the pieces
+  const JetDefinition::Recombiner * common_recombiner = _get_common_recombiner(all_pieces);
+  if (common_recombiner) {
+    if (typeid(*common_recombiner) == typeid(JetDefinition::DefaultRecombiner)) {
+      RecombinationScheme scheme = 
+        static_cast<const JetDefinition::DefaultRecombiner *>(common_recombiner)->scheme();
+      if (_has_subjet_extra)
+        subjet_def = JetDefinition(_subjet_alg, _subjet_radius, _subjet_extra, scheme);
+      else if (_has_subjet_radius)
+        subjet_def = JetDefinition(_subjet_alg, _subjet_radius, scheme);
+      else 
+        subjet_def = JetDefinition(_subjet_alg, scheme);
+    } else {
+      if (_has_subjet_extra)
+        subjet_def = JetDefinition(_subjet_alg, _subjet_radius, _subjet_extra, common_recombiner);
+      else if (_has_subjet_radius)
+        subjet_def = JetDefinition(_subjet_alg, _subjet_radius, common_recombiner);
+      else 
+        subjet_def = JetDefinition(_subjet_alg, common_recombiner);
+    }
+  } else {
+    throw Error("Recluster: requested to guess the recombination scheme (or recombiner) from the original jet but an inconsistency was found between the pieces constituing that jet.");
+  }
+}
+
+// area support
+//----------------------------------------------------------------------
+
+// check if the jet (or all its pieces) have explicit ghosts
+// (assuming the jet has area support).
+//
+// Note that if the jet has an associated cluster sequence that is no
+// longer valid, an error will be thrown (needed since it could be the
+// 1st check called after the enumeration of the pieces)
+bool Recluster::_check_explicit_ghosts(const vector<PseudoJet> &all_pieces) const{
+  for (vector<PseudoJet>::const_iterator it=all_pieces.begin(); it!=all_pieces.end(); it++)
+    if (! it->validated_csab()->has_explicit_ghosts()) return false;
+  return true;
+}
+
+// C/A specific tests
+//----------------------------------------------------------------------
+
+// check if one can apply the simplification for C/A subjets
+//
+// This includes:
+//  - the subjet definition asks for C/A subjets
+//  - all the pieces share the same CS
+//  - that CS is C/A with the same recombiner as the subjet def
+//  - the filtering radius is not larger than any of the pairwise
+//    distance between the pieces
+//
+// Note that if the jet has an associated cluster sequence that is no
+// longer valid, an error will be thrown (needed since it could be the
+// 1st check called after the enumeration of the pieces)
+bool Recluster::_check_ca(const vector<PseudoJet> &all_pieces, 
+                          const JetDefinition &subjet_def) const{
+  if (subjet_def.jet_algorithm() != cambridge_algorithm) return false;
+
+  // check that the 1st of all the pieces (we're sure there is at
+  // least one) is coming from a C/A clustering. Then check that all
+  // the following pieces share the same ClusterSequence
+  const ClusterSequence * cs_ref = all_pieces[0].validated_cs();
+  if (cs_ref->jet_def().jet_algorithm() != cambridge_algorithm) return false;
+  for (unsigned int i=1; i<all_pieces.size(); i++)
+    if (all_pieces[i].validated_cs() != cs_ref) return false;
+
+  // check that the 1st peice has the same recombiner as the one used
+  // for the subjet clustering
+  // Note that since they share the same CS, checking the 1st one is enough
+  if (!cs_ref->jet_def().has_same_recombiner(subjet_def)) return false;
+
+  // we also have to make sure that the reclustering radius is not larger
+  // than any of the inter-pieces distance
+  double Rsub2 = subjet_def.R();
+  Rsub2 *= Rsub2;
+  for (unsigned int i=0; i<all_pieces.size()-1; i++){
+    for (unsigned int j=i+1; j<all_pieces.size(); j++){
+      if (all_pieces[i].squared_distance(all_pieces[j]) <  Rsub2) return false;
+    }
+  }
+
+  return true;
+}
+
+} // contrib namespace
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: external/fastjet/contribs/RecursiveTools/Recluster.hh
===================================================================
--- external/fastjet/contribs/RecursiveTools/Recluster.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/Recluster.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,183 @@
+#ifndef __FASTJET_TOOLS_RECLUSTER_HH__
+#define __FASTJET_TOOLS_RECLUSTER_HH__
+
+// $Id: Recluster.hh 700 2014-07-07 12:50:05Z gsoyez $
+//
+// Copyright (c) 2014-, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include <fastjet/JetDefinition.hh>
+#include <fastjet/CompositeJetStructure.hh> // to derive the ReclusterStructure from CompositeJetStructure
+#include <fastjet/tools/Transformer.hh>     // to derive Recluster from Transformer
+#include <iostream>
+#include <string>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+namespace contrib{
+
+//----------------------------------------------------------------------
+/// \class Recluster
+/// Class that helps reclustering a jet with a new jet definition
+///
+/// The result of the reclustering is returned as a single PseudoJet
+/// with a CompositeJet structure. The pieces of that PseudoJet will
+/// be the individual subjets
+///
+/// When constructed from a JetDefinition, that definition will be
+/// used to obtain the subjets.  When constructed from a JetAlgorithm
+/// and parameters (0 parameters for e+e-, just R or R and an extra
+/// parameter for others) the recombination scheme will be taken as
+/// the same one used to initially cluster the original jet.
+///
+/// The result of this transformer depends on its usage. There are two
+/// typical use-cases: either we recluster one fat jet into subjets,
+/// OR, we recluster the jet with a different jet alg. When Recluster
+/// is created from a full jet definition. The last parameter of the
+/// constructors below dicatate that behaviour: if "single" is true
+/// (the default), a single jet, issued from a regular clustering is
+/// returned (if there are more than one, the hardest is taken);
+/// otherwise (single==false), the result will be a composite jet with
+/// each subjet as pieces
+/// 
+/// Open points for discussion:
+///
+///  - do we add an option to force area support? [could be useful
+///    e.g. for the filter with a subtractor where area support is
+///    mandatory]
+///
+class Recluster : public Transformer {
+public:
+  /// define a recluster that decomposes a jet into subjets using a
+  /// generic JetDefinition
+  ///
+  ///  \param subjet_def   the jet definition applied to obtain the subjets
+  ///  \param single       when true, cluster the jet in a single jet (the
+  ///                      hardest one) with an associated ClusterSequence, 
+  ///                      otherwise return a composite jet with subjets
+  ///                      as pieces.
+  Recluster(const JetDefinition & subjet_def, bool single=true)
+    : _subjet_def(subjet_def), _use_full_def(true), _single(single) {}
+
+  /// define a recluster that decomposes a jet into subjets using a
+  /// JetAlgorithm and its parameters
+  ///
+  ///  \param subjet_alg    the jet algorithm applied to obtain the subjets
+  ///  \param subjet_radius the jet radius if required
+  ///  \param subjet_extra  optional extra parameters for the jet algorithm (only when needed)
+  ///  \param single        when true, cluster the jet in a single jet (the
+  ///                       hardest one) with an associated ClusterSequence, 
+  ///                       otherwise return a composite jet with subjets
+  ///                       as pieces.
+  /// 
+  /// Typically, for e+e- algoriothm you should use the third version
+  /// below with no parameters, for "standard" pp algorithms, just the
+  /// clustering radius has to be specified and for genkt-type of
+  /// algorithms, both the radius and the extra parameter have to be
+  /// specified.
+  Recluster(JetAlgorithm subjet_alg, double subjet_radius, double subjet_extra,
+            bool single=true)
+    : _subjet_alg(subjet_alg), _use_full_def(false), 
+      _subjet_radius(subjet_radius), _has_subjet_radius(true), 
+      _subjet_extra(subjet_extra), _has_subjet_extra(true), _single(single) {}
+  Recluster(JetAlgorithm subjet_alg, double subjet_radius, bool single=true)
+    : _subjet_alg(subjet_alg), _use_full_def(false), 
+      _subjet_radius(subjet_radius), _has_subjet_radius(true),
+      _has_subjet_extra(false), _single(single) {}
+  Recluster(JetAlgorithm subjet_alg, bool single=true)
+    : _subjet_alg(subjet_alg), _use_full_def(false), 
+      _has_subjet_radius(false), _has_subjet_extra(false), _single(single) {}
+
+  /// default dtor
+  virtual ~Recluster(){};
+
+  //----------------------------------------------------------------------
+  // standard Transformer behaviour inherited from the base class
+  // (i.e. result(), description() and structural info)
+
+  /// runs the reclustering and sets kept and rejected to be the jets of interest
+  /// (with non-zero rho, they will have been subtracted).
+  ///
+  /// \param jet    the jet that gets reclustered
+  /// \return the reclustered jet
+  virtual PseudoJet result(const PseudoJet & jet) const;
+
+  /// class description
+  virtual std::string description() const;
+
+  // the type of the associated structure
+  typedef CompositeJetStructure StructureType;
+
+private:
+  /// set the reclustered elements in the simple case of C/A+C/A
+  void _recluster_cafilt(const std::vector<PseudoJet> & all_pieces,
+                         std::vector<PseudoJet> & subjets,
+                         double Rfilt) const;
+
+  /// set the reclustered elements in the generic re-clustering case
+  void _recluster_generic(const PseudoJet & jet, 
+                          std::vector<PseudoJet> & subjets,
+                          const JetDefinition & subjet_def,
+                          bool do_areas) const;
+  
+  // a series of checks
+  //--------------------------------------------------------------------
+  /// get the pieces down to the fundamental pieces
+  bool _get_all_pieces(const PseudoJet &jet, std::vector<PseudoJet> &all_pieces) const;
+
+  /// get the common recombiner to all pieces (NULL if none)
+  const JetDefinition::Recombiner* _get_common_recombiner(const std::vector<PseudoJet> &all_pieces) const;
+
+  /// construct the proper jet definition ensuring that the recombiner
+  /// is taken from the underlying pieces (an error is thrown if the
+  /// pieces do no share a common recombiner)
+  void _build_jet_def_with_recombiner(const std::vector<PseudoJet> &all_pieces, 
+                                      JetDefinition &subjet_def) const;
+
+  /// check if one can apply the simplified trick for C/A subjets
+  bool _check_ca(const std::vector<PseudoJet> &all_pieces, 
+                 const JetDefinition &subjet_def) const;
+
+  /// check if the jet (or all its pieces) have explicit ghosts
+  /// (assuming the jet has area support
+  ///
+  /// Note that if the jet has an associated cluster sequence that is no
+  /// longer valid, an error will be thrown
+  bool _check_explicit_ghosts(const std::vector<PseudoJet> &all_pieces) const;
+
+  JetDefinition _subjet_def;   ///< the jet definition to use to extract the subjets
+  JetAlgorithm  _subjet_alg;   ///< the jet algorithm to be used
+  bool _use_full_def;          ///< true when the full JetDefinition is supplied to the ctor
+  double _subjet_radius;       ///< the jet radius (only if needed for the jet alg)
+  bool _has_subjet_radius;     ///< the subjet radius has been specified
+  double _subjet_extra;        ///< the jet alg extra param (only if needed)
+  bool _has_subjet_extra;      ///< the extra param has been specified
+
+  bool _single;                ///< (true) return a single jet with a
+                               ///< regular clustering or (false) a
+                               ///< composite jet with subjets as pieces
+
+  static LimitedWarning   _explicit_ghost_warning;
+};
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif   // __FASTJET_TOOLS_RECLUSTER_HH__
Index: external/fastjet/contribs/RecursiveTools/RecursiveSymmetryCutBase.cc
===================================================================
--- external/fastjet/contribs/RecursiveTools/RecursiveSymmetryCutBase.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/RecursiveSymmetryCutBase.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,281 @@
+// $Id: RecursiveSymmetryCutBase.cc 700 2014-07-07 12:50:05Z gsoyez $
+//
+// Copyright (c) 2014-, Gavin P. Salam, Gregory Soyez, Jesse Thaler
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include "RecursiveSymmetryCutBase.hh"
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include <algorithm> 
+#include <cstdlib> 
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+namespace contrib{
+
+LimitedWarning RecursiveSymmetryCutBase::_negative_mass_warning;
+LimitedWarning RecursiveSymmetryCutBase::_mu2_gt1_warning;
+//LimitedWarning RecursiveSymmetryCutBase::_nonca_warning;
+LimitedWarning RecursiveSymmetryCutBase::_explicit_ghost_warning;
+
+bool RecursiveSymmetryCutBase::_verbose = false;
+
+//----------------------------------------------------------------------
+PseudoJet RecursiveSymmetryCutBase::result(const PseudoJet & jet) const {
+  // construct the input jet (by default, recluster with C/A)
+
+  if (! jet.has_constituents()){
+    throw Error("RecursiveSymmetryCutBase can only be applied to jets with constituents");
+  }
+
+  PseudoJet j = 
+    _do_reclustering 
+      ? _recluster ? (*_recluster)(jet)
+                   : Recluster(cambridge_algorithm, JetDefinition::max_allowable_R)(jet)
+      : jet;
+    
+  // issue a warning if the jet is not obtained through a C/A
+  // clustering
+  // if ((! j.has_associated_cluster_sequence()) ||
+  //     (j.validated_cs()->jet_def().jet_algorithm() != cambridge_algorithm))
+  //  _nonca_warning.warn("RecursiveSymmetryCutBase is designed to be applied on jets from a Cambridge/Aachen clustering; use it with other algorithms at your own risk.");
+
+  if (! j.has_valid_cluster_sequence()){
+    throw Error("RecursiveSymmetryCutBase can only be applied to jets associated to a (valid) cluster sequence");
+  }
+
+  if (_subtractor) {
+    const ClusterSequenceAreaBase * csab = 
+      dynamic_cast<const ClusterSequenceAreaBase *>(j.associated_cs());
+    if (csab == 0 || (!csab->has_explicit_ghosts()))
+      _explicit_ghost_warning.warn("RecursiveSymmetryCutBase: there is no clustering sequence, or it lacks explicit ghosts: subtraction is not guaranteed to function properly");
+  }
+
+  // establish the first subjet and optionally subtract it
+  PseudoJet subjet = j;
+  if (_subtractor && (!_input_jet_is_subtracted)) {
+    subjet = (*_subtractor)(subjet);
+  }
+
+  bool use_mu_cut = (_mu_cut != numeric_limits<double>::infinity());
+
+  // variables for tracking what will happen
+  PseudoJet piece1, piece2;
+ 
+  // vectors for storing optional verbose structure
+  // these hold the deltaR, symmetry, and mu values of dropped branches
+  std::vector<double> dropped_delta_R;
+  std::vector<double> dropped_symmetry;
+  std::vector<double> dropped_mu;
+  
+  // now recurse into the jet's structure
+  while (subjet.has_parents(piece1, piece2)) {
+    
+    // first sanity check: 
+    // - zero or negative pts are not allowed for the input subjet
+    // - zero or negative masses are not allowed for configurations
+    //   in which the mass will effectively appear in a denominator
+    //   (The masses will be checked later)
+    if (subjet.pt2() <= 0) return PseudoJet();
+
+    if (_subtractor) {
+      piece1 = (*_subtractor)(piece1);
+      piece2 = (*_subtractor)(piece2);
+    }
+    
+    // determine the symmetry parameter
+    double sym;
+
+    if        (_symmetry_measure == y) {
+      // the original d_{ij}/m^2 choice from MDT
+      // first make sure the mass is sensible
+      if (subjet.m2() <= 0) {
+        _negative_mass_warning.warn("RecursiveSymmetryCutBase: cannot calculate y, because (sub)jet mass is negative; bailing out");
+        return _result_no_substructure(subjet); //TBC: do we return the hardest parent? A NULL PseudoJet?
+      }
+      sym = piece1.kt_distance(piece2) / subjet.m2();
+
+    } else if (_symmetry_measure == vector_z) {
+      // min(pt1, pt2)/(pt), where the denominator is a vector sum
+      // of the two subjets
+      sym = min(piece1.pt(), piece2.pt()) / subjet.pt();
+
+    } else if (_symmetry_measure == scalar_z) {
+      // min(pt1, pt2)/(pt1+pt2), where the denominator is a scalar sum
+      // of the two subjets
+      double pt1 = piece1.pt();
+      double pt2 = piece2.pt();
+      // make sure denominator is non-zero
+      sym = pt1 + pt2;
+      if (sym == 0) return PseudoJet(); 
+      sym = min(pt1, pt2) / sym;
+
+    } else {
+      throw Error ("Unrecognized choice of symmetry_measure");
+    }
+
+    // determine the symmetry cut
+    // (This function is specified in the derived classes)
+    double this_symmetry_cut = symmetry_cut_fn(piece1, piece2);
+
+    // and make a first tagging decision based on symmetry cut
+    bool tagged = (sym > this_symmetry_cut);
+
+    // if tagged based on symmetry cut, then check the mu cut (if relevant)
+    // and update the tagging decision. Calculate mu^2 regardless, for cases
+    // of users not cutting on mu2, but still interested in its value.
+    double mu2 = max(piece1.m2(), piece2.m2())/subjet.m2();
+    if (tagged && use_mu_cut) {
+      // first a sanity check -- mu2 won't be sensible if the subjet mass 
+      // is negative, so we can't then trust the mu cut - bail out
+      if (subjet.m2() <= 0) {
+        _negative_mass_warning.warn("RecursiveSymmetryCutBase: cannot trust mu, because (sub)jet mass is negative; bailing out");
+        return PseudoJet();
+      }
+      if (mu2 > 1) _mu2_gt1_warning.warn("RecursiveSymmetryCutBase encountered mu^2 value > 1");
+      if (mu2 > pow(_mu_cut,2)) tagged = false;
+    }
+
+
+    // if we've tagged the splitting, return the jet with its substructure
+    if (tagged) {
+      // record relevant information
+      StructureType * structure = new StructureType(subjet);
+      structure->_symmetry = sym;
+      structure->_mu       = (mu2 >= 0) ? sqrt(mu2) : -sqrt(-mu2);
+      structure->_delta_R  = piece1.delta_R(piece2);
+      if (_verbose_structure) {
+        structure->_has_verbose = true;
+        structure->_dropped_symmetry = dropped_symmetry;
+        structure->_dropped_mu = dropped_mu;
+        structure->_dropped_delta_R = dropped_delta_R;
+      }
+      subjet.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(structure));
+      return subjet;
+    }
+    
+    // if desired, store information about dropped branches before recursing
+    if (_verbose_structure) {
+      dropped_delta_R.push_back(piece1.delta_R(piece2));
+      dropped_symmetry.push_back(sym);
+      dropped_mu.push_back((mu2 >= 0) ? sqrt(mu2) : -sqrt(-mu2));
+    }
+    
+    // otherwise continue unclustering, allowing for the different
+    // ways of choosing which parent to look into
+    int choice;
+    if        (_recursion_choice == larger_mt) {
+      choice = piece1.mt2() > piece2.mt2() ? 1 : 2;
+
+    } else if (_recursion_choice == larger_pt) {
+      choice = piece1.pt2() > piece2.pt2() ? 1 : 2;
+
+    } else if (_recursion_choice == larger_m)  {
+      choice = piece1.m2()  > piece2.m2()  ? 1 : 2;
+
+    } else {
+      throw Error ("Unrecognized value for recursion_choice");
+    }    
+    if (_verbose) cout << "choice is " << choice << endl;;
+    subjet = (choice == 1) ? piece1 : piece2;
+  } // (subjet.has_parents(...))
+
+  if (_verbose) cout << "reached end; returning null jet " << endl;
+  
+  // decide on tagging versus grooming mode here
+  PseudoJet result = _result_no_substructure(subjet);
+  
+  if (result != 0) {
+    // if in grooming mode, add dummy structure information
+    StructureType * structure = new StructureType(result);
+    structure->_symmetry = 0.0;
+    structure->_mu       = 0.0;
+    structure->_delta_R  = 0.0;
+    if (_verbose_structure) { // still want to store verbose information about dropped branches
+      structure->_has_verbose = true;
+      structure->_dropped_symmetry = dropped_symmetry;
+      structure->_dropped_mu = dropped_mu;
+      structure->_dropped_delta_R = dropped_delta_R;
+    }
+    result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(structure));
+  }
+  
+  return result;
+}
+
+
+//----------------------------------------------------------------------
+string RecursiveSymmetryCutBase::description() const {
+  ostringstream ostr;
+  ostr << "Recursive " << (_grooming_mode ? "Groomer" : "Tagger") << " with a symmetry cut ";
+
+  switch(_symmetry_measure) {
+  case y:
+    ostr << "y"; break;
+  case scalar_z:
+    ostr << "scalar_z"; break;
+  case vector_z:
+    ostr << "vector_z"; break;
+  default:
+    cerr << "failed to interpret symmetry_measure" << endl; exit(-1);
+  }
+  ostr << " > " << symmetry_cut_description();
+
+  if (_mu_cut != numeric_limits<double>::infinity()) {
+    ostr << ", mass-drop cut mu=max(m1,m2)/m < " << _mu_cut;
+  } else {
+    ostr << ", no mass-drop requirement";
+  }
+
+  ostr << ", recursion into the subjet with larger ";
+  switch(_recursion_choice) {
+  case larger_pt:
+    ostr << "pt"; break;
+  case larger_mt:
+    ostr << "mt(=sqrt(m^2+pt^2))"; break;
+  case larger_m:
+    ostr << "mass"; break;
+  default:
+    cerr << "failed to interpret recursion_choice" << endl; exit(-1);
+  }
+
+  if (_subtractor) {
+    ostr << " and subtractor: " << _subtractor->description();
+    if (_input_jet_is_subtracted) {ostr << " (input jet is assumed already subtracted)";}
+  }
+  return ostr.str();
+}
+
+// decide what to return when no substructure has been found
+PseudoJet RecursiveSymmetryCutBase::_result_no_substructure(const PseudoJet &last_parent) const{
+  if (_grooming_mode){
+    // in grooming mode, return the last parent
+    return last_parent;
+  } else {
+    // in tagging mode, return an empty PseudoJet
+    return PseudoJet();
+  }
+}
+
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
Index: external/fastjet/contribs/RecursiveTools/RecursiveSymmetryCutBase.hh
===================================================================
--- external/fastjet/contribs/RecursiveTools/RecursiveSymmetryCutBase.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/RecursiveSymmetryCutBase.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,300 @@
+// $Id: RecursiveSymmetryCutBase.hh 700 2014-07-07 12:50:05Z gsoyez $
+//
+// Copyright (c) 2014-, Gavin P. Salam, Gregory Soyez, Jesse Thaler
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#ifndef __FASTJET_CONTRIB_RECURSIVESYMMETRYCUTBASE_HH__
+#define __FASTJET_CONTRIB_RECURSIVESYMMETRYCUTBASE_HH__
+
+#include <limits>
+#include <fastjet/internal/base.hh>
+#include "fastjet/tools/Transformer.hh"
+#include "fastjet/WrappedStructure.hh"
+
+#include "Recluster.hh"
+
+/** \mainpage RecursiveTools contrib 
+
+    The aims RecursiveTools contrib to provide a set of tools for
+    recursive investigation of the substructure of jets.
+
+    Currently it includes:
+    - fastjet::contrib::ModifiedMassDropTagger
+    - fastjet::contrib::SoftDrop
+    - the two above classes derive from fastjet::contrib::RecursiveSymmetryCutBase
+    - fastjet::contrib::Recluster provides a reclustering transformer
+    - example*.cc provides a usage examples
+ */
+
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+namespace contrib{
+
+//------------------------------------------------------------------------
+/// \class RecursiveSymmetryCutBase
+/// A base class for all the tools that de-cluster a jet until a
+/// sufficiently symmetric configuration if found.
+///
+/// Derived classes (so far, ModifiedMassDropTagger and SoftDrop) have to
+/// implement the symmetry cut and its description
+///
+/// Note that by default, the jet will be reculstered with
+/// Cambridge/Aachen before applying the de-clustering procedure. This
+/// behaviour can be changed using set_clustering (see below).
+///
+/// By default, this class behaves as a tagger, i.e. returns an empty
+/// PseudoJet if no substructure is found.  While the derived
+/// ModifiedMassDropTagger is a tagger, the derived SoftDrop is a groomer
+/// (i.e. it returns a non-zero jet even if no substructure is found).
+///
+/// This class provides support for
+///  - an optional mass-drop cut (see ctor)
+///  - options to select which symmetry measure should be used (see ctor)
+///  - options to select how the recursion proceeds (see ctor)
+///  - options for reclustering the jet before running the de-clustering
+///    (see set_reclustering)
+///  - an optional subtractor (see ctor and other methods below)
+class RecursiveSymmetryCutBase : public Transformer {
+public:
+  // ctors and dtors
+  //----------------------------------------------------------------------
+
+  /// an enum of the different (a)symmetry measures that can be used
+  enum SymmetryMeasure{scalar_z, ///< \f$ \min(p_{ti}, p_{tj})/(p_{ti} + p_{tj}) \f$
+                       vector_z, ///< \f$ \min(p_{ti}, p_{tj})/p_{t(i+j)} \f$
+                       y         ///  \f$ \min(p_{ti}^2,p_{tj}^2) \Delta R_{ij}^2 / m_{ij}^2 \f$
+                       
+  };
+
+  /// an enum for the options of how to choose which of two subjets to recurse into
+  enum RecursionChoice{larger_pt, ///< choose the subjet with larger \f$ p_t \f$
+                       larger_mt, ///< choose the subjet with larger \f$ m_t \equiv (m^2+p_t^2)^{\frac12}] \f$
+                       larger_m   ///  choose the subjet with larger mass (deprecated)
+  }; 
+
+  /// Full constructor, which takes the following parameters:
+  ///
+  /// \param symmetry_measure   the choice of measure to use to estimate the symmetry
+  /// \param mu_cut             the maximal allowed value of mass drop variable mu = m_heavy/m_parent 
+  /// \param recursion_choice   the strategy used to decide which subjet to recurse into
+  /// \param subtractor         an optional pointer to a pileup subtractor (ignored if zero)
+  ///
+  /// If the (optional) pileup subtractor is supplied, then, by
+  /// default, the input jet is assumed unsubtracted and the
+  /// RecursiveSymmetryCutBase returns a subtracted 4-vector. [see
+  /// also the set_input_jet_is_subtracted() member function].
+  ///
+  RecursiveSymmetryCutBase(SymmetryMeasure  symmetry_measure = scalar_z,
+			   double           mu_cut = std::numeric_limits<double>::infinity(), 
+			   RecursionChoice  recursion_choice = larger_pt,
+			   const FunctionOfPseudoJet<PseudoJet> * subtractor = 0
+			   ) : 
+    _symmetry_measure(symmetry_measure),
+    _mu_cut(mu_cut),
+    _recursion_choice(recursion_choice),
+    _subtractor(subtractor), _input_jet_is_subtracted(false),
+    _do_reclustering(true), _recluster(0),
+    _grooming_mode(false),
+    _verbose_structure(false) // by default, don't story verbose information
+  {}
+    
+  /// default destructor
+  virtual ~RecursiveSymmetryCutBase(){}
+
+  // internal subtraction configuration
+  //----------------------------------------------------------------------
+
+  /// This tells the tagger whether to assume that the input jet has
+  /// already been subtracted. This is relevant only if a non-null
+  /// subtractor pointer has been supplied, and the default assymption
+  /// is that the input jet is passed unsubtracted.
+  /// 
+  /// Note: given that subtractors usually change the momentum of the
+  /// main jet, but not that of the subjets, subjets will continue to
+  /// have subtraction applied to them.
+  void set_input_jet_is_subtracted(bool is_subtracted) {_input_jet_is_subtracted = is_subtracted;}
+
+  /// returns a bool to indicate if the input jet is assumed already subtracted
+  bool input_jet_is_subtracted() const {return _input_jet_is_subtracted;}
+
+  /// an alternative way to set the subtractor
+  ///
+  /// Note that when a subtractor is provided, the result of the
+  /// RecursiveSymmetryCutBase will be a subtracted jet.
+  void set_subtractor(const FunctionOfPseudoJet<PseudoJet> * subtractor_) {_subtractor = subtractor_;}
+
+  /// returns a pointer to the subtractor
+  const FunctionOfPseudoJet<PseudoJet> * subtractor() const {return _subtractor;}
+
+  // reclustering behaviour
+  //----------------------------------------------------------------------
+
+  /// configure the reclustering prior to the SoftDrop de-clustering
+  ///  \param do_reclustering   recluster the jet or not?
+  ///  \param recluster         how to recluster the jet 
+  ///                           (only if do_recluster is true; 
+  ///                           Cambridge/Aachen used if NULL)
+  ///
+  /// Note that the ModifiedMassDropTagger and SoftDrop are designed
+  /// to work with a Cambridge/Aachen clustering. Use any other option
+  /// at your own risk!
+  void set_reclustering(bool do_reclustering=true, const Recluster *recluster=0){
+    _do_reclustering = do_reclustering;
+    _recluster = recluster;
+  }
+
+  // what to do when no substructure is found
+  //----------------------------------------------------------------------
+  /// specify the behaviour adopted when no substructure is found
+  ///  - in tagging  mode, an empty PseudoJet will be returned
+  ///  - in grooming mode, a single particle is returned
+  /// for clarity, we provide both function although they are redundant
+  void set_grooming_mode(bool enable=true){ _grooming_mode = enable;}
+  void set_tagging_mode(bool enable=true){ _grooming_mode = !enable;}
+
+  
+  /// Allows access to verbose information about recursive declustering,
+  /// in particular values of symmetry, delta_R, and mu of dropped branches
+  void set_verbose_structure(bool enable=true) { _verbose_structure = enable; }
+  
+  
+  // inherited from the Transformer base
+  //----------------------------------------------------------------------
+
+  /// the function that carries out the tagging; if a subtractor is
+  /// being used, then this function assumes that input jet is
+  /// unsubtracted (unless set_input_jet_is_subtracted(true) has been
+  /// explicitly called before) and the result of the MMDT will be a
+  /// subtracted jet.
+  virtual PseudoJet result(const PseudoJet & j) const;
+
+  /// description of the tool
+  virtual std::string description() const;
+
+  /// the type of the associated structure
+  //typedef RecursiveSymmetryCutBaseStructure StructureType;  
+
+  class StructureType;
+
+  /// for testing 
+  static bool _verbose;
+
+protected:
+  // the methods below have to be defined by deerived classes
+  //----------------------------------------------------------------------
+  /// the cut on the symmetry measure (typically z) that one need to
+  /// apply for a given pair of subjets p1 and p2
+  virtual double symmetry_cut_fn(const PseudoJet & /* p1 */, 
+                                 const PseudoJet & /* p2 */) const = 0;
+  /// the associated dwescription
+  virtual std::string symmetry_cut_description() const = 0;
+
+private:
+  SymmetryMeasure  _symmetry_measure;
+  double           _mu_cut;
+  RecursionChoice  _recursion_choice;
+  const FunctionOfPseudoJet<PseudoJet> * _subtractor;
+  bool             _input_jet_is_subtracted;
+
+  bool _do_reclustering;       ///< start with a reclustering
+  const Recluster *_recluster; ///< how to recluster the jet
+
+  bool _grooming_mode;  ///< grooming or tagging mode
+
+  static LimitedWarning   _negative_mass_warning;
+  static LimitedWarning   _mu2_gt1_warning;
+  //static LimitedWarning   _nonca_warning;
+  static LimitedWarning   _explicit_ghost_warning;
+
+  // additional verbose structure information
+  bool _verbose_structure;
+  
+  /// decide what to return when no substructure has been found
+  PseudoJet _result_no_substructure(const PseudoJet &last_parent) const;
+};
+
+  
+  
+//----------------------------------------------------------------------
+/// class to hold the structure of a jet tagged by RecursiveSymmetryCutBase.
+class RecursiveSymmetryCutBase::StructureType : public WrappedStructure {
+public:
+  StructureType(const PseudoJet & j) :
+    WrappedStructure(j.structure_shared_ptr()),
+    _has_verbose(false) // by default, do not store verbose structure
+  {}
+  
+  // information about kept branch
+  double delta_R()  const {return _delta_R;};
+  double symmetry() const {return _symmetry;};
+  double mu()       const {return _mu;};
+  
+  // additional verbose information about dropped branches
+  bool has_verbose() const { return _has_verbose;}
+  
+  // number of dropped branches
+  int dropped_count() const {
+    if (!_has_verbose) throw Error("RecursiveSymmetryCutBase::StructureType: Verbose structure must be turned on to get dropped_count() values.");
+    return _dropped_delta_R.size();
+  }
+  
+  // delta_R of dropped branches
+  std::vector<double> dropped_delta_R() const {
+    if (!_has_verbose) throw Error("RecursiveSymmetryCutBase::StructureType: Verbose structure must be turned on to get dropped_delta_R() values.");
+    return _dropped_delta_R;
+  }
+
+  // symmetry values of dropped branches
+  std::vector<double> dropped_symmetry() const {
+    if (!_has_verbose) throw Error("RecursiveSymmetryCutBase::StructureType: Verbose structure must be turned on to get dropped_symmetry() values.");
+    return _dropped_symmetry;
+  }
+
+  // mass drop values of dropped branches
+  std::vector<double> dropped_mu() const {
+    if (!_has_verbose) throw Error("RecursiveSymmetryCutBase::StructureType: Verbose structure must be turned on to get dropped_mu() values.");
+    return _dropped_mu;
+  }
+  
+  // maximum symmetry value dropped
+  double max_dropped_symmetry() const {
+    if (!_has_verbose) throw Error("RecursiveSymmetryCutBase::StructureType: Verbose structure must be turned on to get max_dropped_symmetry().");
+    if (_dropped_symmetry.size() == 0) return 0.0;
+    return *std::max_element(_dropped_symmetry.begin(),_dropped_symmetry.end());
+  }
+  
+private:
+  double _delta_R, _symmetry, _mu;
+  friend class RecursiveSymmetryCutBase;
+
+  // additional verbose information
+  bool _has_verbose;
+  // information about dropped values
+  std::vector<double> _dropped_delta_R;
+  std::vector<double> _dropped_symmetry;
+  std::vector<double> _dropped_mu;
+  
+};
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
+
+#endif  // __FASTJET_CONTRIB_RECURSIVESYMMETRYCUTBASE_HH__
Index: external/fastjet/contribs/RecursiveTools/SoftDrop.cc
===================================================================
--- external/fastjet/contribs/RecursiveTools/SoftDrop.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/SoftDrop.cc	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,72 @@
+// $Id: SoftDrop.cc 686 2014-06-14 03:25:09Z jthaler $
+//
+// Copyright (c) 2014-, Gregory Soyez, Jesse. Thaler
+// based on arXiv:1402.2657 by Andrew J. Larkoski, Simone Marzani,
+// Gregory Soyez, Jesse Thaler
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#include "SoftDrop.hh"
+#include <cmath>
+#include <sstream>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+namespace contrib{
+
+//----------------------------------------------------------------------
+// TODO:
+//
+// - implement reclustering (at the moment we assume it's C/A as for mMDT
+//
+// - what is returned if no substructure is found? [and for negativeve
+//   pt, m2 or other situations where mMDT currentlty returns an empty
+//   PseudoJet]
+//
+//   GS.: mMDT seeks substructure so it makes sense for it to return
+//   an empry PseudoJet when no substructure is found (+ it is the
+//   original behaviour). For SoftDrop, in grooming mode (beta>0), if
+//   would make sense to return a jet with a single particle. In
+//   tagging mode (beta<0), the situation is less clear. At the level
+//   of the implementation, having a virtual function could work
+//   (with a bit of care to cover the -ve pt or m2 cases)
+//
+// - Do we include Andrew and Simone in the "contrib-author" list
+//   since they are on the paper? Do we include Gavin in the author's
+//   list since he started this contrib?
+//
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+double SoftDrop::symmetry_cut_fn(const PseudoJet & p1, 
+                                 const PseudoJet & p2) const{
+  return _symmetry_cut * pow(p1.squared_distance(p2)/_R0sqr, 0.5*_beta);
+}
+
+//----------------------------------------------------------------------
+string SoftDrop::symmetry_cut_description() const {
+  ostringstream ostr;
+  ostr << _symmetry_cut << " (theta/" << sqrt(_R0sqr) << ")^" << _beta << " [SoftDrop]";
+  return ostr.str();
+}
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
Index: external/fastjet/contribs/RecursiveTools/SoftDrop.hh
===================================================================
--- external/fastjet/contribs/RecursiveTools/SoftDrop.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/SoftDrop.hh	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,139 @@
+// $Id: SoftDrop.hh 686 2014-06-14 03:25:09Z jthaler $
+//
+// Copyright (c) 2014-, Gregory Soyez, Jesse Thaler
+// based on arXiv:1402.2657 by Andrew J. Larkoski, Simone Marzani,
+// Gregory Soyez, Jesse Thaler
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet contrib.
+//
+// It is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at
+// your option) any later version.
+//
+// It is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this code. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+
+#ifndef __FASTJET_CONTRIB_SOFTDROP_HH__
+#define __FASTJET_CONTRIB_SOFTDROP_HH__
+
+#include "RecursiveSymmetryCutBase.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+namespace contrib{
+
+//------------------------------------------------------------------------
+/// \class SoftDrop
+/// An implementation of the SoftDrop from arXiv:1402.2657.
+///
+/// For the basic functionalities, we refer the reader to the
+/// documentation of the RecursiveSymmetryCutBase from which SoftDrop
+/// inherits. Here, we mostly put the emphasis on things specific to
+/// SoftDrop:
+///
+///  - the cut applied recursively is 
+///     \f[
+///        z > z_{\rm cut} (\theta/R0)^\beta
+///     \f]
+///    with z the asymmetry measure and \f$\theta\f$ the geometrical
+///    distance between the two subjets. R0 is set to 1 by default.
+///
+///  - by default, we work in "grooming mode" i.s. if no substructure
+///    is found, we return a jet made of a single parton. Note that
+///    this behaviour differs from the mMDT (and can be a source of
+///    differences when running SoftDrop with beta=0.)
+///
+class SoftDrop : public RecursiveSymmetryCutBase {
+public:
+  /// Simplified constructor. This takes the value of the "beta"
+  /// parameter and the symmetry cut (applied by default on the
+  /// scalar_z variable, as for the mMDT). It also takes an optional
+  /// subtractor.
+  ///
+  /// If the (optional) pileup subtractor can be supplied, then see
+  /// also the documentation for the set_input_jet_is_subtracted() member
+  /// function.
+  ///
+  /// \param beta               the value of the beta parameter
+  /// \param symmetry_cut       the value of the cut on the symmetry measure
+  /// \param R0                 the angular distance normalisation [1 by default]
+  SoftDrop(double beta,
+           double symmetry_cut,
+           double R0 = 1,
+           const FunctionOfPseudoJet<PseudoJet> * subtractor = 0) : 
+    RecursiveSymmetryCutBase(scalar_z,  // the default SymmetryMeasure
+                             std::numeric_limits<double>::infinity(), // default is no mass drop
+                             larger_pt, // the default RecursionChoice
+                             subtractor),
+    _beta(beta), _symmetry_cut(symmetry_cut), _R0sqr(R0*R0) {
+    // change the default: use grooming mode
+    set_grooming_mode();
+  }
+
+  /// Full constructor, which takes the following parameters:
+  ///
+  /// \param beta               the value of the beta parameter
+  /// \param symmetry_cut       the value of the cut on the symmetry measure
+  /// \param symmetry_measure   the choice of measure to use to estimate the symmetry
+  /// \param R0                 the angular distance normalisation [1 by default]
+  /// \param mu_cut             the maximal allowed value of mass drop variable mu = m_heavy/m_parent 
+  /// \param recursion_choice   the strategy used to decide which subjet to recurse into
+  /// \param subtractor         an optional pointer to a pileup subtractor (ignored if zero)
+  ///
+  /// The default values provided for this constructor are suited to
+  /// obtain the SoftDrop as discussed in arXiv:1402.2657:
+  ///  - no mass drop is requested
+  ///  - recursion follows the branch with the largest pt
+  /// The symmetry measure has to be specified (scalar_z is the recommended value)
+  ///
+  /// Notes: 
+  ///
+  /// - by default, SoftDrop will recluster the jet with the
+  ///   Cambridge/Aachen algorithm if it is not already the case. This
+  ///   behaviour can be changed using the "set_reclustering" method
+  ///   defined below
+  ///
+  SoftDrop(double           beta,
+           double           symmetry_cut, 
+           SymmetryMeasure  symmetry_measure,
+           double           R0 = 1.0,
+           double           mu_cut = std::numeric_limits<double>::infinity(), 
+           RecursionChoice  recursion_choice = larger_pt,
+           const FunctionOfPseudoJet<PseudoJet> * subtractor = 0) : 
+     RecursiveSymmetryCutBase(symmetry_measure, mu_cut, recursion_choice, subtractor),
+     _beta(beta), _symmetry_cut(symmetry_cut), _R0sqr(R0*R0)
+  {}
+
+  /// default destructor
+  virtual ~SoftDrop(){}
+
+protected:
+
+  // Unlike MMDT, the SoftDrop symmetry_cut_fn depends on the subjet kinematics
+  // since the symmetry condition depends on the DeltaR between subjets.
+  virtual double symmetry_cut_fn(const PseudoJet & /* p1 */, 
+                                 const PseudoJet & /* p2 */) const;
+  virtual std::string symmetry_cut_description() const;
+
+private:
+  double _beta;         ///< the power of the angular distance to be used
+                        ///< in the symmetry condition
+  double _symmetry_cut; ///< the value of zcut (the prefactor in the asymmetry cut)
+  double _R0sqr;        ///< normalisation of the angular distance
+                        ///< (typically set to the jet radius, 1 by default)
+};
+
+} // namespace contrib
+
+FASTJET_END_NAMESPACE
+
+#endif  // __FASTJET_CONTRIB_SOFTDROP_HH__
Index: external/fastjet/contribs/RecursiveTools/TODO
===================================================================
--- external/fastjet/contribs/RecursiveTools/TODO	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/TODO	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,8 @@
+For future releases?
+--------------------
+- JDT:  In Recluster, change "single" to an enum for user clarity?
+  [do we have any other option that "sungle" or "subjets"]
+- JDT:  Should we have a FASTJET_CONTRIB_BEGIN_NAMESPACE?  It would
+  help those of us who use XCode to edit, which is aggressive about
+  auto-indenting. [Consider this for the full contrib??]
+- More generic kinematic cuts?
Index: external/fastjet/contribs/RecursiveTools/VERSION
===================================================================
--- external/fastjet/contribs/RecursiveTools/VERSION	(revision 666d7956227a7de702863f32a3d79046f190a264)
+++ external/fastjet/contribs/RecursiveTools/VERSION	(revision 666d7956227a7de702863f32a3d79046f190a264)
@@ -0,0 +1,1 @@
+1.0.0
