From 97c4081b465fb44e29077cea22fc1f943bcf5890 Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Tue, 3 Mar 2015 17:37:17 +0100
Subject: [PATCH] v12r5g1

---
 Phys/Swimming/cmt/requirements                |  41 ++
 Phys/Swimming/cmt/version.cmt                 |   1 +
 Phys/Swimming/dict/functions.h                |  16 +
 Phys/Swimming/dict/functions.xml              |   5 +
 Phys/Swimming/doc/release.notes               | 134 ++++
 Phys/Swimming/example/DecayTreeTuple.py       | 105 +++
 Phys/Swimming/example/DecayTreeTupleD2hh.py   | 105 +++
 Phys/Swimming/example/SwimStrippingB2JpsiX.py |  35 +
 Phys/Swimming/example/SwimStrippingD2hh.py    |  34 +
 Phys/Swimming/example/SwimTriggerB2JpsiX.py   |  36 +
 Phys/Swimming/example/SwimTriggerD2hh.py      |  36 +
 .../Swimming/python/Swimming/Configuration.py | 364 ++++++++++
 Phys/Swimming/python/Swimming/EventLoop.py    | 359 ++++++++++
 Phys/Swimming/python/Swimming/GeneralSetup.py |  16 +
 .../python/Swimming/GetVeloAcceptance.py      |  55 ++
 Phys/Swimming/python/Swimming/Globals.py      |  51 ++
 .../Swimming/python/Swimming/HltTransforms.py |  66 ++
 Phys/Swimming/python/Swimming/MooreSetup.py   |  12 +
 .../python/Swimming/OfflineSelExample.py      |  80 +++
 Phys/Swimming/python/Swimming/RefineTPs.py    |  66 ++
 .../python/Swimming/SwimmingTisTos.py         | 158 +++++
 .../Swimming/python/Swimming/SwimmingUtils.py | 136 ++++
 Phys/Swimming/python/Swimming/decorators.py   |  36 +
 Phys/Swimming/scripts/RunSwimming.py          | 632 ++++++++++++++++++
 Phys/Swimming/scripts/SubmitJobExample.py     |  55 ++
 Phys/Swimming/src/functions.cpp               |  66 ++
 PhysSys/cmt/requirements                      |   5 +-
 PhysSys/cmt/version.cmt                       |   2 +-
 PhysSys/doc/release.notes                     |   3 +
 cmt/project.cmt                               |   2 +-
 30 files changed, 2709 insertions(+), 3 deletions(-)
 create mode 100644 Phys/Swimming/cmt/requirements
 create mode 100644 Phys/Swimming/cmt/version.cmt
 create mode 100644 Phys/Swimming/dict/functions.h
 create mode 100644 Phys/Swimming/dict/functions.xml
 create mode 100644 Phys/Swimming/doc/release.notes
 create mode 100644 Phys/Swimming/example/DecayTreeTuple.py
 create mode 100644 Phys/Swimming/example/DecayTreeTupleD2hh.py
 create mode 100644 Phys/Swimming/example/SwimStrippingB2JpsiX.py
 create mode 100644 Phys/Swimming/example/SwimStrippingD2hh.py
 create mode 100644 Phys/Swimming/example/SwimTriggerB2JpsiX.py
 create mode 100644 Phys/Swimming/example/SwimTriggerD2hh.py
 create mode 100755 Phys/Swimming/python/Swimming/Configuration.py
 create mode 100644 Phys/Swimming/python/Swimming/EventLoop.py
 create mode 100644 Phys/Swimming/python/Swimming/GeneralSetup.py
 create mode 100644 Phys/Swimming/python/Swimming/GetVeloAcceptance.py
 create mode 100644 Phys/Swimming/python/Swimming/Globals.py
 create mode 100644 Phys/Swimming/python/Swimming/HltTransforms.py
 create mode 100644 Phys/Swimming/python/Swimming/MooreSetup.py
 create mode 100644 Phys/Swimming/python/Swimming/OfflineSelExample.py
 create mode 100644 Phys/Swimming/python/Swimming/RefineTPs.py
 create mode 100644 Phys/Swimming/python/Swimming/SwimmingTisTos.py
 create mode 100644 Phys/Swimming/python/Swimming/SwimmingUtils.py
 create mode 100644 Phys/Swimming/python/Swimming/decorators.py
 create mode 100644 Phys/Swimming/scripts/RunSwimming.py
 create mode 100644 Phys/Swimming/scripts/SubmitJobExample.py
 create mode 100644 Phys/Swimming/src/functions.cpp

diff --git a/Phys/Swimming/cmt/requirements b/Phys/Swimming/cmt/requirements
new file mode 100644
index 000000000..5656ee01e
--- /dev/null
+++ b/Phys/Swimming/cmt/requirements
@@ -0,0 +1,41 @@
+#============================================================================
+# Created    : 2011-04-13
+# Maintainer : Vladimir Gligorov
+#============================================================================
+package           Swimming
+version           v2r3
+
+#============================================================================
+# Structure, i.e. directories to process. 
+#============================================================================
+branches          cmt doc python
+#============================================================================
+# Used packages. Specify the version, * at the end specifies 'any revision'
+#    Put as many lines as needed, with all packages, without the '#'
+#============================================================================
+use     GaudiPolicy     v*
+use     GaudiKernel     v*
+
+#============================================================================
+# Linker library
+#============================================================================
+library          Functions         ../src/functions.cpp
+apply_pattern    linker_library    library=Functions
+
+#============================================================================
+# Reflex dictionary
+#============================================================================
+apply_pattern     reflex_dictionary                                         \
+                  dictionary=RandomFunctions                                \
+                  headerfiles=$(SWIMMINGROOT)/dict/functions.h     \
+                  selectionfile=$(SWIMMINGROOT)/dict/functions.xml \
+                  options="-U__MINGW32__"
+
+include_path      none
+#============================================================================
+# Component library building rule
+#============================================================================
+#============================================================================
+# define component library link options
+#============================================================================
+apply_pattern install_python_modules
diff --git a/Phys/Swimming/cmt/version.cmt b/Phys/Swimming/cmt/version.cmt
new file mode 100644
index 000000000..e399f34f8
--- /dev/null
+++ b/Phys/Swimming/cmt/version.cmt
@@ -0,0 +1 @@
+v2r3
diff --git a/Phys/Swimming/dict/functions.h b/Phys/Swimming/dict/functions.h
new file mode 100644
index 000000000..03a36cc78
--- /dev/null
+++ b/Phys/Swimming/dict/functions.h
@@ -0,0 +1,16 @@
+// $Id: $
+#ifndef BETASREADERS_H 
+#define BETASREADERS_H 1
+
+#include <string>
+#include <boost/integer_traits.hpp>
+#include <boost/integer/integer_mask.hpp>
+
+namespace Random {
+   boost::uint32_t mix(boost::uint32_t state);
+   boost::uint32_t mix32(boost::uint32_t state, boost::uint32_t extra);
+   boost::uint32_t mix64(boost::uint32_t state, boost::uint64_t extra);
+   boost::uint32_t mixString(boost::uint32_t state, const std::string& extra);
+}
+
+#endif // BETASREADERS_H
diff --git a/Phys/Swimming/dict/functions.xml b/Phys/Swimming/dict/functions.xml
new file mode 100644
index 000000000..1a65936c5
--- /dev/null
+++ b/Phys/Swimming/dict/functions.xml
@@ -0,0 +1,5 @@
+<lcgdict>
+  <function name="Random::mix32" />
+  <function name="Random::mix64" />
+  <function name="Random::mixString" />
+</lcgdict>
diff --git a/Phys/Swimming/doc/release.notes b/Phys/Swimming/doc/release.notes
new file mode 100644
index 000000000..2de33ae76
--- /dev/null
+++ b/Phys/Swimming/doc/release.notes
@@ -0,0 +1,134 @@
+!-----------------------------------------------------------------------------
+! Package     : Phys/Swimming
+! Responsible : Vladimir Gligorov, Roel Aaij
+! Purpose     : Scripts for swimming the HLT/Stripping/Offline selections
+!               for lifetime measurements 
+!-----------------------------------------------------------------------------
+
+!====================== Phys/Swimming v2r3 2011-11-03 =======================
+
+! 2011-11-14 - Roel Aaij
+ - Fix another wrong usage of operator[] to access by index.
+
+! 2011-11-11 - Roel Aaij
+ - Make custom event-loop function conform to the intended interface.
+ - Use containedObjects() to access candidates by index.
+
+!====================== Phys/Swimming v2r2 2011-11-03 =======================
+! 2011-11-03 - V. Gligorov
+ - Fix small bug in configurable to enable "Inputs" property to do something
+ - Add two new HLT transforms which do not forward upgrade all HLT1 tracks
+   in all events, to save time in production.
+ - Add new example scripts for swimming D2hh to the examples directory.  
+
+! 2011-11-01 - Roel Aaij
+ - Add WriteFSR property to steer the writing of FSRs in the output file.
+
+! 2011-10-28 - Roel Aaij
+ - Fix for looping over candidates in SwimmingTisTos when swimming the
+   stripping.
+
+! 2011-10-28 - Roel Aaij
+ - Add all information to first and last turningpoints instead of storing only
+   the global decision.
+
+! 2011-10-27 - Roel Aaij
+ - Add Hlt node killing sequence as postConfigAction.
+
+! 2011-10-26 - Roel Aaij
+ - Fix 2 bugs (3 letters...)
+
+! 2011-10-25 - Roel Aaij
+ - Add OutputType property to allow DaVinci to write a DST when swimming the
+   stripping.
+
+! 2011-10-24 - Roel Aaij, Vava Gligorov
+ - Add configuration class and functions to run the swimming using gaudirun.py
+ - Add example scripts for use with gaudirun.py to example
+ - Small fix for odin check in RunSwimming.py
+
+! 2011-10-20 - Roel Aaij
+ - For a final refined turning point, the last interval is moved forward by half
+   the final granularity to avoid a systematic downward bias (swimming is always
+   left to right).
+ - Use pprint to make debug more readable (but also more lines).
+ - Add AppMgr.stop, finalize, exit at the end.
+
+! 2011-10-19 - Roel Aaij
+ - Fixed some HltDecLast fallout from a previous change.
+ - And reverted the fix because an important aspect was overlooked.
+
+! 2011-10-16 - Roel Aaij
+ - Add DecayTreeTuple.py, an example script to write a DecayTreeTuple from
+   either a DST or a MicroDST.
+ - Use hashParticle from SwimmingEvent to calculate a hash for an
+   LHCb::Particle and use it to store the daughter information.
+
+! 2011-10-12 - Roel Aaij
+ - Change custom map.__call__ into more natural __setitem__
+
+! 2011-10-11 - Roel Aaij
+ - Many changes, mainly:
+   . Use new event model classes to persist swimming result.
+   . Update the way trigger results are passed around.
+   . Write the swimming result to the MicroDST.
+   . Add candidate selection possibility, currently deterministic random or
+     the first candidate.
+   . In case of non-trivial candidate selection, put the selected candidate 
+     in a special location for swimming.
+   . Add functions and dictionary for deterministic random selection.
+
+!============================== v2r1 07-09-2011 ===============================
+! 2011-09-07 - V. Gligorov
+ - Many small bugfixes and updates to the code.
+   . Save decisions of all triggers if swimming more than one trigger at once
+   . Save which tracks participated in which trigger decision
+ - Write out muDST file at the end of swimming the stripping.     
+
+!============================== v2r0 14-08-2011 ===============================
+! 2011-08-14 - V. Gligorov
+ - Update to 2011 data.
+ - Includes the following changes :
+   . Added code to get VELO geometric acceptance for each track at each
+     turning point.
+   . Added trigger tranformations for 2011 data.
+   . Rewritten event loop which no longer needs to rewind events in order to swim
+     them. Many thanks to Marco Clemencic and Gerhard Raven for hints and tips
+     in this respect. The timing to swim a single event is now ~10s/event for HLT,
+     ~4s/event for Stripping. 
+ 
+!============================== v1r2 29-05-2011  ===============================
+
+! 2011-05-29 - V. Gligorov
+ - Fix bug in swimming range when refining a turning point. 
+ - Tag v1r2
+
+!============================== v1r1p1 18-04-2011 ==============================
+
+! 2011-04-18 - Diego Martinez Santos
+ - Make version v1r1p1
+
+! 2011-04-17 - V. Gligorov
+ - Small bugfix for the options "-n" and "-s" which specify the number of
+   events to run over and the first event to run over respectively. 
+
+!============================== v1r1 16-04-2011 ==============================
+
+! 2011-04-16 - Vladimir Gligorov
+ - Update of the code. Setup options moved into separate files where possible.
+   TisTos code moved into its own script, SwimmingTisTos.py.
+ - Added functionality to store information on how many of the final state
+   tracks from the signal candidate were reconstructed in HLT1/2, and how
+   many of these tracks were TOS with respect to the signal trigger in HLT1. 
+
+!============================== v1r0 13-04-2011 ==============================
+
+! 2011-04-13 - Vladimir Gligorov
+  - First commit of the code which used to live in Hlt2CommissioningScripts.
+    This has been broken up into several smaller scripts. 
+    . RunSwimming   : is the main script which controls the event loop
+    . RefineTPs     : controls the recursive refinement of the turning points
+    . HltTransforms : contains the transformations which allow swimming from TCKs 
+    . SwimmingUtils : contains miscallaneous helper functions
+    . Globals       : contains a helper class to pass "globals" (e.g. the TES)
+                      between the various modules
diff --git a/Phys/Swimming/example/DecayTreeTuple.py b/Phys/Swimming/example/DecayTreeTuple.py
new file mode 100644
index 000000000..a4ae76a44
--- /dev/null
+++ b/Phys/Swimming/example/DecayTreeTuple.py
@@ -0,0 +1,105 @@
+##
+## Static Configuration 
+##
+from Gaudi.Configuration import *
+from Configurables import ( ApplicationMgr,
+                            CondDB,
+                            HistogramPersistencySvc,
+                            DaVinci,
+                            MessageSvc,
+                            GaudiSequencer,
+                            ANNDispatchSvc,
+                            HltDecReportsDecoder,
+                            HltSelReportsDecoder )
+
+CondDB( UseOracle = False,DisableLFC=True )
+
+## More space for output
+MessageSvc().Format = "% F%30W%S%15W%R%T %0W%M"
+
+## mDST paths
+locationRoot = '/Event'
+selectionPath = 'SingleCandidate'
+particlePath = selectionPath + '/Particles'
+#pvLocation = 'Rec/Vertex/Primary'
+
+p2PVLocation = selectionPath +'/Particle2VertexRelations'
+
+mDST = True
+if mDST:
+    mDSTName = 'SwimmingMDST'
+    p2PVLocation = '%s/BestPV_%s_P2PV' % ( selectionPath, mDSTName )
+    from MicroDSTConf.TriggerConfUtils import configureL0AndHltDecoding
+    locationRoot += '/' + mDSTName
+    configureL0AndHltDecoding(locationRoot)
+
+from Gaudi.Configuration import *
+from Configurables import ( DaVinci, MessageSvc, FilterDesktop )
+
+# Make the DecayTreeTuple
+from Configurables import DecayTreeTuple
+dtt = DecayTreeTuple (
+    'SwimmingDTT',
+    ## print histos 
+    HistoPrint = True,
+    ## N-tuple LUN 
+    NTupleLUN  = "DTT",
+    ## input particles from selection:
+    Inputs = [ particlePath ],
+    ## Primary vertices from mDST
+    P2PVInputLocations = [ p2PVLocation ],
+    UseP2PVRelations = True,
+    WriteP2PVRelations = False,
+    )
+
+dtt.Decay = "B_s0 -> (^J/psi(1S) => ^mu+ ^mu-) (^phi(1020) -> ^K+ ^K-)"
+if mDST: dtt.RootInTES = locationRoot
+
+from DecayTreeTuple.Configuration import *
+## Add appropriate tools
+
+dtt.addBranches({
+    "B" : "B_s0 : B_s0 -> (J/psi(1S) => mu+ mu-) (phi(1020) -> K+ K-)"
+})
+
+dtt.B.addTupleTool('TupleToolPropertime')
+ttsi = dtt.B.addTupleTool('TupleToolSwimmingInfo/TriggerInfo')
+ttsis = dtt.B.addTupleTool('TupleToolSwimmingInfo/StrippingInfo')
+ttsi.ReportsLocation = selectionPath + '/P2TPRelations'
+ttsis.ReportsLocation = selectionPath + '/P2TPRelations'
+ttsis.ReportStage = "Stripping"
+
+tttt = dtt.B.addTupleTool('TupleToolTISTOS')
+tttt.TriggerList = ['Hlt1TrackAllL0Decision', 'Hlt1TrackMuonDecision', 'Hlt1DiMuonHighMassDecision',
+                    'Hlt2DiMuonDetachedJpsiDecision', 'Hlt2DiMuonJpsiDecision']
+tttt.VerboseHlt1 = True
+tttt.VerboseHlt2 = True
+
+dv = DaVinci()
+dv.DDDBtag = 'head-20110914'
+dv.CondDBtag = 'head-20110914'
+dv.DataType = '2011'
+dv.Lumi = False
+dv.InputType = "MDST" if mDST else "DST"
+dv.UserAlgorithms = [ dtt ]
+dv.EvtMax = -1
+
+ApplicationMgr().HistogramPersistency = "ROOT"
+from Configurables import HistogramPersistencySvc
+HistogramPersistencySvc ( OutputFile = 'histos.root' ) 
+
+from Configurables import NTupleSvc
+NTupleSvc().Output += [ "DTT DATAFILE='tuples.root' TYPE='ROOT' OPT='NEW'"]
+NTupleSvc().OutputLevel = 1
+
+## Point the EventClockSvc to the RootInTES
+## from Configurables import EventClockSvc, OdinTimeDecoder, TimeDecoderList
+## EventClockSvc().addTool( TimeDecoderList, name = "EventTimeDecoder" )
+## EventClockSvc().EventTimeDecoder.RootInTES = locationRoot
+
+from GaudiConf import IOHelper
+if mDST:
+    ## IOHelper().inputFiles(['/castor/cern.ch/user/r/raaij/test/Swimming.SwimmingMicroDST.mdst'])
+    IOHelper().inputFiles(['Swimming.SwimmingMDST.mdst'])
+else:
+    IOHelper().inputFiles(['/project/bfys/raaij/cmtuser/Moore_v12r8/scripts/SwimTrigDST.dst'])
diff --git a/Phys/Swimming/example/DecayTreeTupleD2hh.py b/Phys/Swimming/example/DecayTreeTupleD2hh.py
new file mode 100644
index 000000000..35c29bd45
--- /dev/null
+++ b/Phys/Swimming/example/DecayTreeTupleD2hh.py
@@ -0,0 +1,105 @@
+##
+## Static Configuration 
+##
+from Gaudi.Configuration import *
+from Configurables import ( ApplicationMgr,
+                            CondDB,
+                            HistogramPersistencySvc,
+                            DaVinci,
+                            MessageSvc,
+                            GaudiSequencer,
+                            ANNDispatchSvc,
+                            HltDecReportsDecoder,
+                            HltSelReportsDecoder )
+
+CondDB( UseOracle = False,DisableLFC=True )
+
+## More space for output
+MessageSvc().Format = "% F%30W%S%15W%R%T %0W%M"
+
+## mDST paths
+locationRoot = '/Event'
+selectionPath = 'CharmCompleteEvent/Phys/D2hhPromptD2KPiLine'
+particlePath = selectionPath + '/Particles'
+#pvLocation = 'Rec/Vertex/Primary'
+
+p2PVLocation = selectionPath +'/Particle2VertexRelations'
+
+mDST = True
+if mDST:
+    mDSTName = 'SwimmingMDST'
+    p2PVLocation = '%s/BestPV_%s_P2PV' % ( selectionPath, mDSTName )
+    from MicroDSTConf.TriggerConfUtils import configureL0AndHltDecoding
+    locationRoot += '/' + mDSTName
+    configureL0AndHltDecoding(locationRoot)
+
+from Gaudi.Configuration import *
+from Configurables import ( DaVinci, MessageSvc, FilterDesktop )
+
+# Make the DecayTreeTuple
+from Configurables import DecayTreeTuple
+dtt = DecayTreeTuple (
+    'SwimmingDTT',
+    ## print histos 
+    HistoPrint = True,
+    ## N-tuple LUN 
+    NTupleLUN  = "DTT",
+    ## input particles from selection:
+    Inputs = [ particlePath ],
+    ## Primary vertices from mDST
+    P2PVInputLocations = [ p2PVLocation ],
+    UseP2PVRelations = True,
+    WriteP2PVRelations = False,
+    )
+
+dtt.Decay = "[[D0]cc -> ^K- ^pi+]cc"
+if mDST: dtt.RootInTES = locationRoot
+
+from DecayTreeTuple.Configuration import *
+## Add appropriate tools
+
+dtt.addBranches({
+    "D" : "D0 : [[D0]cc -> K- pi+]cc"
+})
+
+dtt.D.addTupleTool('TupleToolPropertime')
+ttsi = dtt.D.addTupleTool('TupleToolSwimmingInfo/TriggerInfo')
+ttsis = dtt.D.addTupleTool('TupleToolSwimmingInfo/StrippingInfo')
+ttsi.ReportsLocation = selectionPath + '/P2TPRelations'
+ttsis.ReportsLocation = selectionPath + '/P2TPRelations'
+ttsis.ReportStage = "Stripping"
+
+tttt = dtt.D.addTupleTool('TupleToolTISTOS')
+tttt.TriggerList = ['Hlt1TrackAllL0Decision', 'Hlt1TrackMuonDecision', 'Hlt1DiMuonHighMassDecision',
+                    'Hlt2DiMuonDetachedJpsiDecision', 'Hlt2DiMuonJpsiDecision']
+tttt.VerboseHlt1 = True
+tttt.VerboseHlt2 = True
+
+dv = DaVinci()
+dv.DDDBtag = 'head-20110914'
+dv.CondDBtag = 'head-20110914'
+dv.DataType = '2011'
+dv.Lumi = False
+dv.InputType = "MDST" if mDST else "DST"
+dv.UserAlgorithms = [ dtt ]
+dv.EvtMax = -1
+
+ApplicationMgr().HistogramPersistency = "ROOT"
+from Configurables import HistogramPersistencySvc
+HistogramPersistencySvc ( OutputFile = 'histos.root' ) 
+
+from Configurables import NTupleSvc
+NTupleSvc().Output += [ "DTT DATAFILE='tuples.root' TYPE='ROOT' OPT='NEW'"]
+NTupleSvc().OutputLevel = 1
+
+## Point the EventClockSvc to the RootInTES
+## from Configurables import EventClockSvc, OdinTimeDecoder, TimeDecoderList
+## EventClockSvc().addTool( TimeDecoderList, name = "EventTimeDecoder" )
+## EventClockSvc().EventTimeDecoder.RootInTES = locationRoot
+
+from GaudiConf import IOHelper
+if mDST:
+    ## IOHelper().inputFiles(['/castor/cern.ch/user/r/raaij/test/Swimming.SwimmingMicroDST.mdst'])
+    IOHelper().inputFiles(['Swimming.SwimmingMDST.mdst'])
+else:
+    IOHelper().inputFiles(['/castor/cern.ch/user/r/raaij/test/SwimTrigDST.dst'])
diff --git a/Phys/Swimming/example/SwimStrippingB2JpsiX.py b/Phys/Swimming/example/SwimStrippingB2JpsiX.py
new file mode 100644
index 000000000..d98351097
--- /dev/null
+++ b/Phys/Swimming/example/SwimStrippingB2JpsiX.py
@@ -0,0 +1,35 @@
+from Configurables import Swimming
+from Gaudi.Configuration import *
+
+Swimming().DataType = '2011'
+Swimming().EvtMax = 1000
+Swimming().Simulation = False
+Swimming().DDDBtag = 'head-20110914'
+Swimming().CondDBtag = 'head-20110914'
+Swimming().Persistency = 'ROOT'
+Swimming().InputType = 'DST'
+Swimming().Input = ["DATAFILE='PFN:castor:/castor/cern.ch/user/r/raaij/Swimming/SwimTrigDST_0x00730035.dst'"]
+Swimming().SwimStripping = True
+Swimming().StrippingStream = 'DiMuon'
+Swimming().StrippingVersion = 'Stripping17'
+Swimming().StrippingFile = 'B2JpsiXforBeta_s'
+Swimming().StrippingLine = 'BetaS'
+Swimming().StripCands = '/Event/Phys/BetaSBs2JpsiPhiDetachedLine'
+Swimming().OffCands = '/Event/SingleCandidate'
+Swimming().SelectMethod = 'random'
+Swimming().OutputType = 'MDST'
+Swimming().UseFileStager = True
+Swimming().Debug = True
+
+from Configurables import CondDB
+CondDB(UseOracle = False, DisableLFC = True)
+
+# Configure Moore to swim the trigger
+from Swimming.Configuration import ConfigureDaVinci
+ConfigureDaVinci()
+
+# The custom event loop
+from Gaudi.Configuration import setCustomMainLoop
+from Swimming.EventLoop import SwimmingEventLoop
+setCustomMainLoop(SwimmingEventLoop)
+
diff --git a/Phys/Swimming/example/SwimStrippingD2hh.py b/Phys/Swimming/example/SwimStrippingD2hh.py
new file mode 100644
index 000000000..5e82dcec6
--- /dev/null
+++ b/Phys/Swimming/example/SwimStrippingD2hh.py
@@ -0,0 +1,34 @@
+from Configurables import Swimming
+from Gaudi.Configuration import *
+
+Swimming().DataType = '2011'
+Swimming().EvtMax = 1000
+Swimming().Simulation = False
+Swimming().DDDBtag = 'head-20110914'
+Swimming().CondDBtag = 'head-20110914'
+Swimming().Persistency = 'ROOT'
+Swimming().InputType = 'DST'
+Swimming().Input = ["DATAFILE='PFN:castor:/afs/cern.ch/user/g/gligorov/w0/cmtuser/DaVinci_HEAD/Phys/Swimming/example/SwimTrigDST.dst'"]
+Swimming().SwimStripping = True
+Swimming().StrippingStream = 'CharmCompleteEvent'
+Swimming().StrippingVersion = 'Stripping17'
+Swimming().StrippingFile = 'D2hh'
+Swimming().StrippingLine = 'D2hh'
+Swimming().StripCands = '/Event/Phys/D2hhPromptD2KPiLine'
+Swimming().OffCands = '/Event/CharmCompleteEvent/Phys/D2hhPromptD2KPiLine'
+Swimming().SelectMethod = 'random'
+Swimming().OutputType = 'MDST'
+Swimming().UseFileStager = True
+
+from Configurables import CondDB
+CondDB(UseOracle = False, DisableLFC = True)
+
+# Configure Moore to swim the trigger
+from Swimming.Configuration import ConfigureDaVinci
+ConfigureDaVinci()
+
+# The custom event loop
+from Gaudi.Configuration import setCustomMainLoop
+from Swimming.EventLoop import SwimmingEventLoop
+setCustomMainLoop(SwimmingEventLoop)
+
diff --git a/Phys/Swimming/example/SwimTriggerB2JpsiX.py b/Phys/Swimming/example/SwimTriggerB2JpsiX.py
new file mode 100644
index 000000000..e8cc5d05a
--- /dev/null
+++ b/Phys/Swimming/example/SwimTriggerB2JpsiX.py
@@ -0,0 +1,36 @@
+from Configurables import Swimming
+from Gaudi.Configuration import *
+
+Swimming().DataType = '2011'
+Swimming().EvtMax = 50
+Swimming().Simulation = False
+Swimming().DDDBtag = "head-20110722"
+Swimming().CondDBtag = "head-20110901"
+Swimming().Persistency = 'ROOT'
+Swimming().InputType = 'DST'
+Swimming().OutputFile = 'SwimTrigDST.dst'
+Swimming().SwimStripping = False
+Swimming().TCK = '0x00790038'
+Swimming().Hlt1Triggers = ["Hlt1DiMuonHighMassDecision", "Hlt1TrackAllL0Decision", "Hlt1TrackMuonDecision"]
+Swimming().Hlt2Triggers = ["Hlt2DiMuonJPsiDecision", "Hlt2DiMuonDetachedJPsiDecision"]
+Swimming().OffCands = "/Event/SingleCandidate"
+Swimming().TransformName = '2011_WithBeamSpotFilter'
+Swimming().SelectMethod = 'random'
+Swimming().OutputType = 'DST'
+Swimming().UseFileStager = True
+Swimming().Debug = True
+
+## from Configurables import FileStagerSvc
+## FileStagerSvc().OutputLevel = 1
+
+from Configurables import CondDB
+CondDB(UseOracle = True)
+
+# Configure Moore to swim the trigger
+from Swimming.Configuration import ConfigureMoore
+ConfigureMoore()
+
+# The custom event loop
+from Gaudi.Configuration import setCustomMainLoop
+from Swimming.EventLoop import SwimmingEventLoop
+setCustomMainLoop(SwimmingEventLoop)
diff --git a/Phys/Swimming/example/SwimTriggerD2hh.py b/Phys/Swimming/example/SwimTriggerD2hh.py
new file mode 100644
index 000000000..c95c35b7c
--- /dev/null
+++ b/Phys/Swimming/example/SwimTriggerD2hh.py
@@ -0,0 +1,36 @@
+from Configurables import Swimming
+from Gaudi.Configuration import *
+
+Swimming().DataType = '2011'
+Swimming().EvtMax = 100
+Swimming().Simulation = False
+Swimming().DDDBtag = "head-20110302"
+Swimming().CondDBtag = "head-20110321"
+Swimming().Persistency = 'ROOT'
+Swimming().InputType = 'DST'
+Swimming().OutputFile = 'SwimTrigDST.dst'
+Swimming().SwimStripping = False
+Swimming().TCK = '0x00730035'
+Swimming().Hlt1Triggers = ["Hlt1TrackAllL0Decision"]
+Swimming().Hlt2Triggers = ["Hlt2CharmHadD02HH_D02KPiDecision"]
+Swimming().OffCands = "/Event/CharmCompleteEvent/Phys/D2hhPromptD2KPiLine"
+Swimming().TransformName = '2011_WithBeamSpotFilter'
+Swimming().SelectMethod = 'random'
+Swimming().OutputType = 'DST'
+Swimming().UseFileStager = False
+Swimming().Input = ["DATAFILE='PFN:castor:/castor/cern.ch/grid/lhcb/LHCb/Collision11/CHARMCOMPLETEEVENT.DST/00012586/0000/00012586_00000584_1.charmcompleteevent.dst'"]
+
+from Configurables import FileStagerSvc
+FileStagerSvc().OutputLevel = 1
+
+from Configurables import CondDB
+CondDB(UseOracle = False, DisableLFC = True )
+
+# Configure Moore to swim the trigger
+from Swimming.Configuration import ConfigureMoore
+ConfigureMoore()
+
+# The custom event loop
+from Gaudi.Configuration import setCustomMainLoop
+from Swimming.EventLoop import SwimmingEventLoop
+setCustomMainLoop(SwimmingEventLoop)
diff --git a/Phys/Swimming/python/Swimming/Configuration.py b/Phys/Swimming/python/Swimming/Configuration.py
new file mode 100755
index 000000000..678021d47
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/Configuration.py
@@ -0,0 +1,364 @@
+"""
+High level configuration tools for Swimming
+"""
+__author__ = "V. Gligorov <vladimir.gligorov@cern.ch>"
+
+from LHCbKernel.Configuration import *
+from GaudiConf.Configuration import *
+from Configurables import GaudiSequencer
+from Configurables import ( LHCbConfigurableUser, LHCbApp,
+                            DstConf, CaloDstUnPackConf )
+
+import GaudiKernel.ProcessJobOptions
+
+
+class Swimming(LHCbConfigurableUser) :
+    
+    __slots__ = {
+        # Application Configuration : sent to LHCbApp and Gaudi
+          "EvtMax"             :  -1             # Number of events to analyse
+        , "SkipEvents"         :   0             # Number of events to skip at beginning for file
+        , "DataType"           : ''              # Data type, can be ['DC06','2008','2009', 'MC09', '2010', '2011'] Forwarded to PhysConf. MUST be set.
+        , "Simulation"         : False           # set to True to use SimCond. Forwarded to PhysConf
+        , "DDDBtag"            : ""              # Tag for DDDB. Default as set in DDDBConf for DataType
+        , "CondDBtag"          : ""              # Tag for CondDB. Default as set in DDDBConf for DataType
+        # Persistency
+        , "Persistency"        : None            # ROOT or POOL, steers the setup of services
+        # Input
+        , "Input"              : []              # Input data. Can also be passed as a second option file.
+        , "InputType"          : "DST"           # or "DIGI" or "ETC" or "RDST" or "DST or "MDST" of "SDST". Nothing means the input type is compatible with being a DST. 
+        # Output
+        , "OutputFile"         : ""              # Name of output file
+        , "OutputType"         : ""              # Type of output for swimming the stripping, DST or MDST
+        # Swimming Options
+        , "Debug"              : False           # Switch on debug mode
+        , "SwimStripping"      : False           # Swim the stripping
+        , "SwimOffSel"         : False           # Swim the offline selection
+        , "TCK"                : ''              # The TCK to swim
+        , "StrippingStream"    : ''              # The stripping stream name to swim e.g. 'CharmCompleteEvent'
+        , "StrippingVersion"   : ''              # The stripping version, e.g. 'Stripping17'  
+        , "StrippingLine"      : ''              # The stripping line to swim
+        , "StrippingFile"      : ''              #
+        , "Hlt1Triggers"       : []              # The Hlt1 triggers to swim
+        , "Hlt2Triggers"       : []              # The Hlt2 triggers to swim  
+        , "OffSelModuleName"   : ''              # The name of the module containing the offline selection
+        , "Hlt1RecoLine"       : 'Hlt1TrackForwardPassThroughLooseDecision' # The trigger line used for Hlt1 reconstruction studies
+        , "Hlt2RecoLine"       : 'Hlt2ForwardDecision'                      # The trigger line used for Hlt2 reconstruction studies                 
+        , "OffCands"           : ''              # The TES location of the offline selected candidates
+        , "StripCands"         : ''              # The TES location of the stripping candidates
+        , "MuDSTCands"         : ''              # The TES location of the candidates to write to MuDST
+        , "OnlinePV"           : 'TES:Hlt/Vertex/PV3D'      # The TES location of the HLT primary vertices
+        , "OfflinePV"          : '/Event/Rec/Vertex/Primary'# The TES location of the offline primary vertices
+        , "OutPVSel"           : 'PV3D'          # The name of the HLT1 PV3D 'selection' 
+        , "RelPVFinder"        : 'GenericParticle2PVRelator__p2PVWithIPChi2_OfflineDistanceCalculatorName_/P2PVWithIPChi2' # Related PV finder
+        , "DistCalc"           : 'LoKi::DistanceCalculator' # The distance calculator
+        , "TauCalc"            : 'PropertimeFitter'         # The decay time calculator
+        , "MaxSwimDistance"    : 200.            # The maximum distance to swim with "fine" granularity
+        , "InitialGranularity" : 4.              # The "fine" granularity with which to swim.              
+        , "GranularityRefinement" : 4.           # The amount by which to refine the granularity
+        , "NumberOfRefinements": 5               # The number of refinements 
+        , "ExtraSwimDistance"  : 400.            # The maximum distance to swim with "coarse" granularity
+        , "ExtraGranularity"   : 40.             # The "coarse" granularity with which to swim.
+        , "TransformName"      : ''              # The name of the transform to use
+        , "SwimmingPrefix"     : '/Event/Swimming' # The TES location of the swimming reports
+        , "SelectMethod"       : 'random'        # The method for selecting offline candidates (random, first, or '')
+        , "UseFileStager"      : False           # Use the file stager.
+        , "WriteFSR"           : True            # Write FSRs in output DST.
+       }
+
+    _propertyDocDct = {  
+          "EvtMax"             : """ Number of events to analyse """
+        , "SkipEvents"         : """ Number of events to skip at beginning for file """
+        , "DataType"           : """ Data type, can be ['DC06','2008', '2009', 'MC09', '2010', '2011'] Forwarded to PhysConf, AnalysisConf and LHCbApp """
+        , "Simulation"         : """ set to True to use SimCond. Forwarded to PhysConf """
+        , "DDDBtag"            : """ Tag for DDDB. Default as set in DDDBConf for DataType """
+        , "CondDBtag"          : """ Tag for CondDB. Default as set in DDDBConf for DataType """
+        , "Input"              : """ Input data. Can also be passed as a second option file. """
+        , "InputType"          : """ 'DST' or 'DIGI' or 'ETC' or 'RDST' or 'DST' or 'MDST' or 'SDST'. Nothing means the input type is compatible with being a DST.  """
+        , "Persistency"        : """ ROOT or POOL, steers the setup of services """
+        , "Input"              : """ Input data. Can also be passed as a second option file."""
+        , "InputType"          : """ or 'DIGI' or 'ETC' or 'RDST' or 'DST' or 'MDST' of 'SDST'. Nothing means the input type is compatible with being a DST. """
+        , "OutputFile"         : """ Name of output file"""
+        , "OutputType"         : """ Type of output for swimming the stripping, either DST or MDST."""
+        , "Debug"              : """ Switch on debug mode"""
+        , "SwimStripping"      : """ Swim the stripping"""
+        , "SwimOffSel"        : """ Swim the offline selection"""
+        , "TCK"                : """ The TCK to swim"""
+        , "StrippingStream"    : """ The stripping stream name to swim e.g. 'CharmCompleteEvent'"""
+        , "StrippingVersion"   : """ The stripping version, e.g. 'Stripping17'  """
+        , "StrippingLine"      : """ The stripping line to swim"""
+        , "StrippingFile"      : """   """
+        , "Hlt1Triggers"       : """ The Hlt1 triggers to swim"""
+        , "Hlt2Triggers"       : """ The Hlt2 triggers to swim  """
+        , "OffSelModuleName"   : """ The name of the module containing the offline selection"""
+        , "Hlt1RecoLine"       : """ The trigger line used for Hlt1 reconstruction studies"""
+        , "Hlt2RecoLine"       : """ The trigger line used for Hlt2 reconstruction studies                 """
+        , "OffCands"           : """ The TES location of the offline selected candidates"""
+        , "StripCands"         : """ The TES location of the stripping candidates"""
+        , "MuDSTCands"         : """ The TES location of the candidates to write to MuDST"""
+        , "OnlinePV"           : """ The TES location of the HLT primary vertices"""
+        , "OfflinePV"          : """ The TES location of the offline primary vertices"""
+        , "OutPVSel"           : """ The name of the HLT1 PV3D 'selection' """
+        , "RelPVFinder"        : """ Related PV finder"""
+        , "DistCalc"           : """ The distance calculator"""
+        , "TauCalc"            : """ The decay time calculator"""
+        , "MaxSwimDistance"    : """ The maximum distance to swim with "fine" granularity"""
+        , "InitialGranularity" : """ The "fine" granularity with which to swim.              """
+        , "GranularityRefinement" : """ The amount by which to refine the granularity"""
+        , "NumberOfRefinements": """ The number of refinements """
+        , "ExtraSwimDistance"  : """ The maximum distance to swim with "coarse" granularity"""
+        , "ExtraGranularity"   : """ The "coarse" granularity with which to swim."""
+        , "TransformName"      : """ The name of the transform to use"""
+        , "SwimmingPrefix"     : """ The TES prefix used for swimming objects."""
+        , "SelectMethod"       : """ The method for selecting offline candidates (random, first, or '')"""
+        , "UseFileStager"      : """ Use the file stager. """
+        , "WriteFSR"           : """ Write FSRs in output DST. """
+        }
+
+    __used_configurables__ = [
+        DstConf,
+        CaloDstUnPackConf,
+        LHCbApp
+        ]
+
+################################################################################
+# Apply configuration
+#
+    def __apply_configuration__(self):
+        """
+        Swimming configuration
+        """
+        log.info("Applying Swimming configuration")
+        log.info( self )
+
+        if not self.getProp('SwimStripping') and not self.getProp('TransformName'):
+            raise TypeError, "No or invalid HLT transform specified when trying to swim the trigger!"
+        if not self.getProp('SwimStripping') and self.getProp('SwimOffSel'):
+            raise TypeError, "You cannot swim the trigger and offline selection in the same job!"
+                
+        if self.getProp('SelectMethod') not in ['random', 'first', 'none']:
+            raise TypeError, 'The selectMethod must be eiter "random", "first" or "none".'
+
+        if not self.getProp('OutputType') in ['DST', 'MDST']:
+            raise TypeError, "The only supported output types are DST and MDST."
+        if not self.getProp('SwimStripping') and self.getProp('OutputType') == 'MDST':
+            raise TypeError, "You cannot write a MicroDST when swimming the trigger."
+               
+        from Configurables import DataOnDemandSvc
+
+        app = LHCbApp()
+        self.setOtherProps(app, ['EvtMax', 'SkipEvents', 'Simulation', 'DataType',
+                                 'Persistency'])
+
+        CaloDstUnPackConf ( Enable = True )
+        DstConf           ( EnableUnpack = True )
+
+        importOptions("$STDOPTS/DecodeRawEvent.py")
+        appConf = ApplicationMgr()
+        appConf.HistogramPersistency = 'ROOT'
+        appConf.ExtSvc += ['DataOnDemandSvc']
+        EventSelector().PrintFreq = -1
+        EventSelector().OutputLevel = 6 
+        if not (self.getProp('Input') == []) :
+            EventSelector().Input = self.getProp('Input') 
+
+        # FileStager
+        if self.getProp('UseFileStager'):
+            from FileStager.Configuration import configureFileStager
+            configureFileStager()
+        IODataManager().UseGFAL=False
+
+        # Disable muons in TisTosTool
+        from Configurables import TriggerTisTos
+        ToolSvc().addTool(TriggerTisTos,'TriggerTisTos')
+        ToolSvc().TriggerTisTos.TOSFracMuon = 0.
+
+def ConfigureMoore():
+    config = Swimming()
+    from Swimming.HltTransforms import getTransform
+    thisTransform = getTransform(config.getProp('TransformName'),
+                                 config.getProp('Hlt1Triggers') + config.getProp('Hlt2Triggers'))
+
+    from Configurables import HltMoveVerticesForSwimming
+    from Configurables import Moore,HltConfigSvc
+
+    #Global configuration
+    mykiller    = EventNodeKiller("killHlt")
+    mykiller.Nodes          = ["Hlt","Hlt1","Hlt2","Trig","Raw"]
+    deathstar               = GaudiSequencer("killHltSeq")
+    deathstar.Members       = [mykiller]
+    from Swimming import MooreSetup
+    #
+    Moore().InitialTCK  = config.getProp('TCK')
+    Moore().Simulation  = config.getProp('Simulation')
+    Moore().DataType    = config.getProp('DataType')
+    Moore().DDDBtag     = config.getProp('DDDBtag')
+    Moore().CondDBtag   = config.getProp('CondDBtag')
+    Moore().outputFile  = config.getProp('OutputFile')
+    Moore().WriteFSR    = config.getProp('WriteFSR')
+    Moore().Persistency = config.getProp('Persistency')
+    Moore().WriterRequires = []
+    # Add extra locations to writer
+    from Configurables import InputCopyStream
+    writer = InputCopyStream('Writer')
+    writer.ItemList = [config.getProp('OffCands') + '/P2TPRelations#1',
+                       config.getProp('SwimmingPrefix') + '/Reports#1']
+    
+    #
+    # Define the TCK transformation
+    # 
+    HltConfigSvc().ApplyTransformation = thisTransform
+    #
+    # Define the swimming algorithm
+    #
+    myswimmer                   = HltMoveVerticesForSwimming("HltMovePVs4Swimming")
+    myswimmer.SwimmingDistance  = 0.0
+    loc = None
+    if config.getProp('SelectMethod') == 'none':
+        loc = config.OffCands 
+    else:
+        loc = config.getProp('SwimmingPrefix')
+    myswimmer.Bcontainer        = loc
+    myswimmer.InputSelection    = config.getProp('OnlinePV')
+    myswimmer.OutputSelection   = config.getProp('OutPVSel')
+    myswimmer.OutputLevel       = 4
+
+    class Deathstar(object):
+        def __init__(self, seq):
+            self._seq = seq
+        def insert(self):
+            ApplicationMgr().TopAlg.insert(0, self._seq)
+
+    d = Deathstar(deathstar)
+    appendPostConfigAction(d.insert)
+    
+def ConfigureDaVinci():
+    config = Swimming()
+    from Configurables import DaVinci
+    from StrippingConf.Configuration import StrippingConf
+    from Configurables import ProcStatusCheck
+    from Configurables import EventNodeKiller,GaudiSequencer
+    from PhysSelPython.Wrappers import AutomaticData, SelectionSequence
+
+    # Get the stripping line
+    from StrippingSettings.Utils import lineBuilderConfiguration
+    strippingFile = None
+    if config.getProp('StrippingFile') != 'none':
+        strippingFile = config.getProp('StrippingFile')
+    else:
+        strippingFile = config.getProp('StrippingLine')
+    myconfig = lineBuilderConfiguration(config.getProp('StrippingVersion'),
+                                        config.getProp('StrippingLine'))
+    import StrippingSelections
+    mylineconf = getattr(__import__('StrippingSelections.Stripping' + strippingFile,
+                                    globals(),locals(),
+                                    [myconfig["BUILDERTYPE"]],-1),myconfig["BUILDERTYPE"])
+    mylinedict = myconfig["CONFIG"]
+    print mylineconf
+    print mylinedict
+
+    from StrippingConf.StrippingStream import StrippingStream
+    stream = StrippingStream(config.getProp('StrippingStream') + "Swimming")
+    allLines = mylineconf(config.getProp('StrippingLine'), mylinedict).lines()
+    lines = []
+    for l in allLines:
+        lineName = config.getProp('StripCands').split('/')[-1]
+        if l.outputLocation().find(lineName) != -1:
+            lines.append(l)
+    stream.appendLines(lines)
+
+    # Define the stream
+    filterBadEvents = ProcStatusCheck()
+    sc = StrippingConf( Streams = [stream],
+                        MaxCandidates       = 2000,
+                        AcceptBadEvents     = False,
+                        BadEventSelection   = filterBadEvents )
+
+    # Define the node killer, and make sure to kill everything corresponding to
+    # the stream which we want to swim
+    outputs = []
+    for l in lines:
+        for f in l.filterMembers():
+            if not hasattr(f, 'Output'):
+                continue
+            # Remove the last item so we get everything (Particle, relations,
+            # decayVertices, etc...
+            o = '/'.join(f.Output.split('/')[:-1])
+            outputs.append(o)
+    mykiller    = EventNodeKiller("killStripping")
+    # Some default nodes which we will want to kill in all cases
+    nodestokill = outputs + ['Strip', '/Event/Rec/Vertex/Primary']
+    mykiller.Nodes          = nodestokill 
+    deathstar               = GaudiSequencer("killStrippingSeq")
+    deathstar.Members       = [mykiller]
+
+    # Configure DaVinci
+    DaVinci().InputType   = config.getProp('InputType')
+    DaVinci().DataType    = config.getProp('DataType')
+    DaVinci().Simulation  = config.getProp('Simulation')
+    DaVinci().DDDBtag     = config.getProp('DDDBtag')
+    DaVinci().CondDBtag   = config.getProp('CondDBtag')
+    DaVinci().Persistency = config.getProp('Persistency')
+    
+    # The sequence for the swimming has to be configured 
+    # by hand inserting the node killer before it
+    DaVinci().appendToMainSequence( [deathstar] )
+    DaVinci().appendToMainSequence( [ sc.sequence() ] )
+
+    # Output
+    inputData = AutomaticData(Location = config.getProp('OffCands') + "/Particles")
+    selectionSeq = SelectionSequence("Swimming" + config.getProp('OutputType'),
+                                     TopSelection = inputData)
+    dstWriter = None
+    print config.getProp('OutputType')
+    if config.getProp('OutputType') == 'MDST':
+        from DSTWriters.__dev__.Configuration import MicroDSTWriter, microDSTStreamConf
+        from DSTWriters.__dev__.microdstelements import (CloneRecHeader,
+                                                         CloneODIN,
+                                                         ClonePVs,
+                                                         CloneSwimmingReports,
+                                                         CloneParticleTrees,
+                                                         ClonePVRelations,
+                                                         CloneTPRelations,
+                                                         ReFitAndClonePVs,
+                                                         CloneLHCbIDs,
+                                                         CloneRawBanks)
+        SwimmingConf = microDSTStreamConf()
+        streamConf = { 'default' : SwimmingConf }
+        SwimmingElements = [ CloneRecHeader(),
+                             CloneODIN(),
+                             ClonePVs(),
+                             CloneSwimmingReports(),
+                             CloneParticleTrees(copyProtoParticles = True),
+                             ClonePVRelations("Particle2VertexRelations", True),
+                             CloneTPRelations("P2TPRelations", True),
+                             ReFitAndClonePVs(),
+                             CloneLHCbIDs(),
+                             CloneRawBanks(banks = ['HltSelReports', 'HltDecReports',
+                                                    'L0DU', 'L0Calo', 'L0CaloError', 'L0CaloFull',
+                                                    'L0Muon', 'L0MuonProcCand', 'L0MuonError'],
+                                           inputRawEvent = 'DAQ/RawEvent')]
+        elementsConf = { 'default' : SwimmingElements }
+        dstWriter = MicroDSTWriter('MicroDST',
+                                   StreamConf         = streamConf,
+                                   MicroDSTElements   = elementsConf,
+                                   WriteFSR           = config.getProp('WriteFSR'),
+                                   OutputFileSuffix   = 'Swimming',
+                                   SelectionSequences = [selectionSeq])
+    elif config.getProp('OutputType') == 'DST':
+        from DSTWriters.__dev__.streamconf import OutputStreamConf
+        from DSTWriters.__dev__.Configuration import SelDSTWriter
+        streamConf = OutputStreamConf(streamType = InputCopyStream,
+                                      fileExtension = '.dst',
+                                      extraItems = [config.getProp('OffCands') + '/P2TPRelations#1',
+                                                    config.getProp('SwimmingPrefix') + '/Reports#1'])
+        SelDSTWriterElements = {'default' : []}
+        SelDSTWriterConf = {'default' : streamConf}
+        dstWriter = SelDSTWriter('FullDST',
+                                 StreamConf         = SelDSTWriterConf,
+                                 MicroDSTElements   = SelDSTWriterElements,
+                                 WriteFSR           = config.getProp('WriteFSR'),
+                                 OutputFileSuffix   = 'Swimming',
+                                 SelectionSequences = [selectionSeq])
+
+    DaVinci().appendToMainSequence([dstWriter.sequence()])
diff --git a/Phys/Swimming/python/Swimming/EventLoop.py b/Phys/Swimming/python/Swimming/EventLoop.py
new file mode 100644
index 000000000..cf5e7b7e7
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/EventLoop.py
@@ -0,0 +1,359 @@
+from Configurables import Swimming
+from os import environ
+from pprint import pprint
+from math import *
+
+# I'm being lazy here
+swimStripping           = Swimming().getProp('SwimStripping')
+nEvents                 = Swimming().getProp('EvtMax')
+offCands                = Swimming().getProp('OffCands')
+swimCands               = Swimming().getProp('SwimmingPrefix')
+offlinePVs              = Swimming().getProp('OfflinePV')
+DEBUGMODE               = Swimming().getProp('Debug')
+startingEvent           = Swimming().getProp('SkipEvents')
+
+# Shorter names for some of the options
+# The maximum swimming distance is maxSwimDistance (in mm)
+# The inital granularity is in mm
+# The number of passes is how many times we try to revise the
+# precision with which the acceptance function is known  
+# maxSwimDistance should be an integer multiple of the
+# initialGranularity  
+maxSwimDistance         = Swimming().getProp('MaxSwimDistance')
+initialGranularity      = Swimming().getProp('InitialGranularity')
+# By how much to divide the granularity each time
+# and how many times to refine
+granularityRefinement   = Swimming().getProp('GranularityRefinement')
+numberOfRefinements     = Swimming().getProp('NumberOfRefinements')
+# Add some swimming in "outer" regions of propertime to study potential
+# upper lifetime acceptance effects
+# Here the granularity is deliberately coarser
+# Again, extraSwimDistance should be an integer
+# multiple of the extraGranularity 
+extraSwimDistance       = Swimming().getProp('ExtraSwimDistance')
+extraGranularity        = Swimming().getProp('ExtraGranularity')
+# Swim the stripping or the trigger?
+# default is the trigger, switch this to true
+# if you want to swim the stripping (and/or offline)
+swimOffsel              = Swimming().getProp('SwimOffSel')
+
+writerName = None
+if not swimStripping:
+    writerName = 'Writer'
+elif Swimming().getProp('OutputType') == 'MDST':
+    writerName = 'MicroDSTMainSeq'
+elif Swimming().getProp('OutputType') == 'DST':
+    writerName = 'FullDSTMainSeq'
+def SwimmingEventLoop(gaudi, nEvents):
+    import GaudiPython
+    StatusCode = GaudiPython.gbl.StatusCode
+    from Swimming.decorators import (LHCb,
+                                     SwimmingReports,
+                                     P2TPRelation,
+                                     SharedParticles,
+                                     std_map_ulb,
+                                     std_map_sb,
+                                     std_map_sinfo)
+    gaudi = GaudiPython.AppMgr(outputlevel = 3)
+    gaudi.initialize()
+    TES = gaudi.evtsvc()
+    SEL = gaudi.evtSel()
+    SEL.OutputLevel = 6
+    SEL.firstEvent = startingEvent
+
+    #Now after the initialize some more job dependent stuff
+    if swimStripping :
+        dod = gaudi.service('DataOnDemandSvc')
+        outputs = gaudi.algorithm('killStripping').Nodes
+        for l in dod.AlgMap.keys():
+            if l.find('Phys') == -1:
+                continue
+            l = '/'.join(l.split('/')[:-1])
+            outputs.append(l)
+        gaudi.algorithm('killStripping').Nodes = outputs
+        gaudi.algorithm('killStrippingSeq').Enable  = False
+        gaudi.algorithm('StrippingGlobal').Enable   = False
+        gaudi.algorithm(writerName).Enable   = False
+        triggers = Swimming().getProp('StripCands')
+    #Tools needed for for tistosing
+    else :
+        for algo in ['killHltSeq', 'seqL0', 'Hlt',
+                     'HltSelReportsWriter', writerName,
+                     'HltDecReportsWriter', 'HltVertexReportsWriter',
+                     'HltLumiWriter', 'HltLumiStripper',
+                     'HltRoutingBitsWriter']:
+            gaudi.algorithm(algo).Enable = False
+        hlt1triggers = Swimming().getProp('Hlt1Triggers')
+        hlt2triggers = Swimming().getProp('Hlt2Triggers')
+        triggers     = [hlt1triggers,hlt2triggers]
+
+    #The tis tos tool
+    tistostool      = gaudi.toolsvc().create('TriggerTisTos'    ,interface='ITriggerTisTos')
+    tistosbools     = [tistostool.kAnything,tistostool.kTrueRequired,tistostool.kFalseRequired]
+    #The tools used for swimming the stripping/offline
+    m_lifetimeTool  = gaudi.toolsvc().create(Swimming().getProp('TauCalc'), interface = 'ILifetimeFitter')
+    m_distanceTool  = gaudi.toolsvc().create(Swimming().getProp('DistCalc'), interface = 'IDistanceCalculator')
+    m_relatedPVTool = gaudi.toolsvc().create(Swimming().getProp('RelPVFinder'), interface = 'IRelatedPVFinder')
+
+    #Make the class of globals for passing information around
+
+    from GaudiPython import InterfaceCast
+    tmpSvc = gaudi.service("IncidentSvc")
+    incidentSvc = InterfaceCast("IIncidentSvc")(tmpSvc.getInterface())
+
+    from Swimming.Globals import globalParams
+    myGlobs = globalParams( GaudiPython, gaudi, SEL, TES, incidentSvc,
+                            m_lifetimeTool, m_distanceTool, m_relatedPVTool,
+                            tistostool, tistosbools, triggers, 
+                            Swimming().getProp('Hlt1RecoLine'), Swimming().getProp('Hlt2RecoLine'),
+                            granularityRefinement,
+                            DEBUGMODE, startingEvent, swimStripping, Swimming().getProp('SwimOffSel'),
+                            Swimming().getProp('OffSelModuleName'), offCands, offlinePVs
+                          )
+
+    # Import the utilities
+    from Swimming.SwimmingUtils import (getBinfo, runSwimmingStep,
+                                        createObject, getSelector)
+    from Swimming.RefineTPs import refine
+    from Swimming.SwimmingTisTos import evaluateTisTos 
+
+    # The turning points contain the following information
+    #
+    # The raw position of the turning point in mm (relative to the
+    # point at which the B/D was measured), the lifetime of the B/D
+    # at the turning point, the IP of the B/D at the turning point,
+    # and of course the trigger decision at that turning point.
+    #
+    # In addition we store information about individual tracks in the
+    # signal, in order to deal with inclusive triggers which only require
+    # a part of the signal to fire.
+    #
+    # The information on which triggers were TOS at which stage
+    # If a logical OR of the triggers is being requested, then 
+    # a new turning point is set every time that either one of the trigger
+    # decisions changes. 
+    #
+    # The information on which tracks were TOS in
+    # HLT1. To save space this is stored as an integer,
+    # whose first and last digits are 9 and the digits
+    # inbetween are 1 or 0 depending on whether the
+    # given track was TOS in HLT1 or not. This is relevant
+    # for swimming the 1Track trigger only.     
+    #
+    # The information on which tracks played a part in the
+    # HLT2 decision. Important for swimming inclusive HLT2
+    # triggers or swimming multiple triggers in the same job.
+    #
+    # Which tracks were Reco'd in HLT1 and HLT2 
+    # again this is given in the format specified above
+    #
+    # Which tracks were Rec'ible in the VELO, offline (3 hits) or 
+    # in HLT1 (5 hits)
+    #
+    # Get the candidate selector.
+    selector = getSelector(Swimming().getProp('SelectMethod'))(myGlobs)
+
+    # Initialize at -1 so the eventNumber can be incremented at the top of the loop.
+    eventNumber = -1
+    while True:
+        # Increment event number
+        eventNumber += 1
+
+        # Check if we've hit the maximum
+        if (nEvents != -1 and eventNumber > nEvents):
+            print "Finished processing events"
+            break
+        elif (eventNumber % 100) == 0: 
+            print "Processing event", eventNumber
+
+        # Containers to store the turningpoints
+        roughTurningPoints = []
+        finalTurningPointsForWriting = []
+
+        gaudi.run(1)
+        if not TES["/Event/Rec/Header"] :
+                print "Reached end of file, we're done!"
+                break
+
+        odin = TES['/Event/DAQ/ODIN']
+        if DEBUGMODE :
+            print "Processing %d %d" % (odin.runNumber(), odin.eventNumber())
+        if not swimStripping and \
+               odin.triggerConfigurationKey() != int(Swimming().getProp('TCK'), 16):
+            print "WARNING, TCK 0x%08x does not match configured TCK %s, skipping event." \
+                  % (odin.triggerConfigurationKey(), Swimming().getProp('TCK'))
+            continue
+        
+        #Safety checks
+        mycands = TES[offCands + "/Particles"]
+        if not mycands :
+            if DEBUGMODE :
+                print "Problem while processing event number",startingEvent+eventNumber
+                print "No container of offline candidates found!"
+                print "Skipping the event but this is bad, check what you are doing!!"   
+            continue
+        if mycands.size() == 0 : 
+            if DEBUGMODE :
+                print "Problem while processing event number",startingEvent+eventNumber
+                print "Container of offline candidates empty!" 
+                print "Skipping the event but this is bad, check what you are doing!!"
+            continue
+        if DEBUGMODE :
+            print "Passed the safety checks OK"
+            print "Candidates in event =", mycands.size()
+
+        # Select the candidate to swim
+        mycand = selector(mycands)
+        if not mycand:
+            print "Somehow there is no candidate!!! This should never happen."
+            print "Skipping this event."
+            continue
+            
+        if DEBUGMODE :
+            print "Got the offline candidate OK"
+            print "About to store its information"
+            print mycand
+
+        # If we are swimming the trigger and have a non-trivial selection method,
+        # put the selected candidate in a separate location.
+        if not swimStripping and Swimming().getProp('SelectMethod') != 'none':
+            swimmingParticles = createObject(SharedParticles)
+            swimmingParticles.insert(mycand)
+            TES.registerObject(swimCands + '/Particles', swimmingParticles)
+            
+        HltDecLast  = None
+        HltDec      = None
+        swimLoop    = int(-1.*maxSwimDistance + -1.*extraSwimDistance)
+        while (swimLoop <= (maxSwimDistance + extraSwimDistance)) :
+            if DEBUGMODE:
+                print "Running over event", startingEvent+eventNumber,"swimming step",swimLoop             
+            # We got this far now get the candidate and, for the "zero" step only
+            # fill the corresponding event variables for it 
+            # Note that this function call also executes the stripping algorithm
+            # having moved the primary vertices around first
+            runSwimmingStep(myGlobs, mycand, swimLoop)
+
+            # Now get the trigger decision for this swimming step
+            HltDec = evaluateTisTos(myGlobs,mycand)
+            if DEBUGMODE :
+                print "Retrieved HLT decision",HltDec,"OK for this event" 
+
+            # If this is the very first swimming step, set HltDecLast to the global
+            # HltDec at this point, otherwise get it from the previous step.
+            if swimLoop == int(-1.*maxSwimDistance + -1.*extraSwimDistance):
+                HltDecLast = HltDec
+            elif roughTurningPoints != []:
+                HltDecLast = roughTurningPoints[-1][3]
+
+            # The first and last point are a special case for the bookkeeping
+            # as we want to record the limits of our swimming and the trigger
+            # decisions at these limits 
+            if (abs(swimLoop) == int(1.*maxSwimDistance + 1.*extraSwimDistance)) or \
+               (HltDec != HltDecLast): 
+                # Get the lifetime and IP of the B/D with respect to its favourite PV
+                bParams = getBinfo(myGlobs,mycand)
+                roughTurningPoints.append([swimLoop,bParams[0],bParams[1],HltDec,HltDecLast])
+        
+            # Now the granularity varies with the position 
+            # We swim more finely close to the actual decay point
+            if ((swimLoop >= -int(maxSwimDistance)) and (swimLoop < int(maxSwimDistance))) :
+                swimLoop += int(initialGranularity)
+            else :
+                swimLoop += int(extraGranularity) 
+        # Now the refinement step
+        # We have to refine every turning point, but the first and last
+        # ones which we save don't count as they are just there to
+        # demarcate the limits of our search, so we don't use them
+        if roughTurningPoints == [] :
+            continue
+        if DEBUGMODE :
+            print "****************************"
+            print "The rough turning points are"
+            pprint(roughTurningPoints)
+            print "****************************"
+        for thisturn in roughTurningPoints:
+            # Write the first and last as is, no refinement
+            if (thisturn == roughTurningPoints[0]) or (thisturn == roughTurningPoints[-1]) :
+                finalTurningPointsForWriting.append(thisturn)
+                continue
+            if DEBUGMODE :
+                print "****************************"
+                print "About to refine TP"
+                pprint(thisturn)
+                print "****************************"
+            if ((thisturn[0] > -int(maxSwimDistance)) and (thisturn[0] <= int(maxSwimDistance))) :
+                finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,initialGranularity,numberOfRefinements)
+            else : 
+                finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,extraGranularity,numberOfRefinements)
+        if DEBUGMODE :
+            print "****************************"
+            print "The final turning points for writing are:" 
+            pprint(finalTurningPointsForWriting)
+            print "****************************" 
+
+        # Which stage are we swimming?
+        stage = None
+        if swimStripping:
+            stage = 'Stripping'
+        else:
+            stage = 'Trigger'
+
+        # Get or Create the KeyedContainer for the SwimmingReports
+        reportLocation = Swimming().getProp('SwimmingPrefix') + '/Reports'
+        reports = TES[reportLocation]
+        if not reports:
+            reports = createObject(SwimmingReports)
+            # Put the container in the TES
+            sc = TES.registerObject(reportLocation, reports)
+            if not sc.isSuccess():
+                print "Failed to register SwimmingReports in TES"
+                break
+        # Get or create the SwimmingReport
+        report = reports(mycand.key())
+        if not report:
+            report = createObject(LHCb.SwimmingReport, mycand)
+            # Put the SwimmingReport in the container.
+            reports.insert(report)
+        elif report.hasStage(stage):
+            print "WARNING, stage %s already present, this is unsupported and will fail!"
+            return StatusCode(False)
+        
+        # Create the TurningPoint objects and put them in the report
+        for turn in finalTurningPointsForWriting:
+            d = std_map_sb()
+            for decision, value in turn[3][1].iteritems():
+                d[decision] = value
+            m = std_map_sinfo()
+            for decision, info in turn[3][2].iteritems():
+                i = std_map_ulb()
+                for k, v in info.iteritems():
+                    i[k] = v
+                m[decision] = i
+            tp = LHCb.TurningPoint(turn[0], turn[1], turn[2], turn[3][0], d, m)
+            report.addTurningPoint(stage, tp)
+
+        # Create the relations table
+        relations = TES[offCands + '/P2TPRelations']
+        if not relations:
+            relations = createObject(P2TPRelation)
+            # Put the relations table in the TES
+            sc = TES.registerObject(offCands + '/P2TPRelations', relations)
+            if not sc.isSuccess():
+                print "Failed to register SwimmingReports in TES"
+                break
+
+        from Swimming.SwimmingTisTos import appendToFSP
+        particles = [mycand]
+        appendToFSP(mycand, particles)
+        for particle in particles:
+            rel = relations.relations(particle)
+            if rel.empty():
+                relations.relate(particle, report)
+            elif rel(0).to().key() != report.key():
+                print "There is a relation, but it points to another swimming report, this is very bad!!"
+                return StatusCode(False)
+
+        # Write the Output
+        myGlobs.gaudi.algorithm(writerName).execute()
+
+    return StatusCode(True)
diff --git a/Phys/Swimming/python/Swimming/GeneralSetup.py b/Phys/Swimming/python/Swimming/GeneralSetup.py
new file mode 100644
index 000000000..41a10d420
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/GeneralSetup.py
@@ -0,0 +1,16 @@
+#some more general options which come before
+#the gaudi.initialize step
+from LHCbKernel.Configuration import *
+from Configurables import DataOnDemandSvc,CondDB
+from Configurables import DstConf, CaloDstUnPackConf
+from Configurables import Gaudi__IODataManager as IODataManager
+CaloDstUnPackConf ( Enable = True )
+DstConf           ( EnableUnpack = True )
+CondDB().IgnoreHeartBeat = True
+IODataManager().UseGFAL=False
+importOptions("$STDOPTS/DecodeRawEvent.py")
+appConf = ApplicationMgr()
+appConf.HistogramPersistency = 'ROOT'
+appConf.ExtSvc += ['DataOnDemandSvc']
+EventSelector().PrintFreq = -1
+EventSelector().OutputLevel = 6 
diff --git a/Phys/Swimming/python/Swimming/GetVeloAcceptance.py b/Phys/Swimming/python/Swimming/GetVeloAcceptance.py
new file mode 100644
index 000000000..6a4ace56a
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/GetVeloAcceptance.py
@@ -0,0 +1,55 @@
+# Functions to compute the VELO geometric acceptance 
+from math import exp, sqrt, cos, asin, floor, fabs
+
+__all__ = ["trackInVELOAcceptance"]
+
+z_strip_A = [ -175., -145., -115., -85., -55., -25., 5., 35., 65., 95., 125., 155., 185., 215., 245., 275., 435., 585., 635., 685., 735. ]
+z_strip_C = [ -160., -130., -100., -70., -40., -10.,20., 50., 80.,110., 140., 170., 200., 230., 260., 300., 450., 600., 650., 700., 750. ]
+r_min = 8.2
+r_max = 40.
+
+def z_from_radius( x0, y0, z0, tx, ty, r1 ):
+  # returns z position where particle with direction tx, ty coming from x0, y0, z0 reaches radius r1
+  tr2 = tx * tx + ty * ty
+  if 0 == tr2: 
+    return -1000.
+  ratio = ( x0 * tx + y0 * ty ) / tr2
+  #rad = ratio * ratio + r1 * r1 - x0 * x0 - y0 * y0
+  rad = ratio * ratio + ( r1 * r1 - x0 * x0 - y0 * y0 ) / tr2
+  if rad <= 0: 
+    return -1000.
+  return z0 - ratio + sqrt( rad )
+
+def n_mods_z_range( z1, z2, z_positions ):
+  # returns number of modules with z coordinates between z1 and z2
+  n = 0
+  for z in z_positions:
+    if z > z1 and z < z2: n += 1
+  return n
+
+def _trackInVELOAcceptance( x, y, z, tx1, ty1, n_min ):
+  r = sqrt( x*x+y*y )
+  n1 = 0
+  if r < r_max : 
+    if r > r_min:
+      z1_min = z
+      z1_max = z_from_radius( x, y, z, tx1, ty1, r_max )
+    else:  
+      z1_min = z_from_radius( x, y, z, tx1, ty1, r_min )
+      z1_max = z_from_radius( x, y, z, tx1, ty1, r_max )
+    if ( x + tx1 * ( z1_min - z ) ) > 0: 
+      n1 = n_mods_z_range( z1_min, z1_max, z_strip_A )
+    else:  
+      n1 = n_mods_z_range( z1_min, z1_max, z_strip_C )
+  if n1 >= n_min:
+    return 1
+  return 0    
+
+def trackInVELOAcceptance( parent, track, minhits) :
+  x  = parent.endVertex().position().x()
+  y  = parent.endVertex().position().y()
+  z  = parent.endVertex().position().z()  
+  tx = track.slopes().x()
+  ty = track.slopes().y()
+  return _trackInVELOAcceptance(x,y,z,tx,ty,minhits)
+
diff --git a/Phys/Swimming/python/Swimming/Globals.py b/Phys/Swimming/python/Swimming/Globals.py
new file mode 100644
index 000000000..8d96e6927
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/Globals.py
@@ -0,0 +1,51 @@
+#Defines the "global" objects to be
+#used across the various modules and 
+#functions
+
+class globalParams:
+    def __init__(self,gp,
+                 gaudi,SEL,TES,incidentSvc,
+                 m_lifetimeTool,m_distanceTool,m_relatedPVTool,
+                 tistostool,tistosbools,triggers,
+                 hlt1recoline,hlt2recoline,
+                 granularityRefinement,
+                 DEBUGMODE,startingEvent,swimStripping,swimOffline,
+                 offSelName,offCands,offlinePVs
+                ) :
+        self.GaudiPython = gp
+        self.incidentSvc = incidentSvc
+        self.gaudi = gaudi
+        self.TES   = TES
+        self.SEL   = SEL
+     
+        self.m_lifetimeTool  = m_lifetimeTool
+        self.m_distanceTool  = m_distanceTool
+        self.m_relatedPVTool = m_relatedPVTool       
+
+        self.tistostool     = tistostool
+        self.tistosbools    = tistosbools
+        self.triggers       = triggers
+       
+        self.hlt1recoline   = hlt1recoline
+        self.hlt2recoline   = hlt2recoline
+ 
+        self.granularityRefinement  = granularityRefinement
+        self.DEBUGMODE              = DEBUGMODE
+        self.startingEvent          = startingEvent
+        self.swimStripping          = swimStripping
+        self.swimOffline            = swimOffline
+        
+        self.offSelName             = offSelName
+        self.offCands               = offCands
+        self.offlinePVs             = offlinePVs          
+
+        # These are some default setups for return values,
+        # - The first value is a global Pass/Fail
+        # - The second a {name : boolean} where the name is a trigger
+        # decision or a stripping candidate location
+        # - The third is only filled for when swimming the trigger with a {name : {FSP.key() : boolean}}
+        if not swimStripping:
+            self.HltDecFalse = (False, {}, {})
+        else:
+            self.StrDecFalse = (False, {triggers : False}, {})
+            self.StrDecTrue  = (True , {triggers : True },  {})
diff --git a/Phys/Swimming/python/Swimming/HltTransforms.py b/Phys/Swimming/python/Swimming/HltTransforms.py
new file mode 100644
index 000000000..b75d94801
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/HltTransforms.py
@@ -0,0 +1,66 @@
+def getTransform(name,triggerstorun) :
+  if name == "2010" :
+    return { 'GaudiSequencer/.*' : 
+                                    { 'Members' : 
+                                                    { "'PatPV3D/HltPVsPV3D' , 'HltVertexFilter/Hlt1PreparePV3D'" : 
+                                                      "'PatPV3D/HltPVsPV3D', 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'" 
+                                                    } 
+                                    } ,
+             'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} ,
+             'GaudiSequencer/Hlt1TrackPhotonFilterSequence' :
+                                    { 'Members' :
+                                                    { "'HltTrackFilter/Hlt1TrackPhotonTFOTIP' , 'HltTrackFilter/Hlt1TrackPhotonTFOTNH' , 'HltTrackFilter/Hlt1TrackPhotonTFOTEXH' , 'HltTrackUpgrade/Hlt1TrackPhotonTUForward' , 'HltTrackFilter/Hlt1TrackPhotonTFOTPT' , 'HltTrackFilter/Hlt1TrackPhotonTFOTMom' , 'HltTrackUpgrade/Hlt1TrackPhotonTUFitTrack' , 'HltTrackFilter/Hlt1TrackPhotonTFTrkChi2' , 'HltFilterFittedTracks/Hlt1TrackPhotonHltFilterFittedTracksFFT'" :
+                                                      "'HltTrackUpgrade/Hlt1TrackPhotonTUForward' , 'HltTrackUpgrade/Hlt1TrackPhotonTUFitTrack'"
+                                                    }
+                                    } ,
+             'HltTrackUpgrade/Hlt1TrackPhotonTUForward' : { 'InputSelection'  : { 'Hlt1TrackPhotonTFOTEXH' : 'Velo'}} ,
+             'HltTrackUpgrade/Hlt1TrackPhotonTUFitTrack': { 'OutputSelection' : { 'Hlt1TrackPhotonTUFitTrack' : 'Hlt1TrackPhotonDecision' } ,
+                                                            'InputSelection'  : { 'Hlt1TrackPhotonTFOTMom' : 'Hlt1TrackPhotonTUForward'} 
+                                                          } ,
+             'LoKi::L0Filter/Hlt1TrackPhotonL0DUFilter' : { 'Code' : {"L0_CHANNEL.*Photon.*" : "L0_DECISION_PHYSICS"} }
+           }
+  elif name == "2011_NoBeamSpotFilter" :
+    PrescalerFiddlePrefix = 'DeterministicPrescaler/'
+    PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global)(?!Hlt1TrackPhoton).*PreScaler'
+    PrescalerFiddle = "".join(['(?!%s)'%trigger for trigger in triggerstorun]) 
+    return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}},
+            'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} ,
+            'LoKi::L0Filter/Hlt1TrackPhotonL0DUFilter' : { 'Code' : {"L0_CHANNEL('PhotonHi')|L0_CHANNEL('ElectronHi')" : "L0_DECISION_PHYSICS"} },
+            '.*HltUnit/Hlt1TrackPhotonUnit' : {'Code' : {"Velo.*EMPTY":"VeloCandidates>>LooseForward>>FitTrack>>SINK( 'Hlt1TrackPhotonDecision' )>>~TC_EMPTY"}},
+            'GaudiSequencer/.*' : {'Members':{"'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D'":
+                                              "'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}},
+            '.*HltUnit/.*': {'Preambulo' : {'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D':
+                                            'HltMoveVerticesForSwimming/HltMovePVs4Swimming'}}}
+  elif name == "2011_NoBeamSpotFilter_NoRecoLines" :
+    PrescalerFiddlePrefix = 'DeterministicPrescaler/'
+    PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global).*PreScaler'
+    PrescalerFiddle = "".join(['(?!%s)'%trigger for trigger in triggerstorun]) 
+    return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}},
+            'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} ,
+            'GaudiSequencer/.*' : {'Members':{"'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D'":
+                                              "'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}},
+            '.*HltUnit/.*': {'Preambulo' : {'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D':
+                                            'HltMoveVerticesForSwimming/HltMovePVs4Swimming'}}}
+  elif name == "2011_WithBeamSpotFilter" :
+    PrescalerFiddlePrefix = 'DeterministicPrescaler/'
+    PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global)(?!Hlt1TrackPhoton).*PreScaler'
+    PrescalerFiddle = "".join(['(?!%s)'%trigger.split('Decision')[0] for trigger in triggerstorun])
+    print PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix 
+    return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}},
+            'DeterministicPrescaler/Hlt1TrackForwardPassThroughLoosePreScaler' : { 'AcceptFraction' : {'.*' : '1'}} ,
+            'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} ,
+            'LoKi::L0Filter/Hlt1TrackPhotonL0DUFilter' : { 'Code' : {"L0_CHANNEL('PhotonHi')|L0_CHANNEL('ElectronHi')" : "L0_DECISION_PHYSICS"} },
+            '.*HltUnit/Hlt1TrackPhotonUnit' : {'Code' : {"Velo.*EMPTY":"VeloCandidates>>LooseForward>>FitTrack>>SINK( 'Hlt1TrackPhotonDecision' )>>~TC_EMPTY"}},
+            '.*HltPV3D': {'Code' : {"'PV3D'":"'PV3D_PreSwim'"}},
+            'GaudiSequencer/.*' : {'Members':{"HltPV3D'":"HltPV3D', 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}}} 
+  elif name == "2011_WithBeamSpotFilter_NoRecoLines" :
+    PrescalerFiddlePrefix = 'DeterministicPrescaler/'
+    PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global).*PreScaler'
+    PrescalerFiddle = "".join(['(?!%s)'%trigger.split('Decision')[0] for trigger in triggerstorun])
+    print PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix
+    return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}},
+            'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} ,
+            '.*HltPV3D': {'Code' : {"'PV3D'":"'PV3D_PreSwim'"}},
+            'GaudiSequencer/.*' : {'Members':{"HltPV3D'":"HltPV3D', 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}}}
+  else :
+    return {}
diff --git a/Phys/Swimming/python/Swimming/MooreSetup.py b/Phys/Swimming/python/Swimming/MooreSetup.py
new file mode 100644
index 000000000..3202963aa
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/MooreSetup.py
@@ -0,0 +1,12 @@
+#General options for swimming the trigger
+from Configurables import Moore,HltConfigSvc
+#Global configuration
+Moore().UseTCK = True
+Moore().L0 = True
+Moore().ReplaceL0BanksWithEmulated = False
+Moore().UseDBSnapshot = False
+Moore().EnableRunChangeHandler = False
+Moore().CheckOdin = False
+Moore().Verbose = False
+Moore().EnableDataOnDemand = True
+HltConfigSvc().optionsfile = '/tmp/dump.opts'
diff --git a/Phys/Swimming/python/Swimming/OfflineSelExample.py b/Phys/Swimming/python/Swimming/OfflineSelExample.py
new file mode 100644
index 000000000..1f7a21867
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/OfflineSelExample.py
@@ -0,0 +1,80 @@
+__all__=["OffSelFunc"]
+
+#
+# Example offline selection : B->hh
+#
+def OffSelFunc(myGlobs,Particle):
+    import ROOT
+    Result = 0 
+    #Cut variables here
+    Min_Mother_FD = 2.4 
+    Min_Mother_FDChi2 = 50
+    Max_Mother_IP = 0.09
+    Max_Mother_IPChi2 = 16  
+        
+    Mother_PT = 900 
+    Max_Daughter_PT = 2450
+    Min_Daughter_PT = 700 
+    Min_Daughter_P  = 13500
+
+    Max_Daughter_IP = 0.25
+    Min_Daughter_IP = 0.11
+    Max_Daughter_IPChi2 = 140.
+    Min_Daughter_IPChi2 = 80. 
+  
+    Min_Daughter_TrackChi2 = 3 
+    Max_Daughter_TrackChi2 = 4 
+ 
+    B_VertexBase = myGlobs.TES[myGlobs.offlinePVs]
+    B_imppar = 0.
+    p1_imppar = 0.
+    p2_imppar = 0.
+    B_chi2 = 0.
+    p1_chi2 = 0.
+    p2_chi2 = 0.
+    B_fd_chi2 = 0.  
+    B_fd = 0.
+
+    B_imppar = Double()
+    p1_imppar = Double()
+    p2_imppar = Double()
+    B_chi2 = Double()
+    p1_chi2 = Double()
+    p2_chi2 = Double()
+    B_fd_chi2 = Double()
+    B_fd = Double()   
+ 
+    myrelatedPV = myGlobs.m_relatedPVTool.relatedPV(Particle, B_VertexBase )#Feed function vertex base, which is then becomes best PV
+    myGlobs.m_distanceTool.distance( Particle, myrelatedPV, B_imppar, B_chi2 ) #vertex base here becomes is PV
+    myGlobs.m_distanceTool.distance( myrelatedPV,Particle.endVertex(),B_fd,B_fd_chi2)
+    # Calculate IP_chi2 for daughter particle 1
+    Daughter1 = Particle.daughters()[0].target() #Not sure about this
+    #need to get vertex base for daughter1
+    daug1relatedPV = myGlobs.m_relatedPVTool.relatedPV(Daughter1, B_VertexBase )
+    myGlobs.m_distanceTool.distance( Daughter1, daug1relatedPV, p1_imppar, p1_chi2 )
+    # Calculate IP_chi2 for daughter particle 2
+    Daughter2 = Particle.daughters()[1].target() #Not sure about this
+    #need to get vertex base for daughter2  
+    daug2relatedPV= myGlobs.m_relatedPVTool.relatedPV(Daughter2, B_VertexBase )
+    myGlobs.m_distanceTool.distance( Daughter2, daug2relatedPV, p2_imppar, p2_chi2 )
+    #Apply cut conditions to check if pass/fail
+    Min_daughter_chi2 = min(p1_chi2, p2_chi2)
+    Max_daughter_chi2 = max(p1_chi2, p2_chi2)
+    Min_daughter_ip   = min(p1_imppar, p2_imppar)
+    Max_daughter_ip   = max(p1_imppar, p2_imppar)
+
+    if myGlobs.DEBUGMODE:
+        print "Quantities to cut offline on:"
+        print Min_daughter_chi2, Max_daughter_chi2, Min_daughter_ip, Max_daughter_ip, B_imppar, B_chi2, B_fd, B_fd_chi2
+ 
+    if (Min_daughter_chi2 > Min_Daughter_IPChi2) and \
+       (Max_daughter_chi2 > Max_Daughter_IPChi2) and \
+       (Min_daughter_ip   > Min_Daughter_IP)     and \
+       (Max_daughter_ip   > Max_Daughter_IP)     and \
+       (B_imppar          < Max_Mother_IP)       and \
+       (B_chi2            < Max_Mother_IPChi2)   and \
+       (B_fd              > Min_Mother_FD)       and \
+       (B_fd_chi2         > Min_Mother_FDChi2) :
+        return True
+    else :
+        return False
diff --git a/Phys/Swimming/python/Swimming/RefineTPs.py b/Phys/Swimming/python/Swimming/RefineTPs.py
new file mode 100644
index 000000000..67e32cefe
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/RefineTPs.py
@@ -0,0 +1,66 @@
+from copy import copy
+from pprint import pprint
+__all__ = ["refine"]
+
+#The recursive refinement of the turning points
+def refine(myGlobs, mycand, thisturn, lastGranularity, numberOfRefinements) :
+    #
+    from SwimmingUtils  import getBinfo, runSwimmingStep
+    from SwimmingTisTos import evaluateTisTos
+
+    # This algorithm recursively refines the turning points searching
+    # around the current best estimate of the TP position. Since there
+    # exists a preferred direction (we swim from extremely positive to 
+    # extremely negative lifetimes), we only need to search on one side
+    # of the TP. If we know that at 40mm the decision was 0 and at 44mm
+    # it was 1, the refinement searches between 40 and 44. If you then
+    # find that 41.2mm was 0 and 41.6mm was 1 you search between these 
+    # two, and so on. 
+    HltDecLast = copy(thisturn[4])
+    refinedTurningPoints = []
+    # How far to swim
+    newGranularity = lastGranularity / myGlobs.granularityRefinement
+    # Where to start?
+    swimPoint = thisturn[0] - lastGranularity + newGranularity 
+    while (swimPoint < (thisturn[0] + newGranularity)) :
+        runSwimmingStep(myGlobs, mycand, swimPoint)
+        HltDec = evaluateTisTos(myGlobs, mycand)
+        if HltDec != HltDecLast:
+            bParams = getBinfo(myGlobs, mycand)
+            refinedTurningPoints.append([swimPoint, bParams[0], bParams[1], HltDec, HltDecLast])
+            HltDecLast = copy(HltDec)
+        swimPoint += newGranularity
+    if refinedTurningPoints == []:
+        refinedTurningPoints.append(thisturn)
+    #We finished this refinement, a little printout never hurt
+    if myGlobs.DEBUGMODE :
+        print "****************************"
+        print "The refined turning points are"
+        pprint(refinedTurningPoints)
+        print "****************************"
+    numberOfRefinements -= 1
+    if numberOfRefinements == 0:
+        # We're done and at the end of the recursion, so we split the last
+        # interval in 2 and have one extra calculation of candidate properties
+        # used to update the turning point. The TisTos information is kept.
+        for turn in refinedTurningPoints:
+            swimPoint = turn[0] + 0.5 * newGranularity
+            if myGlobs.DEBUGMODE:
+                print "final splitting of the interval which goes from %s to %s" % (turn[0], swimPoint)
+            runSwimmingStep(myGlobs, mycand, swimPoint)
+            bParams = getBinfo(myGlobs, mycand)
+            turn[0] = swimPoint
+            turn[1] = bParams[0]
+            turn[2] = bParams[1]
+        if myGlobs.DEBUGMODE :
+            print "****************************"
+            print "The final refined turning point is:"
+            pprint(refinedTurningPoints)
+            print "****************************"
+        return refinedTurningPoints
+    else :
+        #Need to refine every new turning point which we find
+        toreturn = []
+        for turn in refinedTurningPoints :
+            toreturn += refine(myGlobs, mycand, turn, newGranularity, numberOfRefinements)
+        return toreturn
diff --git a/Phys/Swimming/python/Swimming/SwimmingTisTos.py b/Phys/Swimming/python/Swimming/SwimmingTisTos.py
new file mode 100644
index 000000000..896d39815
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/SwimmingTisTos.py
@@ -0,0 +1,158 @@
+#The TISTOS function of the swimming. For TISTOSing the trigger
+#we use the regular TISTOS tools, the stripping is done "by hand"
+from collections import defaultdict
+from GaudiPython.Bindings import gbl
+hashParticle = gbl.Swimming.hashParticle
+
+__all__ = ["evaluateTisTos","appendToFSP"]
+
+def isTos(myGlobs,trigger) :
+    if (myGlobs.tistostool.hltObjectSummaries(  trigger,
+                                                myGlobs.tistosbools[0],
+                                                myGlobs.tistosbools[1]
+                                             ).size() != 0) :
+        return True
+    return False 
+
+def isTob(myGlobs,trigger) :
+    if (myGlobs.tistostool.hltObjectSummaries(  trigger,
+                                                myGlobs.tistosbools[2],
+                                                myGlobs.tistosbools[2]
+                                             ).size() != 0) :
+        return True
+    return False 
+
+def evaluateTisTos(myGlobs,mycand):
+    #Evaluate whether or not you TOS-ed on your triggers
+    decisions = {}
+    if not myGlobs.swimStripping :
+        myGlobs.tistostool.setOfflineInput()
+        myGlobs.tistostool.addToOfflineInput(mycand)
+        globalPass = True
+        for level in myGlobs.triggers :
+            passedlevel = False
+            for trigger in level :
+                if isTos(myGlobs,trigger) :
+                    decisions[trigger] = True
+                    passedlevel = True
+                else :
+                    decisions[trigger] = False
+            if not passedlevel:
+                globalPass = False
+
+        # So it passed the trigger, now we need to evaluate
+        # which tracks caused HLT1 to fire, and which were
+        # reco'd in HLT1 and HLT2
+        finalstateparts_mycand = []
+        appendToFSP(mycand,finalstateparts_mycand)
+        daughterInfo = defaultdict(dict)
+        for fsp in finalstateparts_mycand :
+            if globalPass:
+                myGlobs.tistostool.setOfflineInput()
+                myGlobs.tistostool.setOfflineInput(fsp)
+            h = hashParticle(fsp)
+            # First how many fired HLT1 
+            for trigger in myGlobs.triggers[0]:
+                daughterInfo['trTOS_'+trigger][h] = globalPass and (isTos(myGlobs, trigger) or isTob(myGlobs, trigger))
+            # Did this track play a part in the HLT2 yes?
+            for trigger in myGlobs.triggers[1]:
+                daughterInfo['trTOS_'+trigger][h] = globalPass and isTob(myGlobs, trigger)
+
+            # Now how many were recod in HLT1
+            daughterInfo['trRec_HLT1'][h] = globalPass and isTos(myGlobs,myGlobs.hlt1recoline)
+            # Now how many were recod in HLT2
+            daughterInfo['trRec_HLT2'][h] = globalPass and isTos(myGlobs,myGlobs.hlt2recoline)
+            # Now the VELO acceptance
+            from GetVeloAcceptance import trackInVELOAcceptance
+            iv3 = trackInVELOAcceptance(mycand, fsp.proto().track(), 3)
+            iv5 = trackInVELOAcceptance(mycand, fsp.proto().track(), 5)
+            daughterInfo['trRec_VELO_OFF'][h]   = globalPass and iv3
+            daughterInfo['trRec_VELO_HLT1'][h]  = globalPass and iv5
+                    
+        return (globalPass, decisions, dict(daughterInfo))
+    else :
+        if myGlobs.DEBUGMODE :
+            print "Evaluating TISTOS for stripping"
+            print "Will look for candidates at", myGlobs.triggers
+        candidates = myGlobs.TES[myGlobs.triggers+"/Particles"]
+        if not candidates:
+            if myGlobs.DEBUGMODE :
+                print "Found no candidates, returning false" 
+            return myGlobs.StrDecFalse
+        else :
+            if candidates.size() == 0:
+                if myGlobs.DEBUGMODE :
+                    print "0 candidates found, return False"
+                return myGlobs.StrDecFalse
+            else :
+                if myGlobs.DEBUGMODE :
+                    print "Found", candidates.size(), "candidates"
+                    print "About to match them"
+                for i in xrange(candidates.size()):
+                    cand = candidates(i)
+                    if myGlobs.DEBUGMODE :
+                        print "########################"
+                        "About to match these two candidates"
+                        print cand,mycand
+                        print "########################"
+                    if matchCands(myGlobs,mycand,cand):
+                        # If we're not swimming the offline selection, we're done
+                        if not myGlobs.swimOffline :
+                            return myGlobs.StrDecTrue
+                        # Import offline selection
+                        OffSelFunc = __import__('Swimming.' + myGlobs.offSelName).OffSelFunc
+                        if OffSelFunc(myGlobs,mycand):
+                            return myGlobs.StrDecTrue
+        return myGlobs.StrDecFalse
+#
+#
+#
+#Two functions to match two candidates
+#together, one for particles the other one for tracks
+def matchLists(list1,list2) :
+    num = list1.size()
+    nummatch = 0
+    for id in list1 :
+        for ID in list2 :
+            if (id.lhcbID() == ID.lhcbID()) :
+                nummatch += 1
+                break
+    return nummatch/num
+#
+#
+#
+def appendToFSP(daughter,finalstateparticles) :
+    if daughter.isBasicParticle() : finalstateparticles += [daughter]
+    else :
+        for gd in daughter.daughtersVector() :
+            appendToFSP(gd, finalstateparticles)
+#
+#
+#
+def matchCands(myGlobs,cand1,cand2) :
+    finalstateparticles_cand1 = []
+    finalstateparticles_cand2 = []
+    appendToFSP(cand1,finalstateparticles_cand1)
+    appendToFSP(cand2,finalstateparticles_cand2)
+    num_cand1 = finalstateparticles_cand1.__len__()
+    num_cand2 = finalstateparticles_cand2.__len__()
+    nummatch = 0
+    if myGlobs.DEBUGMODE :
+        print "Number of daughters of each candidate"
+        print num_cand1,num_cand2
+    if num_cand1 <> num_cand2 :
+        print "Trying to match unequal candidates!"
+        print "You have probably supplied the wrong stripping or offline candidate location!"
+        print "The swimming will not work, returning False"
+        return False
+    else :
+        try :
+            for kid1 in finalstateparticles_cand1 :
+                for kid2 in finalstateparticles_cand2 :
+                    if matchLists(kid1.proto().track().lhcbIDs(),kid2.proto().track().lhcbIDs()) :
+                        nummatch += 1
+        except :
+            return False
+    if myGlobs.DEBUGMODE:
+        print (nummatch*1.)/(num_cand1*1.)
+    return (nummatch*1.)/(num_cand1*1.)
diff --git a/Phys/Swimming/python/Swimming/SwimmingUtils.py b/Phys/Swimming/python/Swimming/SwimmingUtils.py
new file mode 100644
index 000000000..0d9b4e0d3
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/SwimmingUtils.py
@@ -0,0 +1,136 @@
+#This file holds utility functions for the swimming job
+
+__all__ = ['getBinfo',
+           'runSwimmingStep',
+           'createObject',
+           'getSelector']
+
+import GaudiPython
+GaudiPython.loaddict( 'RandomFunctionsDict' )
+Random = GaudiPython.Bindings.gbl.Random
+
+def createObject(t, *args):
+    """ Function to create objects which are not owned by python, will not be
+    garbage collected and can therefore be put in the TES. """
+    i = t(*args)
+    import ROOT
+    ROOT.SetOwnership(i, False)
+    return i
+
+class RandomSelector(object):
+    def __init__(self, globs, extra = 'RandomSelector'):
+        self._extra = extra
+        self._initialRandom = Random.mixString(len(extra), extra)
+        self._TES = globs.TES
+ 
+    def __call__(self, candidates):
+        odin = self._TES['DAQ/ODIN']
+        r = self.random(odin)
+        n = candidates.size()
+        for i in xrange(n):
+            if r <= (float(i) / float(n)): break
+        return candidates.containedObjects()[i]
+
+    def random(self, odin):
+        x = self._initialRandom;
+        x = Random.mix64(x, odin.gpsTime())
+        x = Random.mix32(x, odin.runNumber())
+        x = Random.mix64(x, odin.eventNumber())
+        return float(x) / float(0xFFFFFFFF)
+
+class FirstSelector(object):
+    def __init__(self, *args):
+        pass
+
+    def __call__(self, candidates):
+        return candidates.containedObjects()[0]
+    
+_selectors = {'random' : RandomSelector,
+              'first'  : FirstSelector,
+              'none'   : FirstSelector}
+
+def getSelector(s):
+    return _selectors[s]
+
+#
+#
+#
+#Grab the two properties we are most interested in
+def getBinfo(myGlobs,mycand):
+    if not myGlobs.swimStripping :
+        return (myGlobs.gaudi.algorithm('HltMovePVs4Swimming')).Blifetime, (myGlobs.gaudi.algorithm('HltMovePVs4Swimming')).BipChi2
+    else :
+        temptimes = getcandpropertimeinfo(myGlobs,mycand)
+        return (temptimes[0],temptimes[4])
+#
+#
+#
+#Get the info of the candidate for the ntuple
+#in the case of swimming the stripping/offline
+def getcandpropertimeinfo(myGlobs,mycand):
+    #
+    myrelatedPV = myGlobs.m_relatedPVTool.relatedPV(mycand,myGlobs.TES[myGlobs.offlinePVs])
+    btimes = []
+    #now the temporary ROOT rubbish
+    import ROOT
+    #First the lifetime
+    tau     = ROOT.Double(-1000000.0)
+    tauerr  = ROOT.Double(-1000000.0)
+    tauchi2 = ROOT.Double(-1000000.0)
+    myGlobs.m_lifetimeTool.fit(myrelatedPV,mycand,tau,tauerr,tauchi2)
+    btimes.append(tau)
+    btimes.append(tauerr)
+    #Now the flight distance and ips
+    fd      = ROOT.Double(-1000000.0)
+    fdchi2  = ROOT.Double(-1000000.0)
+    mip     = ROOT.Double(-1000000.0)
+    mipchi2 = ROOT.Double(-1000000.0)
+    myGlobs.m_distanceTool.distance(mycand,myrelatedPV,mip,mipchi2)
+    myGlobs.m_distanceTool.distance(myrelatedPV,mycand.endVertex(),fd,fdchi2)
+    btimes.append(fdchi2)
+    btimes.append(mip)
+    btimes.append(mipchi2)
+    #Finally return the answer
+    return btimes
+#
+#
+#
+#Move the PV, for swimming the stripping
+def movePVs(myGlobs, mycand, swimLoop) :
+    if myGlobs.DEBUGMODE :
+        print "Old PV positions are"
+        for PV in myGlobs.TES[myGlobs.offlinePVs] :
+            print PV
+    for PV in myGlobs.TES[myGlobs.offlinePVs]:
+        PV.position().SetX(PV.position().X() + swimLoop * mycand.slopes().Unit().X())
+        PV.position().SetY(PV.position().Y() + swimLoop * mycand.slopes().Unit().Y())
+        PV.position().SetZ(PV.position().Z() + swimLoop * mycand.slopes().Unit().Z())    
+    if myGlobs.DEBUGMODE :
+        print "New PV positions are"
+        for PV in myGlobs.TES[myGlobs.offlinePVs] :
+            print PV
+    return True
+#
+#
+#                
+#
+def runSwimmingStep(myGlobs, mycand, swimLoop):
+    myGlobs.TES["/Event/Rec/ProtoP/Charged"]
+    myGlobs.TES["/Event/Rec/ProtoP/Neutrals"]
+    myGlobs.TES[myGlobs.offlinePVs]
+    if myGlobs.swimStripping:
+        myGlobs.incidentSvc.fireIncident(myGlobs.GaudiPython.gbl.Incident("VavaIncident","EndEvent"))
+        myGlobs.gaudi.executeEvent()
+        myGlobs.gaudi.algorithm("killStrippingSeq").execute()
+        if myGlobs.DEBUGMODE:
+            "About to move the PVs for the stripping"
+        movePVs(myGlobs, mycand, swimLoop)
+        myGlobs.gaudi.algorithm("StrippingGlobal").execute()
+    else :
+        myGlobs.incidentSvc.fireIncident(myGlobs.GaudiPython.gbl.Incident("VavaIncident","EndEvent"))
+        myGlobs.gaudi.executeEvent()
+        myGlobs.gaudi.algorithm("HltMovePVs4Swimming").SwimmingDistance = swimLoop
+        myGlobs.gaudi.algorithm("killHltSeq").execute()
+        myGlobs.gaudi.algorithm("seqL0").execute() 
+        myGlobs.gaudi.algorithm("Hlt").execute()
+    ## return myGlobs.TES[myGlobs.offCands+'/Particles'][0]
diff --git a/Phys/Swimming/python/Swimming/decorators.py b/Phys/Swimming/python/Swimming/decorators.py
new file mode 100644
index 000000000..5f032522c
--- /dev/null
+++ b/Phys/Swimming/python/Swimming/decorators.py
@@ -0,0 +1,36 @@
+from GaudiPython.Bindings import gbl
+
+__all__ = ['LHCb',
+           'SwimmingReports',
+           'P2TPRelation',
+           'SharedParticles',
+           'std_map_ulb',
+           'std_map_sb',
+           'std_map_sinfo']
+
+# Types
+LHCb            = gbl.LHCb
+SwimmingReports = gbl.KeyedContainer('LHCb::SwimmingReport', 'Containers::KeyedObjectManager<Containers::hashmap>')
+P2TPRelation    = LHCb.Relation2D('LHCb::Particle', 'LHCb::SwimmingReport')
+SharedParticles = gbl.SharedObjectsContainer('LHCb::Particle')
+
+std_map_sinfo       = gbl.std.map('string', 'map<unsigned long,bool>')
+
+# Decorate maps to bool with __call__
+std_map_ulb          = gbl.std.map('unsigned long', 'bool')
+pair_ulb             = gbl.std.pair('const unsigned long', 'bool')
+std_map_ulb.__pair   = pair_ulb
+
+std_map_sb          = gbl.std.map('string', 'bool')
+pair_sb             = gbl.std.pair('const string', 'bool')
+std_map_sb.__pair   = pair_sb
+
+def set_map(self, k, v):
+    p = self.__pair(k, v)
+    it = self.find(k)
+    if it != self.end():
+        self.erase(it)
+    self.insert(p)
+
+std_map_ulb.__setitem__ = set_map
+std_map_sb.__setitem__ = set_map
diff --git a/Phys/Swimming/scripts/RunSwimming.py b/Phys/Swimming/scripts/RunSwimming.py
new file mode 100644
index 000000000..6f3aeae05
--- /dev/null
+++ b/Phys/Swimming/scripts/RunSwimming.py
@@ -0,0 +1,632 @@
+'''
+The top level algorithm for the swimming
+'''
+
+__author__  = "Vladimir V. Gligorov"
+__date__    = "2011-04-14"
+
+#! /usr/bin/env python
+from os import environ
+from pprint import pprint
+import GaudiPython 
+from Gaudi.Configuration import *
+from GaudiConf.Configuration import *
+from GaudiPython import InterfaceCast
+from Gaudi import *
+from math import *
+import sys 
+from Swimming.decorators import *
+
+# Use the options parser to get the job options
+from optparse import OptionParser
+parser = OptionParser()
+# Toggles : Swim MC or Real data? (Real data is default)
+#         : Debug mode? Off by default, this prints out a LOT.
+#         : Swim the stripping? Off by default (hence swims trigger)
+#         : Swim an offline selection? Off by default, can only be 
+#           used when swimming the stripping.   
+parser.add_option("--root",             action = "store_true", dest = "ROOT",          default = False)
+parser.add_option("--mc",               action = "store_true", dest = "forMC",         default = False)
+parser.add_option("--debug",            action = "store_true", dest = "debug",         default = False)
+parser.add_option("--swimStripping",    action = "store_true", dest = "swimStripping", default = False)
+parser.add_option("--swimOffsel",       action = "store_true", dest = "swimOffsel",    default = False)
+# Basic options : number of events to swim
+#               : starting event number on DST
+#               : TCK to swim (only if swimStripping is False)
+#               : stripping stream (only swimStripping is True)
+#               : stripping version (only swimStripping is True)
+#               : stripping line (only one allowed, only if swimStripping is True)
+#               : the HLT1 triggers to swim (only if swimStripping is False)
+#               : the HLT2 triggers to swim (only if swimStripping is False)                
+#               : the name of the module holding the offline selection (only if swimStripping and swimOffsel are True) 
+parser.add_option("-n",                 action = "store", type = "string", dest = "numevents",       default = '10') 
+parser.add_option("-s",                 action = "store", type = "string", dest = "firstevent",      default = '0')
+parser.add_option("--TCK",              action = "store", type = "string", dest = "TCKid",           default = "0x00730035") 
+parser.add_option("--strippingStream",  action = "store", type = "string", dest = "strippingStream", default = "CharmCompleteEvent")
+parser.add_option("--strippingVersion", action = "store", type = "string", dest = "strippingVersion",default = "Stripping13b")
+parser.add_option("--strippingLine",    action = "store", type = "string", dest = "strippingLine",   default = "D2hh")
+parser.add_option("--strippingFile",    action = "store", type = "string", dest = "strippingFile",   default = "none")
+parser.add_option("--hlt1triggers",     action = "store", type = "string", dest = "hlt1triggers",    default = "Hlt1TrackAllL0Decision")
+parser.add_option("--hlt2triggers",     action = "store", type = "string", dest = "hlt2triggers",    default = "Hlt2CharmHadD02HH_D02KPiDecision")
+parser.add_option("--offselmodulename", action = "store", type = "string", dest = "offselmodulename",default = "OfflineSelExample")
+# In addition to the "regular" swimming, which tells us the 
+# trigger/stripping decision as a function of the candidate
+# propertime, we also need to know which parts of the signal
+# candidate were reconstructed in the trigger. This is because
+# e.g. in HLT1 we only need one track to trigger, but the
+# acceptance function is different depending on the number of
+# tracks which had the possibility to fire the trigger, i.e.
+# the number of tracks reconstructed in the trigger reconstruction.
+# The defaults should be sufficient for all 2011 data processing. 
+parser.add_option("--hlt1recoline",    action = "store", type = "string", dest="hlt1recoline", default = "Hlt1TrackForwardPassThroughLooseDecision")
+parser.add_option("--hlt2recoline",    action = "store", type = "string", dest="hlt2recoline", default = "Hlt2ForwardDecision")      
+# TES locations of candidates : offline
+#                             : stripping
+#                             : for the microDST writer
+parser.add_option("--offcands",        action = "store", type = "string", dest="offcands",
+                  default='/Event/CharmCompleteEvent/Phys/D2hhPromptD0RSSel')
+parser.add_option("--stripcands",      action = "store", type = "string", dest="stripcands",
+                  default="/Event/Phys/D2hhPromptD0RSSel")
+parser.add_option("--mudstcands",      action = "store", type = "string", dest="mudstlocation",
+                  default="/Event/CharmCompleteEvent/Phys/D2hhPromptDst2D2RSLine")
+# Other options : DDDB tag
+#               : CondDB tag
+#               : TES location of HLT PVs (default is fine for 2011 data)
+#               : TES location of Offline PVs (default is fine for 2011 data)
+#               : HLT selection name of PVs (default is fine for 2011 data)
+#               : Datatype
+parser.add_option("--dddb",            action = "store", type = "string", dest = "dddb",       default="head-20110302")
+parser.add_option("--conddb",          action = "store", type = "string", dest = "conddb",     default="head-20110407")
+parser.add_option("--onlinePV",        action = "store", type = "string", dest = "onlinePV",   default="TES:Hlt/Vertex/PV3D")
+parser.add_option("--offlinePV",       action = "store", type = "string", dest = "offlinePV",  default="/Event/Rec/Vertex/Primary")
+parser.add_option("--outPVSel",        action = "store", type = "string", dest = "outPVSel",   default="PV3D")
+parser.add_option("--datatype",        action = "store", type = "string", dest = "datatype",   default="2011")
+parser.add_option("--filestager",      action = "store_true", dest = "filestager", default = False)
+# Tool names    : defaults are fine for 2011 data, only for swimming the stripping
+parser.add_option("--relPVFinder",     action = "store", type = "string", dest = "relPVFinder", 
+                  default = "GenericParticle2PVRelator__p2PVWithIPChi2_OfflineDistanceCalculatorName_/P2PVWithIPChi2")
+parser.add_option("--distCalc",        action = "store", type = "string", dest = "distCalc",
+                  default = "LoKi::DistanceCalculator")
+parser.add_option("--tauCalc",         action = "store", type = "string", dest = "tauCalc",
+                  default = "PropertimeFitter")
+# The options for the swimming granularity etc.
+# Because we do not apriori know how many turning points there are in each event,
+# we need to swim in two steps. First we scan the Velo end-to-end with some given
+# granularity (default is 4mm). Then each turning point is iteratively refined
+# to a precision of around 16 microns (by default) in steps defined by the granularityRefinement
+# variable. For example if the initial granularity is 4mm and the granularityRefinement
+# is 4, the steps would be 4mm, 1mm, 0.25mm, 0.0625mm, 0.015625mm.
+#
+# The swimming is done in the direction of the B/D momentum.
+#
+# maxSwimDistance       : the maximum distance to swim (forward and backward) with the "fine" granularity 
+# initialGranularity    : the "fine" granularity with which to swim. 
+# granularityRefinement : how much to "refine" the granularity in each step. The initial granularity is divided by this number.
+# numberOfRefinements   : how many times to "refine" each turning point
+# extraSwimDistance     : the maximum distance to swim (forward and backward) beyond the "fine" granularity
+# extraGranularity      : the "coarse" granularity with which to swim.  
+parser.add_option("--maxSwimDistance",       action = "store", type = "float",   dest = "maxSwimDistance",       default = 200.) #mm
+parser.add_option("--initialGranularity",    action = "store", type = "float",   dest = "initialGranularity",    default = 4.)   #mm 
+parser.add_option("--granularityRefinement", action = "store", type = "float",   dest = "granularityRefinement", default = 4.)   #dimensionless
+parser.add_option("--numberOfRefinements",   action = "store", type = "int",     dest = "numberOfRefinements",   default = 4)    #dimensionless
+parser.add_option("--extraSwimDistance",     action = "store", type = "float",   dest = "extraSwimDistance",     default = 400.) #mm
+parser.add_option("--extraGranularity",      action = "store", type = "float",   dest = "extraGranularity",      default = 40.)  #mm
+# The name of the HLT transform to use. This is the code which modifies the TCK in order to allow the
+# trigger to be swum. This must match the data -- in particular in 2011 we recognise
+# two periods which need different transforms : with and without the beamspot filter for primary vertices.  
+parser.add_option("--transformName",         action = "store", type = "string",  dest = "transformName",         default = "2011_WithBeamSpotFilter")
+# For writing the data out
+parser.add_option("--swimReportLocation",    action = "store", type = "string",  dest = "swimRepLoc",            default = "/Event/Swimming/Reports") 
+parser.add_option("--outfilename",           action = "store", type = "string",  dest = "outfilename",           default = "SwimTrigDST.dst")
+# How to select a single candidate, none assumes that there is a single
+# candidate, random selects one at random and first selects the first candidate
+parser.add_option("--selectMethod",          action = "store", type = "string",  dest = "select",                default = "random")
+# Switch this on to make a quick interactive test on some Stripping13b charm
+# data
+parser.add_option("--test",                  action = "store_true",              dest = "interactiveTest",       default = False)
+(options, args) = parser.parse_args()
+
+from Swimming.HltTransforms import getTransform
+thisTransform = getTransform(options.transformName,options.hlt1triggers.split(',')+options.hlt2triggers.split(','))
+# Check for incompatible options!
+if not options.swimStripping and not thisTransform :
+    print "No or invalid HLT transform specified when trying to swim the trigger!"
+    sys.exit(-1)  
+if options.swimOffsel and not options.swimStripping :
+    print "You cannot swim the trigger and offline selection in the same job!"
+    print "Goodbye!"
+    sys.exit(-1)
+
+if options.select not in ['random', 'first', 'none']:
+    print 'The selectMethod must be eiter "random", "first" or "none".'
+    sys.exit(-1)
+
+# Shorter names for some of the options
+nEvents                 = int(options.numevents)
+offCands                = options.offcands
+swimCands               = '/Event/Swimming'
+offlinePVs              = options.offlinePV
+DEBUGMODE               = options.debug
+startingEvent           = int(options.firstevent)
+# The maximum swimming distance is maxSwimDistance (in mm)
+# The inital granularity is in mm
+# The number of passes is how many times we try to revise the
+# precision with which the acceptance function is known  
+# maxSwimDistance should be an integer multiple of the
+# initialGranularity  
+maxSwimDistance         = options.maxSwimDistance
+initialGranularity      = options.initialGranularity
+# By how much to divide the granularity each time
+# and how many times to refine
+granularityRefinement   = options.granularityRefinement 
+numberOfRefinements     = options.numberOfRefinements
+# Add some swimming in "outer" regions of propertime to study potential
+# upper lifetime acceptance effects
+# Here the granularity is deliberately coarser
+# Again, extraSwimDistance should be an integer
+# multiple of the extraGranularity 
+extraSwimDistance       = options.extraSwimDistance
+extraGranularity        = options.extraGranularity
+# Swim the stripping or the trigger?
+# default is the trigger, switch this to true
+# if you want to swim the stripping (and/or offline)
+swimStripping           = options.swimStripping
+swimOffsel              = options.swimOffsel
+
+if swimStripping :
+    from Configurables import DaVinci
+    from StrippingConf.Configuration import StrippingConf
+    from Configurables import ProcStatusCheck
+    from Configurables import EventNodeKiller,GaudiSequencer
+    from PhysSelPython.Wrappers import AutomaticData, SelectionSequence
+    #
+    from StrippingSettings.Utils import lineBuilderConfiguration
+    strippingFile = None
+    if options.strippingFile != 'none':
+        strippingFile = options.strippingFile
+    else:
+        strippingFile = options.strippingLine
+    myconfig = lineBuilderConfiguration(options.strippingVersion, options.strippingLine)
+    import StrippingSelections
+    mylineconf = getattr(__import__('StrippingSelections.Stripping' + strippingFile,
+                                    globals(),locals(),
+                                    [myconfig["BUILDERTYPE"]],-1),myconfig["BUILDERTYPE"])
+    mylinedict = myconfig["CONFIG"]
+    print mylineconf
+    print mylinedict
+    from StrippingConf.StrippingStream import StrippingStream
+    stream = StrippingStream(options.strippingStream + "Swimming")
+    allLines = mylineconf(options.strippingLine, mylinedict).lines()
+    lines = []
+    for l in allLines:
+        lineName = options.stripcands.split('/')[-1]
+        if l.outputLocation().find(lineName) != -1:
+            lines.append(l)
+    stream.appendLines(lines)
+    #Define the stream
+    filterBadEvents = ProcStatusCheck()
+    sc = StrippingConf( Streams = [stream],
+                        MaxCandidates       = 2000,
+                        AcceptBadEvents     = False,
+                        BadEventSelection   = filterBadEvents )
+    #Define the node killer, and make sure to kill everything corresponding to
+    #the stream which we want to swim
+    outputs = []
+    for l in lines:
+        for f in l.filterMembers():
+            if not hasattr(f, 'Output'):
+                continue
+            # Remove the last item so we get everything (Particle, relations,
+            # decayVertices, etc...
+            o = '/'.join(f.Output.split('/')[:-1])
+            outputs.append(o)
+    mykiller    = EventNodeKiller("killStripping")
+    #Some default nodes which we will want to kill in all cases
+    nodestokill = outputs + ['Strip', '/Event/Rec/Vertex/Primary']
+    mykiller.Nodes          = nodestokill 
+    deathstar               = GaudiSequencer("killStrippingSeq")
+    deathstar.Members       = [mykiller]
+    # Configure DaVinci
+    DaVinci().InputType     = 'DST'
+    DaVinci().DataType      = options.datatype
+    DaVinci().Simulation    = options.forMC
+    DaVinci().DDDBtag       = options.dddb
+    DaVinci().CondDBtag     = options.conddb
+    # The sequence for the swimming has to be configured 
+    # by hand inserting the node killer before it
+    DaVinci().appendToMainSequence( [deathstar] )
+    DaVinci().appendToMainSequence( [ sc.sequence() ] )
+    #uDST writer
+    from DSTWriters.__dev__.Configuration import MicroDSTWriter, microDSTStreamConf
+    from DSTWriters.__dev__.microdstelements import *
+    SwimmingConf = microDSTStreamConf()
+    streamConf = { 'default' : SwimmingConf }
+    SwimmingElements = [ CloneRecHeader(),
+                         CloneODIN(),
+                         ClonePVs(),
+                         CloneSwimmingReports(),
+                         CloneParticleTrees(copyProtoParticles = True),
+                         ClonePVRelations("Particle2VertexRelations", True),
+                         CloneTPRelations("P2TPRelations", True),
+                         ReFitAndClonePVs(),
+                         CloneLHCbIDs(),
+                         CloneRawBanks(banks = ['HltSelReports', 'HltDecReports',
+                                                'L0DU', 'L0Calo', 'L0CaloError', 'L0CaloFull',
+                                                'L0Muon', 'L0MuonProcCand', 'L0MuonError'],
+                                        inputRawEvent = 'DAQ/RawEvent')]
+    elementsConf = { 'default' : SwimmingElements }
+    inputData = AutomaticData(Location = offCands + "/Particles")
+    selectionSeq = SelectionSequence("SwimmingMicroDST",
+                                     TopSelection = inputData)
+    dstWriter = MicroDSTWriter('MicroDST',
+                               StreamConf           = streamConf,
+                               MicroDSTElements     = elementsConf,
+                               OutputFileSuffix     = 'Swimming',
+                               SelectionSequences   = [selectionSeq])
+    DaVinci().appendToMainSequence([dstWriter.sequence()])
+    if options.interactiveTest :
+        EventSelector().Input = ["DATAFILE='PFN:castor:/castor/cern.ch/user/r/raaij/test/SwimTrigDST.dst'"]
+else :
+    from Configurables import HltMoveVerticesForSwimming
+    from Configurables import Moore,HltConfigSvc
+    from Configurables import CondDB
+    CondDB(UseOracle = True)
+    #Global configuration
+    mykiller    = EventNodeKiller("killHlt")
+    mykiller.Nodes          = ["Hlt","Hlt1","Hlt2","Trig","Raw"]
+    deathstar               = GaudiSequencer("killHltSeq")
+    deathstar.Members       = [mykiller]
+    from Swimming import MooreSetup
+    #
+    Moore().InitialTCK = options.TCKid
+    Moore().Simulation = options.forMC
+    Moore().DataType   = options.datatype
+    Moore().DDDBtag    = options.dddb
+    Moore().CondDBtag  = options.conddb
+    Moore().outputFile = options.outfilename
+    Moore().WriteFSR = False
+    Moore().WriterRequires = []
+    # Add extra locations to writer
+    from Configurables import InputCopyStream
+    writer = InputCopyStream('Writer')
+    writer.ItemList = [offCands + '/P2TPRelations#1', options.swimRepLoc + '#1']
+    
+    if options.interactiveTest :
+        EventSelector().Input = ["DATAFILE='PFN:root://bee28.grid.sara.nl:1094/pnfs/grid.sara.nl/data/lhcb/user/r/raaij/2011_10/26549/26549151/Bs2JpsiPhiPreDet.SingleOffline.dst'"]
+    #
+    # Define the TCK transformation
+    # 
+    HltConfigSvc().ApplyTransformation = thisTransform
+    #
+    # Define the swimming algorithm
+    #
+    myswimmer                   = HltMoveVerticesForSwimming("HltMovePVs4Swimming")
+    myswimmer.SwimmingDistance  = 0.0
+    myswimmer.Bcontainer        = offCands if options.select == 'none' else swimCands
+    myswimmer.InputSelection    = options.onlinePV
+    myswimmer.OutputSelection   = options.outPVSel
+    myswimmer.OutputLevel       = 4
+
+#The general setup
+from Swimming import GeneralSetup
+from Configurables import DstConf, CaloDstUnPackConf
+CaloDstUnPackConf ( Enable = True )
+DstConf           ( EnableUnpack = True )#
+ApplicationMgr().TopAlg = [deathstar] + ApplicationMgr().TopAlg
+
+# New persistency
+if options.ROOT:
+    from GaudiConf import IOHelper
+    IOHelper("ROOT","ROOT").postConfigServices()
+
+# FileStager
+if options.filestager:
+    from FileStager.Configuration import configureFileStager
+    configureFileStager()
+
+# Disable muons in TisTosTool
+from Configurables import TriggerTisTos
+ToolSvc().addTool(TriggerTisTos,'TriggerTisTos')
+ToolSvc().TriggerTisTos.TOSFracMuon = 0.
+
+gaudi = GaudiPython.AppMgr(outputlevel = 3)
+gaudi.initialize()
+TES = gaudi.evtsvc()
+SEL = gaudi.evtSel()
+SEL.OutputLevel = 6
+SEL.firstEvent = startingEvent
+
+#Now after the initialize some more job dependent stuff
+if swimStripping :
+    dod = gaudi.service('DataOnDemandSvc')
+    outputs = gaudi.algorithm('killStripping').Nodes
+    for l in dod.AlgMap.keys():
+        if l.find('Phys') == -1:
+            continue
+        l = '/'.join(l.split('/')[:-1])
+        outputs.append(l)
+    gaudi.algorithm('killStripping').Nodes = outputs
+    gaudi.algorithm('killStrippingSeq').Enable  = False
+    gaudi.algorithm('StrippingGlobal').Enable   = False
+    gaudi.algorithm('MicroDSTMainSeq').Enable   = False
+    triggers = options.stripcands
+#Tools needed for for tistosing
+else :
+    for algo in ['killHltSeq', 'seqL0', 'Hlt',
+                 'HltSelReportsWriter', 'Writer',
+                 'HltDecReportsWriter', 'HltVertexReportsWriter',
+                 'HltLumiWriter', 'HltLumiStripper',
+                 'HltRoutingBitsWriter']:
+        gaudi.algorithm(algo).Enable = False
+    hlt1triggers = options.hlt1triggers.split(',')
+    hlt2triggers = options.hlt2triggers.split(',')
+    triggers     = [hlt1triggers,hlt2triggers]
+
+#The tis tos tool
+tistostool      = gaudi.toolsvc().create('TriggerTisTos'    ,interface='ITriggerTisTos')
+tistosbools     = [tistostool.kAnything,tistostool.kTrueRequired,tistostool.kFalseRequired]
+#The tools used for swimming the stripping/offline
+m_lifetimeTool  = gaudi.toolsvc().create(options.tauCalc     ,interface='ILifetimeFitter')
+m_distanceTool  = gaudi.toolsvc().create(options.distCalc    ,interface='IDistanceCalculator')
+m_relatedPVTool = gaudi.toolsvc().create(options.relPVFinder ,interface='IRelatedPVFinder')
+
+#Make the class of globals for passing information around
+from Swimming.Globals import globalParams
+tmpSvc = gaudi.service("IncidentSvc")
+m_incidentSvc = InterfaceCast("IIncidentSvc")(tmpSvc.getInterface())
+myGlobs = globalParams( GaudiPython,gaudi,SEL,TES,m_incidentSvc,
+                        m_lifetimeTool,m_distanceTool,m_relatedPVTool,
+                        tistostool,tistosbools,triggers, 
+                        options.hlt1recoline, options.hlt2recoline,
+                        granularityRefinement,
+                        DEBUGMODE,startingEvent,swimStripping,options.swimOffsel,
+                        options.offselmodulename,offCands,offlinePVs
+                      )
+
+# Import the utilities
+from Swimming.SwimmingUtils import * 
+from Swimming.RefineTPs import refine
+from Swimming.SwimmingTisTos import evaluateTisTos 
+
+# Set up for the ntuple writing
+import ROOT
+from ROOT import *
+from math import *
+import GaudiPython
+
+# The turning points contain the following information
+#
+# The raw position of the turning point in mm (relative to the
+# point at which the B/D was measured), the lifetime of the B/D
+# at the turning point, the IP of the B/D at the turning point,
+# and of course the trigger decision at that turning point.
+#
+# In addition we store information about individual tracks in the
+# signal, in order to deal with inclusive triggers which only require
+# a part of the signal to fire.
+#
+# The information on which triggers were TOS at which stage
+# If a logical OR of the triggers is being requested, then 
+# a new turning point is set every time that either one of the trigger
+# decisions changes. 
+#
+# The information on which tracks were TOS in
+# HLT1. To save space this is stored as an integer,
+# whose first and last digits are 9 and the digits
+# inbetween are 1 or 0 depending on whether the
+# given track was TOS in HLT1 or not. This is relevant
+# for swimming the 1Track trigger only.     
+#
+# The information on which tracks played a part in the
+# HLT2 decision. Important for swimming inclusive HLT2
+# triggers or swimming multiple triggers in the same job.
+#
+# Which tracks were Reco'd in HLT1 and HLT2 
+# again this is given in the format specified above
+#
+# Which tracks were Rec'ible in the VELO, offline (3 hits) or 
+# in HLT1 (5 hits)
+#
+# Get the candidate selector.
+selector = getSelector(options.select)(myGlobs)
+
+# Initialize at -1 so the eventNumber can be incremented at the top of the loop.
+eventNumber = -1
+while True:
+    # Increment event number
+    eventNumber += 1
+
+    # Check if we've hit the maximum
+    if (nEvents != -1 and eventNumber > nEvents):
+        print "Finished processing events"
+        break
+    elif (eventNumber % 100) == 0: 
+        print "Processing event", eventNumber
+
+    # Containers to store the turningpoints
+    roughTurningPoints = []
+    finalTurningPointsForWriting = []
+
+    gaudi.run(1)
+    if not TES["/Event/Rec/Header"] :
+            print "Reached end of file, we're done!"
+            break
+
+    odin = TES['/Event/DAQ/ODIN']
+    if not swimStripping and \
+           odin.triggerConfigurationKey() != int(options.TCKid, 16):
+        print "WARNING, TCK 0x%08x does not match configured TCK %s, skipping event." \
+              % (odin.triggerConfigurationKey(), options.TCKid)
+        continue
+    
+    #Safety checks
+    mycands = TES[offCands+"/Particles"]
+    if not mycands :
+        if DEBUGMODE :
+            print "Problem while processing event number",startingEvent+eventNumber
+            print "No container of offline candidates found!"
+            print "Skipping the event but this is bad, check what you are doing!!"   
+        continue
+    if mycands.size() == 0 : 
+        if DEBUGMODE :
+            print "Problem while processing event number",startingEvent+eventNumber
+            print "Container of offline candidates empty!" 
+            print "Skipping the event but this is bad, check what you are doing!!"
+        continue
+    if DEBUGMODE :
+        print "Passed the safety checks OK"
+        print "Candidates in event =", mycands.size()
+
+    # Select the candidate to swim
+    mycand = selector(mycands)
+    if DEBUGMODE :
+        print "Got the offline candidate OK"
+        print "About to store its information"
+        print mycand
+
+    # If we are swimming the trigger and have a non-trivial selection method,
+    # put the selected candidate in a separate location.
+    if not swimStripping and options.select != 'none':
+        swimmingParticles = createObject(SharedParticles)
+        swimmingParticles.insert(mycand)
+        TES.registerObject(swimCands + '/Particles', swimmingParticles)
+        
+    HltDecLast  = None
+    HltDec      = None
+    swimLoop    = int(-1.*maxSwimDistance + -1.*extraSwimDistance)
+    while (swimLoop <= (maxSwimDistance + extraSwimDistance)) :
+        if DEBUGMODE:
+            print "Running over event", startingEvent+eventNumber,"swimming step",swimLoop             
+        # We got this far now get the candidate and, for the "zero" step only
+        # fill the corresponding event variables for it 
+        # Note that this function call also executes the stripping algorithm
+        # having moved the primary vertices around first
+        runSwimmingStep(myGlobs,swimLoop)
+
+        # Now get the trigger decision for this swimming step
+        HltDec = evaluateTisTos(myGlobs,mycand)
+        if DEBUGMODE :
+            print "Retrieved HLT decision",HltDec,"OK for this event" 
+
+        # If this is the very first swimming step, set HltDecLast to the global
+        # HltDec at this point, otherwise get it from the previous step.
+        if swimLoop == int(-1.*maxSwimDistance + -1.*extraSwimDistance):
+            HltDecLast = HltDec
+        elif roughTurningPoints != []:
+            HltDecLast = roughTurningPoints[-1][3]
+
+        # The first and last point are a special case for the bookkeeping
+        # as we want to record the limits of our swimming and the trigger
+        # decisions at these limits 
+        if (abs(swimLoop) == int(1.*maxSwimDistance + 1.*extraSwimDistance)) or \
+           (HltDec != HltDecLast): 
+            # Get the lifetime and IP of the B/D with respect to its favourite PV
+            bParams = getBinfo(myGlobs,mycand)
+            roughTurningPoints.append([swimLoop,bParams[0],bParams[1],HltDec,HltDecLast])
+    
+        # Now the granularity varies with the position 
+        # We swim more finely close to the actual decay point
+        if ((swimLoop >= -int(maxSwimDistance)) and (swimLoop < int(maxSwimDistance))) :
+            swimLoop += int(initialGranularity)
+        else :
+            swimLoop += int(extraGranularity) 
+    # Now the refinement step
+    # We have to refine every turning point, but the first and last
+    # ones which we save don't count as they are just there to
+    # demarcate the limits of our search, so we don't use them
+    if roughTurningPoints == [] :
+        continue
+    if DEBUGMODE :
+        print "****************************"
+        print "The rough turning points are"
+        pprint(roughTurningPoints)
+        print "****************************"
+    for thisturn in roughTurningPoints:
+        # Write the first and last as is, no refinement
+        if (thisturn == roughTurningPoints[0]) or (thisturn == roughTurningPoints[-1]) :
+            finalTurningPointsForWriting.append(thisturn)
+            continue
+        if DEBUGMODE :
+            print "****************************"
+            print "About to refine TP"
+            pprint(thisturn)
+            print "****************************"
+        if ((thisturn[0] > -int(maxSwimDistance)) and (thisturn[0] <= int(maxSwimDistance))) :
+            finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,initialGranularity,numberOfRefinements)
+        else : 
+            finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,extraGranularity,numberOfRefinements)
+    if DEBUGMODE :
+        print "****************************"
+        print "The final turning points for writing are:" 
+        pprint(finalTurningPointsForWriting)
+        print "****************************" 
+
+    # Which stage are we swimming?
+    stage = None
+    if swimStripping:
+        stage = 'Stripping'
+    else:
+        stage = 'Trigger'
+
+    # Get or Create the KeyedContainer for the SwimmingReports
+    reports = TES[options.swimRepLoc]
+    if not reports:
+        reports = createObject(SwimmingReports)
+        # Put the container in the TES
+        sc = TES.registerObject(options.swimRepLoc, reports)
+        if not sc.isSuccess():
+            print "Failed to register SwimmingReports in TES"
+            break
+    # Get or create the SwimmingReport
+    report = reports(mycand.key())
+    if not report:
+        report = createObject(LHCb.SwimmingReport, mycand)
+        # Put the SwimmingReport in the container.
+        reports.insert(report)
+    elif report.hasStage(stage):
+        print "WARNING, stage %s already present, this is unsupported and will fail!"
+        
+    # Create the TurningPoint objects and put them in the report
+    for turn in finalTurningPointsForWriting:
+        d = std_map_sb()
+        for decision, value in turn[3][1].iteritems():
+            d[decision] = value
+        m = std_map_sinfo()
+        for decision, info in turn[3][2].iteritems():
+            i = std_map_ulb()
+            for k, v in info.iteritems():
+                i[k] = v
+            m[decision] = i
+        tp = LHCb.TurningPoint(turn[0], turn[1], turn[2], turn[3][0], d, m)
+        report.addTurningPoint(stage, tp)
+
+    # Create the relations table
+    relations = TES[offCands + '/P2TPRelations']
+    if not relations:
+        relations = createObject(P2TPRelation)
+        # Put the relations table in the TES
+        sc = TES.registerObject(offCands + '/P2TPRelations', relations)
+        if not sc.isSuccess():
+            print "Failed to register SwimmingReports in TES"
+            break
+
+    from Swimming.SwimmingTisTos import appendToFSP
+    particles = [mycand]
+    appendToFSP(mycand, particles)
+    for particle in particles:
+        rel = relations.relations(particle)
+        if rel.empty():
+            relations.relate(particle, report)
+        elif rel(0).to().key() != report.key():
+            print "There is a relation, but it points to another swimming report, this is very bad!!"
+            break
+
+    # If swimming the stripping write out the muDST
+    if swimStripping : 
+        myGlobs.gaudi.algorithm("MicroDSTMainSeq").execute()
+    else :
+        myGlobs.gaudi.algorithm("Writer").execute()
+
+gaudi.stop()
+gaudi.finalize()
+gaudi.exit()
diff --git a/Phys/Swimming/scripts/SubmitJobExample.py b/Phys/Swimming/scripts/SubmitJobExample.py
new file mode 100644
index 000000000..1637de233
--- /dev/null
+++ b/Phys/Swimming/scripts/SubmitJobExample.py
@@ -0,0 +1,55 @@
+import sys,os
+
+#Set the options
+thisproject = "Moore"
+thisversion = "v10r2p1"
+scriptdir = "/afs/cern.ch/user/g/gligorov/w0/cmtuser/Erasmus_v3r3/Phys/Swimming/python/Swimming"
+jobsdir = "/afs/cern.ch/user/g/gligorov/cmtuser/forgrid/ladyganga/MyJobs/SwimmingJobs/Untagged/Trigger/lfnlists_KK_WM"
+thistime = 25000
+maxevents = '1100'
+thesecands = "/Event/Strip02/SeqD2HHStep2/Phys/SelD2HHStep2"
+swimStripping = '0'
+thesehlt1trigs = "Hlt1TrackAllL0Decision"
+thesehlt2trigs = "Hlt2CharmOSTF2BodyWideMassDecision"
+if int(swimStripping) :
+    thesehlt1trigs = "StreamCharmMicroDST"
+    thesehlt2trigs = "/Event/Phys/D02hhPIDLine/Particles"
+    thisproject = "DaVinci"
+    thisversion = "v26r3p2"
+
+files = os.listdir(jobsdir)
+
+for file in files :
+    thistck = ("0x"+file.strip(".py").split('x')[1].split('_')[0]).lower()
+    readlfns = open(jobsdir+"/"+file)
+    thislfnlist = []
+    for line in readlfns :
+        if line.find("dst") > -1: 
+            lfnname = "/lhcb"+line.split("lhcb")[-1].split('dst')[0]+"dst" 
+            thislfnlist.append(LogicalFile(name=lfnname)) 
+
+    gp         = GaudiPython()
+    gp.script  = scriptdir+"/RunSwimming.py"
+    gp.args    = ["--TCK",thistck,"-n",maxevents]
+    gp.project = thisproject
+    gp.version = thisversion
+
+    j                             = Job(backend=Dirac())
+    j.application                 = gp
+    j.name                        = thisproject+"_UntaggedKKWM_"+file.strip(".py")
+    j.inputsandbox                = []
+    #
+    #Add all files in script dir
+    helperscripts = os.listdir(scriptdir)
+    for helperscript in helperscripts :
+        if helperscript.split('.')[1] == "py" and \
+           helperscript <> "RunSwimming.py" :
+            j.inputsandbox.append(scriptdir+"/"+helperscript)
+    #
+    j.inputdata                   = thislfnlist
+    j.outputsandbox               = ["*.root"]
+    j.backend.settings['CPUTime'] = thistime 
+
+    j.splitter = DiracSplitter(filesPerJob=1, ignoremissing=True, maxFiles=-1)
+    #j.submit()
+
diff --git a/Phys/Swimming/src/functions.cpp b/Phys/Swimming/src/functions.cpp
new file mode 100644
index 000000000..7e30135c0
--- /dev/null
+++ b/Phys/Swimming/src/functions.cpp
@@ -0,0 +1,66 @@
+// $Id: $
+// Include files 
+#include <cmath>
+#include <string>
+
+// from Boost
+#include "boost/integer/integer_mask.hpp"
+#include "boost/integer_traits.hpp"
+using boost::uint32_t;
+using boost::uint64_t;
+
+namespace Random {
+uint32_t mix(uint32_t state)
+{
+   // note: the constants below are _not_ arbitrary, but are picked
+   //       carefully such that the bit shuffling has a large 'avalanche' effect...
+   //       See http://bretm.home.comcast.net/~bretm/hash/
+   // 
+   // note: as a result, you might call this a quasi-random (not to be confused
+   //       with psuedo-random!) number generator, in that it generates an output
+   //       which satisfies a requirement on the uniformity of its output distribution.
+   //       (and not on the predictability of the next number in the sequence,
+   //       based on knowledge of the preceding numbers)
+   //
+   // note: another way to look at this is is as an (approximation of an) evaporating 
+   //       black hole: whatever you dump in to it, you get something uniformly 
+   //       distributed back ;-)
+   //
+   state += (state << 16); state ^= (state >> 13);
+   state += (state <<  4); state ^= (state >>  7);
+   state += (state << 10); state ^= (state >>  5);
+   state += (state <<  8); state ^= (state >> 16);
+   return state;
+}
+
+// mix some 'extra' entropy into 'state' and return result
+uint32_t mix32(uint32_t state, uint32_t extra)
+{ 
+   return mix( state + extra ); 
+}
+
+// mix some 'extra' entropy into 'state' and return result
+uint32_t mix64(uint32_t state, uint64_t extra)
+ { 
+   typedef boost::low_bits_mask_t<32>  mask_t;
+   state = mix32( state , uint32_t( extra        & mask_t::sig_bits_fast) );
+   return  mix32( state , uint32_t((extra >> 32) & mask_t::sig_bits_fast) );
+}
+
+// mix some 'extra' entropy into 'state' and return result
+uint32_t mixString(uint32_t state, const std::string& extra)
+{ 
+   // prefix name with ' ' until the size is a multiple of 4.
+   std::string s = std::string((4-extra.size()%4)%4,' ') + extra;
+   for (size_t i=0; i < s.size()/4; ++i) {
+      //FIXME: this might do something different on big endian vs. small endian machines...
+      uint32_t x = uint32_t(s[i*4  ]) 
+         | uint32_t(s[i*4+1])<< 8 
+         | uint32_t(s[i*4+2])<<16 
+         | uint32_t(s[i*4+3])<<24 ;
+      state = mix32( state , x );
+   }
+   return state;
+}
+
+}
diff --git a/PhysSys/cmt/requirements b/PhysSys/cmt/requirements
index 6eb4a9264..a8bf8bfa4 100755
--- a/PhysSys/cmt/requirements
+++ b/PhysSys/cmt/requirements
@@ -1,5 +1,5 @@
 package PhysSys
-version           v12r5
+version           v12r5g1
 
 branches doc cmt
 
@@ -38,6 +38,9 @@ use TisTosTobbing		v7r3	 Phys	 # Tomasz Skwarnicki
 #===================================================================
 use NeuroBayesTools             v1r1p1   Phys    # Ulrich Kerzel
 
+#===================================================================
+use Swimming                    v2r3     Phys    # Vava Gligorov, Roel Aaij
+
 #===================================================================
 # Temporary MC stuff.
 use DaVinciMCKernel v4r2p2 Phys
diff --git a/PhysSys/cmt/version.cmt b/PhysSys/cmt/version.cmt
index 3c450767c..20197ed2c 100644
--- a/PhysSys/cmt/version.cmt
+++ b/PhysSys/cmt/version.cmt
@@ -1 +1 @@
-v12r5
+v12r5g1
diff --git a/PhysSys/doc/release.notes b/PhysSys/doc/release.notes
index 151239e2f..9a0bcb382 100755
--- a/PhysSys/doc/release.notes
+++ b/PhysSys/doc/release.notes
@@ -4,6 +4,9 @@ Package Coordinator : Juan Palacios
 Purpose             : LHCb physics packages
 
 
+</PRE><H1><A NAME=v12r5g1>2011-11-15 Phys v12r5g1</A></H1><PRE>
+- Based on LHCb v32r4g1. Swimming patch release.
+
 </PRE><H1><A NAME=v12r5>2011-06-16 Phys v12r5 </A></H1><PRE>
 - Based on LHCb v32r4. Stripping13/14/15 compatible patches.
 
diff --git a/cmt/project.cmt b/cmt/project.cmt
index 2a3470ed7..8d2699631 100755
--- a/cmt/project.cmt
+++ b/cmt/project.cmt
@@ -1,6 +1,6 @@
 project PHYS
 
-use REC	REC_v11r5
+use REC	REC_v11r5g1
 
 container      PhysSys
 build_strategy	with_installarea
-- 
GitLab