diff --git a/lbtopktautau/2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py b/lbtopktautau/2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
new file mode 100644
index 0000000000000000000000000000000000000000..847e245ef96d6dd97e0d8f15b4016ca17a0b14a2
--- /dev/null
+++ b/lbtopktautau/2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
@@ -0,0 +1,652 @@
+
+##########################################################
+# AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py
+simulation = False
+noPID = False
+no_restrip = False
+stripping_stream = 'Semileptonic'
+stripping_line = 'B2XTauTauLeptonic_Lb2pK_Mu_ReversePIDmu_line'
+decay = '(( Lambda_b0 -> ^(D0 -> ^mu+ ^mu-) ^(Lambda(1520)0 -> ^p+ ^K-) )) ||                                     (( Lambda_b~0 -> ^(D0 -> ^mu- ^mu+) ^(Lambda(1520)~0 -> ^p~- ^K+) ))                                   '
+branches = {'mother': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'jpsi': '(( Lambda_b0 -> ^(D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> ^(D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd1': '(( Lambda_b0 -> (D0 -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> ^mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd2': '(( Lambda_b0 -> (D0 -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- ^mu+) (Lambda(1520)~0 -> p~- K+) ))', 'inter': '(( Lambda_b0 -> (D0 -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) ^(Lambda(1520)~0 -> p~- K+) ))', 'h1': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> ^p~- K+) ))', 'h2': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- ^K+) ))'}
+year = '2016'
+mcdecay = 'N/A'
+# END AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py
+# From here on, the file dv_options_generic.py will be used
+# (Stripping will be added first for the lb2pkemu line)
+###########################################################
+
+try:
+    simulation = simulation
+    noPID = noPID
+    no_restrip = no_restrip
+    stripping_stream = stripping_stream
+    stripping_line = stripping_line
+    decay = decay
+    branches = branches
+    year = year
+    mcdecay = mcdecay
+
+except NameError as error:
+    raise RuntimeError("""{error} - most likely due to incorrect usage; don't run this file directly.
+                       The variables 'simulation', 'noPID', 'stripping_line', 'decay', 'branches', 'year', 'mcdecay'  have to
+                       be specified first. Correct usage is to run 'ganga_options_generic.py'""")
+
+# don't use f-strings as not supported pre python 3.6!
+print("Simulation = {0}".format(simulation))
+print("noPID = {0}".format(noPID))
+print("no_restrip = {0}".format(no_restrip))
+print("year = {0}".format(year))
+print("mcdecay descriptor = {0}".format(mcdecay))
+print("stripping stream = {0}".format(stripping_stream))
+print("stripping line = {0}".format(stripping_line))
+print("decay = {0}".format(decay))
+print("branches = {0}".format(branches))
+
+
+from Gaudi.Configuration import *
+from LHCbKernel.Configuration import *
+from DaVinci.Configuration import *
+from DecayTreeTuple.Configuration import *
+
+from Configurables import DaVinci, DecayTreeTuple, MCDecayTreeTuple
+from Configurables import TupleToolTISTOS
+from Configurables import EventNodeKiller, ProcStatusCheck
+from Configurables import LoKi__HDRFilter
+
+from StrippingConf.Configuration import StrippingConf, StrippingStream
+from StrippingSettings.Utils import strippingConfiguration
+from StrippingArchive.Utils import buildStreams
+from StrippingArchive import strippingArchive
+
+##############################################
+
+print("\n## Determined stripping line to be: \n ===>", stripping_line)
+
+print("\n## config determined")
+print("\n===> stream = ", stripping_stream)
+print("\n===> line = ", stripping_line)
+print("\n===> decay = ", decay)
+print("\n===> branches = ", branches)
+#################################
+# ## Stream and stripping line ###
+stream = stripping_stream
+line = stripping_line
+
+###########################
+# ## Restripping process ###
+
+# In the case that we are dealing with simulation, we may need to restrip due to the fact
+# that the stripping version for the simulation is different (older) than that of the
+# stripping line
+
+# In the case that we remove the PID requirements, this changes the restripping process
+# since we edit the config file to remove these requirements
+
+if simulation == True:
+    if no_restrip == False:
+        event_node_killer = EventNodeKiller('StripKiller')
+        event_node_killer.Nodes = ['/Event/AllStreams', '/Event/Strip']
+    ####################
+        if noPID == False: # conventional restrip
+            if year == '2016':
+                strip = 'stripping28r2p2'
+            elif year == '2017':
+                strip = 'stripping29r2p3'
+            elif year == '2018':
+                strip = 'stripping34r0p3'
+        
+            streams = buildStreams(stripping=strippingConfiguration(strip),
+                                   archive=strippingArchive(strip))
+
+            custom_stream = StrippingStream('AllStreams')
+            custom_line = 'Stripping'+line
+
+            for stream in streams:
+                for sline in stream.lines:
+                    if sline.name() == custom_line:
+                        custom_stream.appendLines([sline])
+        #####################
+        else: # remove PID requirements and restrip
+            # in this case we need to edit the config to remove PID requirements
+            # different stripping versions for different years
+            if year == '2016':
+                from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+            elif year == '2017':
+                from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+            elif year == '2018':
+                from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+
+            # print the unedited config file
+            print("OLD CONFIG below")
+            print(config['CONFIG'])
+            print("OLD CONFIG above")
+
+            # edit the config
+            config1 = config['CONFIG']
+            config1['MuonPID'] = -1001
+            config1['ElectronPID'] = -1001
+            config1['UseNoPIDsHadrons'] = True
+
+            # then print the edited config file
+            print("NEW CONFIG below")
+            print(config1)
+            print("NEW CONFIG above")
+
+            lb = builder('B2XTauTauLeptonic', config1)
+            custom_stream = StrippingStream('MyStream')
+            # Now we have the stream and the line and can add the lines to the stream
+            target_line = 'Stripping' + line
+            for sline in lb.lines():
+                if sline.name() == target_line:
+                    custom_stream.appendLines([sline])
+    #######################
+        filterBadEvents = ProcStatusCheck()
+        sc = StrippingConf(Streams=[custom_stream],
+                            MaxCandidates=10000,
+                            AcceptBadEvents=False,
+                            BadEventSelection=filterBadEvents)
+    
+        ### Fill tuple with DecayTreeTuple ###
+        dtt = DecayTreeTuple('DecayTreeTuple')
+        dtt.Inputs = ['/Event/Phys/{0}/Particles'.format(line)]    
+    else: # no restrip
+        ### Fill tuple with DecayTreeTuple ###
+        dtt = DecayTreeTuple('DecayTreeTuple')
+        dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)]    
+
+else: # data rather than simulation
+    ### Fill tuple with DecayTreeTuple ###
+    dtt = DecayTreeTuple('DecayTreeTuple')
+    dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)]     
+########################################
+# ## Define decay and create branches ###
+dtt.Decay = decay
+dtt.addBranches(branches)
+
+######################
+# ## Add tupletools ###
+# # Generic tupletools ##
+dtt.ToolList = [] #reset toollist to add verbose to geometry/kinematic
+
+SubMassTool = dtt.addTupleTool('TupleToolSubMass')
+
+#
+#    will create Sum_{p=2,max) C(N,p) new entries in the nTuple called [head]_M[ij...]
+#    Particle daughters are sorted by PID at each branch of the tree (cc-independant)
+#
+#**** Substitution property
+#
+#    usage : TupleTool.Substitution += ["pi+ => K+"] TupleTool.Substitution += ["K+ => pi+"]
+#    produce alternative mass with substituted PID pi<->K (cc is assumed)
+#
+#-change only one pion (K) at once in case of several pion (K) in the decay tree (producing separate output par pion (K) )
+#
+#**** DoubleSubstitution property
+#
+#    usage : TupleTool.DoubleSubstitution += ["K+/pi- => pi+/K-"] TupleTool.DoubleSubstitution += ["K+/K-" => pi+/pi-"]
+#    change all [K+pi-]cc ([K+K-]cc) pairs to (pi+K-)cc ([pi+pi-]cc)
+#    change only one pair at once in case of several pairs in the decay tree (producing separate output per pair)
+#
+#    "/" separator is not mandatory : K+pi- syntax is allowed (just a bit slower to parse)
+
+
+GeometryTool = dtt.addTupleTool('TupleToolGeometry') #Fill geometry related information for DecayTreeTuple
+GeometryTool.Verbose=True
+# head_MINIP : minimum impact parameter on any PV
+# head_MINIPCHI2 : minimum chi2 IP on all PVs
+# head_ENDVERTEX_[X|Y|Z] : decay vertex position for composite particles
+# head_ENDVERTEX_[X|Y|Z]ERR : decay vertex position error estimate for composite particles
+# head_ENDVERTEX_CHI2 : decay vertex chi2
+# head_ENDVERTEX_NDOF : decay vertex nDoF
+# head_OWNPV_[X|Y|Z] : related primary vertex position
+# head_OWNPV_[X|Y|Z]ERR : related primary vertex position error estimate for composite particles
+# head_OWNPV_CHI2 : related primary vertex chi2
+# head_OWNPV_NDOF : related primary vertex nDoF
+# head_IP_OWNPV : impact parameter with respect to the PhysDesktop::relatedVertex() considered particle
+# head_IPCHI2_OWNPV : impact parameter chi2 with respect to the relatedVertex() considered particle
+# head_FD_OWNPV : flight distance of composite particle wrt. the relatedVertex() considered particle
+# head_FDCHI2_OWNPV : flight distance significance in units of chi2 wrt. the relatedVertex() considered particle
+# head_DIRA_OWNPV : direction angle wrt. the PhysDesktop::relatedVertex() considered particle
+
+# Verbose being true gives:
+# head_TOPPV_[X|Y|Z] : PhysDesktop::relatedVertex() of the top of decay chain position
+# head_TOPPV_[X|Y|Z]ERR : PhysDesktop::relatedVertex() of the top of decay chain position error estimate
+# head_TOPPV_CHI2 : PhysDesktop::relatedVertex() of the top of decay chain chi2
+# head_TOPPV_NDOF : PhysDesktop::relatedVertex() of the top of decay chain nDoF
+# head_IP_TOPPV : impact parameter with respect to the PhysDesktop::relatedVertex() of the top of decay chain
+# head_IPCHI2_TOPPV : impact parameter chi2 with respect to the relatedVertex() of the top of decay chain
+# head_FD_TOPPV : flight distance of composite particle wrt. the relatedVertex() of the top of decay chain
+# head_FDCHI2_TOPPV : flight distance significance in units of chi2 wrt. the PhysDesktop::relatedVertex() of the top of decay chain
+# head_DIRA_TOPPV : direction angle wrt. the relatedVertex() of the top of decay chain
+# head_ORIVX_[X|Y|Z] : ancestor's related primary vertex position (when applicable)
+# head_ORIVX_[X|Y|Z]ERR : ancestor's related primary vertex position error estimate (when applicable)
+# head_ORIVX_CHI2 : ancestor's related primary vertex chi2 (when applicable)
+# head_ORIVX_NDOF : ancestor's related primary vertex nDoF (when applicable)
+# head_IP_ORIVX : impact parameter with respect to the ancestor's vertex (when applicable)
+# head_IPCHI2_ORIVX : impact parameter chi2 with respect to the ancestor's vertex (when applicable)
+# head_FD_ORIVX : flight distance of composite particle wrt. the ancestor's vertex (when applicable)
+# head_FDCHI2_ORIVX : flight distance significance in units of chi2 wrt. ancestor's vertex (when applicable)
+# head_DIRA_ORIVX : direction angle wrt. ancestor's vertex (when applicable)
+
+KinematicTool = dtt.addTupleTool('TupleToolKinematic') #Fill kinematic information for DecayTreeTuple
+KinematicTool.Verbose=True
+# head_P : momentum's amplitude
+# head_PT : transverse momentum
+# head_P[E|X|Y|Z] : four vector momentum
+# head_MM : measured mass (or assigned mass in case of 'basic' particle
+# head_M : mass calculated from momentum four-vector
+# head_MMERR : error on the measured mass (only for non-basic parts)
+
+# Verbose being true gives:
+# head_REFP[X|Y|Z]: one point the particle momentum extrapolation goes through
+# head_PreFitMass: Mass of 4-vectors of daughters, not yet extrapolated to the head decay vertex (only for composites). 
+#       This is the quantity used in ADAMASS or AM in CombineParticles.CombinationCut
+# prefix_AtVtx_P[X|Y|Z]: momentum information of basic particles at origin vertex position
+
+TrackInfoTool = dtt.addTupleTool('TupleToolTrackInfo') #Fill track information for DecayTreeTuple
+TrackInfoTool.Verbose=True
+# X_TRACK_CHI2NDOF : track chi2/ndof
+# X_TRACK_TYPE : track type
+# X_TRACK_PCHI2 : track Chi2 probability
+# X_TRACK_GhostProb : Ghost probability (run NeuralNetTmva to fill it)
+# X_TRACK_CloneDist : Only available for 2009 data
+
+# Verbose being true gives:
+# X_TRACK_CHI2 : track chi2
+# X_TRACK_NDOF : track ndof
+# X_TRACK_VeloCHI2NDOF : Track fit velo chi2/nDoF
+# X_TRACK_TCHI2NDOF : Track fit T chi2/nDoF
+# X_TRACK_VELO_UTID : hopefully unique double constructed from multiplying all Velo hit IDs
+# X_TRACK_TT_UTID : hopefully unique double constructed from multiplying all TT hit IDs
+# X_TRACK_IT_UTID : hopefully unique double constructed from multiplying all IT hit IDs
+# X_TRACK_OT_UTID : hopefully unique double constructed from multiplying all OT hit IDs
+# X_TRACK_VP_UTID : hopefully unique double constructed from multiplying all VP hit IDs
+# X_TRACK_UT_UTID : hopefully unique double constructed from multiplying all UT hit IDs
+# X_TRACK_FT_UTID : hopefully unique double constructed from multiplying all FT hit IDs
+# X_TRACK_nVeloHits : Number of Velo hits on the track
+# X_TRACK_nVeloRHits : Number of Velo R hits on the track
+# X_TRACK_nVeloPhiHits : Number of Velo phi hits on the track
+# X_TRACK_nVeloPileUpHits : Number of Velo pile-up hits on the track
+# X_TRACK_nTTHits : Number of TT hits on the track
+# X_TRACK_nITHits : Number of IT hits on the track
+# X_TRACK_nOTHits : Number of OT hits on the track
+# X_TRACK_nVPHits : Number of VP hits on the track
+# X_TRACK_nUTHits : Number of UT hits on the track
+# X_TRACK_nFTHits : Number of FT hits on the track
+# X_TRACK_FirstMeasurementX: x position of state at 'FirstMeasurement'
+# X_TRACK_FirstMeasurementY: y position of state at 'FirstMeasurement'
+# X_TRACK_FirstMeasurementZ: z position of state at 'FirstMeasurement'
+# X_TRACK_History: Algorithm which the track was made with
+# X_TRACK_qOverp : q/p of state at 'FirstMeasurement'
+# X_TRACK_Tx : x slope of state at 'FirstMeasurement'
+# X_TRACK_Ty : y slope of state at 'FirstMeasurement'
+
+EventInfoTool = dtt.addTupleTool('TupleToolEventInfo') #Event and Run number for DecayTreeTuple
+EventInfoTool.Verbose=True
+# runNumber: well, the run number
+# eventNumber:
+# BCID and BC type
+# Odin and Hlt TCKs
+# GPS time
+# If the property Mu is given it will fill the Mu of the run. A working dictionary can be 
+#       found at https://twiki.cern.ch/twiki/bin/view/LHCb/NuMuPileUp
+
+# if Verbose is on, also gps time in year,month,day,hour,min,second Note that months are 
+#       numbered [0-11]. That's a convention. Sorry.
+
+PropertimeTool = dtt.addTupleTool('TupleToolPropertime') #Fills the propertime for DecayTreeTuple
+# PropertimeTool.Verbose=True   
+# head_TAU
+# head_TAUERR
+# head_TAUCHI2
+
+RecoStatsTool = dtt.addTupleTool('TupleToolRecoStats') #Fills Reco stats, from RecSummary. 
+# RecoStatsTool.Verbose=True
+
+PidTool = dtt.addTupleTool('TupleToolPid') #DLL and PID information to be stored in a Tuple 
+# PidTool.Verbose=True
+# head_ID : particleID().pid();
+# For the long lived particles (isBasicParticle()).
+# head_PIDe : LHCb::ProtoParticle::CombDLLe
+# head_PIDmu : LHCb::ProtoParticle::CombDLLmu
+# head_PIDK : LHCb::ProtoParticle::CombDLLk
+# head_PIDp : LHCb::ProtoParticle::CombDLLp
+
+ANNPIDTool = dtt.addTupleTool('TupleToolANNPID') #ProbNN values for "Electron", "Muon", "Pion", "Kaon", "Proton", "Ghost"
+# ANNPIDTool.Verbose=True
+
+AnglesTool = dtt.addTupleTool('TupleToolAngles') #Fill MC Particle with decay angle in mother frame
+# AnglesTool.Verbose=True
+# head_CosTheta : angle in mother's frame
+# if WRTMother is false, will calculate angle in frame of top of tree
+
+PrimariesTool = dtt.addTupleTool('TupleToolPrimaries') #Primary vertices properties for DecayTreeTuple
+# PrimariesTool.Verbose=True
+# coordinates PVX, PVY, PVZ
+# errors PVXERR, PVYERR, PVZERR
+# vertex chi2 PVCHI
+# vertex ndf PVNDOF
+# Nb of tracks used to do the vertex PVNTRACKS
+
+## Isolation variables ##
+
+# cone isolation #
+ConeIsoTool = dtt.addTupleTool('TupleToolConeIsolation')
+# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians
+ConeIsoTool.MinConeSize = 0.6
+ConeIsoTool.MaxConeSize = 0.6
+# ConeIsoTool.SizeStep = 0.2
+# Fill asymmetry, delta, and component variables
+# ConeIsoTool.FillAsymmetry = True
+# ConeIsoTool.FillDeltas = True
+# ConeIsoTool.FillComponents = True
+
+
+# head_cc: charged cone
+# head_nc: neutral cone
+
+# head_XX_mult : number of objects inside the cone
+# head_XX_sPT : scalar-summed pT of the objects inside the cone
+# head_XX_vPT : vector-summed pT of the objects inside the cone
+# head_XX_P : x, y and z components of the cone momentum
+# head_XX_asy_P : momentum asymmetry between the head and the cone defined as (head_P - head_XX_P) / (head_P + head_XX_P)
+# head_XX_asy_P : x, y, z and transverse components of the momentum asymmetry
+# head_XX_deltaEta : difference in eta between the head and the cone
+# head_XX_deltaPhi : difference in phi between the head and the cone
+# head_XX_IT : transverse isolation of the head in the cone, defined as head_PT / (head_P + head_XX_P)_T
+# head_IT : transverse isolation of the head in the charged and neutral cones, defined as head_PT / (head_P + head_cc_P + head_nc_P)_T
+# head_cc_maxPt_Q : charge of the max-pT object in the charged cone
+# head_XX_maxPt_P : x, y, z (and e) components of the max-pT object momentum in the cone
+# head_MasshPi0: invariant mass of the seed-Pi0 combinations
+# head_Pi0_DeltaR: DeltaR between the seed and the pi0 directions
+# head_Pi0_E, head_Pi0_PX, head_Pi0_PY, head_Pi0_PZ: four momentum of the pi0
+# head_Pi0_M: invariant mass of the pi0
+# head_Pi0Ph1_CL, head_Pi0Ph2_CL: confidence levels of the (photon) pi0 daughters
+
+# track isolation #
+TrackIsoTool = dtt.addTupleTool('TupleToolTrackIsolation')
+# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians
+TrackIsoTool.MinConeAngle = 0.6
+TrackIsoTool.MaxConeAngle = 0.6
+# TrackIsoTool.StepSize = 0.2
+# fill asymmetry and DeltaAngles variables
+TrackIsoTool.FillAsymmetry = True
+# TrackIsoTool.FillDeltaAngles = True
+
+# Open up a cone around head, exclude all tracks that are in the decay descriptor 
+# (i.e. that belong to the decay you are looking for), build the variables with 
+# the remaining tracks.
+
+#     head_cmult : Number of tracks inside cone.
+#     head_cp : Summed p inside cone
+#     head_cpt : Summed pt inside cone
+#     head_cpx : Summed px inside cone
+#     head_cpy : Summed py inside cone
+#     head_cpz : Summed pz inside cone
+
+# If Verbose, or other flags are set:
+
+# Asymmetry variables
+
+#     head_pasy : (head_P - head_cp)/(head_P + head_cp)
+#     head_ptasy : (head_PT - head_cpt)/(head_PT + head_cpt)
+#     head_pxasy : (head_Px - head_cpx)/(head_Px + head_cpx)
+#     head_pyasy : (head_Py - head_cpy)/(head_Py + head_cpy)
+#     head_pzasy : (head_Pz - head_cpz)/(head_Pz + head_cpz) Delta angle variables
+#     head_DeltaEta : Difference in eta between summed tracks and head
+#     head_DeltaPhi : Difference in phi between summed tracks and head
+
+
+# MinConeAngle: Set the minimal deltaR of the cone (default = 0.5), in radians
+# MaxConeAngle: Set the maximum deltaR of the cone (default = 1.0), in radians
+# StepSize: Set the step of deltaR between two iterations (default = 0.1), in radians
+# TrackType: Set the type of tracks which are considered inside the cone (default = 3)
+# FillAsymmetry: Flag to fill the asymmetry variables (default = false)
+# FillDeltaAngles: Flag to fill the delta angle variables (default = false) 
+
+# vertex isolation #
+VtxIsoTool = dtt.addTupleTool('TupleToolVtxIsoln')
+
+# head_NOPARTWITHINDCHI2WDW : no. of non-signal particles that when added to vertex give delta chi2 < specified window
+# head_NOPARTWITHINCHI2WDW : no. of non-signal particles that when added to vertex give chi2 < specified window 
+# head_SMALLESTCHI2: chi2 of smallest chi2 combination with any of the input Particles 
+# head_SMALLESTDELTACHI2: delta chi2 of smallest delta chi2 combination with any of the input Particles
+#### updates:
+# (head)_NumVtxWithinChi2WindowOneTrack: number of particles that generate a vertex within a chi2 window
+# (head)_SmallestDeltaChi2OneTrack: smallest delta chi2 when adding one track
+# (head)_SmallestDeltaChi2MassOneTrack: mass of the candidate with the smallest delta chi2
+# (head)_SmallestDeltaChi2TwoTracks: smallest delta chi2 when adding one track to the combination 
+#       that has the smallest delta chi2 when adding one track
+# (head)_SmallestDeltaChi2MassTwoTracks: mass of the candidate with the smallest delta chi2 when adding 
+#       one track to the combination that has the smallest delta chi2 when adding one track
+
+## Hybrid tupletool ##
+all_hybrid = dtt.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_All')
+all_hybrid.Variables = {
+    'ETA' : "ETA", #pseudorapidity
+    'PHI' : "PHI", #asimuthal angle
+    'MINIPCHI2' : "MIPCHI2DV(PRIMARY)",
+    #The special version of LoKi::Particles::MinImpParChi2 functor which gets all the primary 
+    #vertices from desktop.
+    'MINIP' : "MIPDV(PRIMARY)",
+    #The special version of LoKi::Particles::MinImpPar functor which gets all the primary 
+    #vertices from desktop. 
+    'IPCHI2_OWNPV' : "BPVIPCHI2()",
+    #The special "context-dependent" version of LoKi::Particles::ImpParChi2 functor which gets 
+    #the related primary vertex from IPhysDesktop tool
+    'IP_OWNPV' : "BPVIP()",
+    #The special "context-dependent" version of LoKi::Particles::ImpPar functor which gets the 
+    #related primary vertex from IPhysDesktop tool.
+    'DIRA_OWNPV' : "BPVDIRA",
+    'ghost' : "TRGHP", #simple evaluator of "ghost probability"
+    'TrackCHI2DOF' : 'TRCHI2DOF',
+    'FD_CHI2' : "BPVVDCHI2",
+    #BPV = Adaptor to "best-primary-vertex", VDCHI2 = Evaluator of the chi2 of GEOMETRY distance
+    #between the particle "endVertex" and "the vertex". 
+    'VCHI2DOF' : 'VFASPF(VCHI2/VDOF)',
+    # #Decay tree fitter functions:
+    # 'DTF_CHI2NDOF'    : "DTF_CHI2NDOF( True )",
+    # #Simple evaluator of $\chi^2$ per degree of freedom for the decay tree fit.
+    # 'DTF_VCHI2NDOF'   : "DTF_FUN ( VFASPF(VCHI2/VDOF) , True )",
+    # #VCHI2 = evaluator of the Chi2 of the vertex / VDOF = evaluator of the number of degrees 
+    # #of freedom for the vertex
+    # 'DTF_MASS_JpsiConstr' : "DTF_FUN ( M , True , 'J/psi(1S)' )" , 
+    # 'DTF_MASS' : "DTF_FUN ( M , True )" ,
+    # 'DTF_CTAU"'        : "DTF_CTAU( 0, True )",
+    # #Evaluate $c\tau$ for the dauthter particle in the decay tree.
+    # 'DTF_CTAUS'       : "DTF_CTAUSIGNIFICANCE( 0, True )"
+    # #Evaluate $ \frac{c\tau}{\sigma \left( c\tau\right) } $ for the dauthter particle 
+    # #in the decay tree.
+}
+
+lb_hybrid = dtt.mother.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_Lb')
+lb_hybrid.Variables = {
+    'DOCAjpsiinter' : "DOCA(1,2)",
+    'DOCAmotherjpsi' : "DOCA(0,1)",
+    'DOCAmotherinter' : "DOCA(0,2)",
+    'DOCAjpsiinterCHI2' : "DOCACHI2(1,2)",
+    'DOCAmotherjpsiCHI2' : "DOCACHI2(0,1)",
+    'DOCAmotherinterCHI2' : "DOCACHI2(0,2)"
+}
+jpsi_hybrid = dtt.jpsi.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_jpsi')
+jpsi_hybrid.Variables = {
+    'DOCAd1d2' : "DOCA(1,2)",
+    'DOCAjpsid1' : "DOCA(0,1)",
+    'DOCAjpsid2' : "DOCA(0,2)",
+    'DOCAd1d2CHI2' : "DOCACHI2(1,2)",
+    'DOCAjpsid1CHI2' : "DOCACHI2(0,1)",
+    'DOCAjpsid2CHI2' : "DOCACHI2(0,2)"
+}
+inter_hybrid = dtt.inter.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_inter')
+inter_hybrid.Variables = {
+    #note that the end vertex of the intermediate hadron is also the end vertex of the lb
+    'DOCAh1h2' : "DOCA(1,2)",
+    'DOCAmotherh1' : "DOCA(0,1)",
+    'DOCAmotherh2' : "DOCA(0,2)",
+    'DOCAh1h2CHI2' : "DOCACHI2(1,2)",
+    'DOCAmotherh1CHI2' : "DOCACHI2(0,1)",
+    'DOCAmotherh2CHI2' : "DOCACHI2(0,2)"
+}
+
+################
+### Triggers ###
+# Add trigger list #
+
+L0Triggers = ['L0MuonDecision','L0DiMuonDecision','L0HadronDecision']
+Hlt1Triggers = [# muon lines
+                'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision',
+                # dimuon lines
+                'Hlt1DiMuonHighMassDecision','Hlt1DiMuonLowMassDecision',
+                # MVA lines
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision',
+                'Hlt1TwoTrackMVALooseDecision','Hlt1TwoTrackMVADecision'
+                ]
+Hlt2Triggers = [# topo lines
+                'Hlt2Topo2BodyDecision','Hlt2Topo3BodyDecision','Hlt2Topo4BodyDecision',
+                'Hlt2TopoMu2BodyDecision','Hlt2TopoMu3BodyDecision','Hlt2TopoMu4BodyDecision',
+                'Hlt2TopoMuMu2BodyDecision','Hlt2TopoMuMu3BodyDecision','Hlt2TopoMuMu4BodyDecision',
+                # muon lines
+                'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision','Hlt2SingleMuonLowPTDecision',
+                'Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision',
+                # dimuon lines
+                'Hlt2DiMuonDecision','Hlt2DiMuonJPsiDecision','Hlt2DiMuonDetachedDecision',
+                'Hlt2DiMuonDetachedHeavyDecision','Hlt2DiMuonDetachedJPsiDecision',
+                'Hlt2DiMuonDetachedPsi2SDecision','Hlt2DiMuonSoftDecision'
+                ]
+# Electrons in Sel
+if '_E_' in stripping_line or '_MuE_' in stripping_line or '_EPi_' in stripping_line:
+    L0Triggers += ["L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision"]
+    Hlt1Triggers += ["Hlt1SingleElectronNoIPDecision"]
+    Hlt2Triggers += ["Hlt2TopoE2BodyDecision","Hlt2TopoE3BodyDecision","Hlt2TopoE4BodyDecision", 
+                     "Hlt2TopoEE2BodyDecision","Hlt2TopoEE3BodyDecision","Hlt2TopoEE4BodyDecision", 
+                     "Hlt2TopoMuE2BodyDecision","Hlt2TopoMuE3BodyDecision","Hlt2TopoMuE4BodyDecision"
+                     ]
+
+AllTriggers = L0Triggers + Hlt1Triggers + Hlt2Triggers
+
+MuonTriggers = [# L0
+                'L0MuonDecision',
+                # Hlt1
+                'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision',
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision',
+                # Hlt2
+                'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision',
+                'Hlt2SingleMuonLowPTDecision','Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision'
+                ]
+HadronTriggers = [# L0
+                'L0HadronDecision',
+                # Hlt1
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision'
+                ]
+ElectronTriggers = [# L0
+                     "L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision", 
+                    # Hlt1
+                    "Hlt1SingleElectronNoIPDecision","Hlt1TrackMVADecision"]
+
+# TupleToolTISTOS #
+# It saves the trigger TIS/TOS decisions for each particle for each Hlt Selection
+dtt.mother.ToolList += [ "TupleToolTISTOS" ]
+dtt.mother.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.mother.TupleToolTISTOS.Verbose = True
+dtt.mother.TupleToolTISTOS.TriggerList = AllTriggers
+dtt.d2.ToolList += [ "TupleToolTISTOS" ]
+dtt.d2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.d2.TupleToolTISTOS.Verbose = True
+dtt.d2.TupleToolTISTOS.TriggerList = HadronTriggers
+dtt.d1.ToolList += [ "TupleToolTISTOS" ]
+dtt.d1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.d1.TupleToolTISTOS.Verbose = True
+dtt.d1.TupleToolTISTOS.TriggerList = HadronTriggers
+dtt.h1.ToolList += [ "TupleToolTISTOS" ]
+dtt.h1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.h1.TupleToolTISTOS.Verbose = True
+if '_Mu_' in stripping_line or '_MuE_' in stripping_line or '_MuPi_' in stripping_line:
+    dtt.h1.TupleToolTISTOS.TriggerList = MuonTriggers
+elif '_EPi_' in stripping_line:
+    dtt.h1.TupleToolTISTOS.TriggerList = ElectronTriggers
+elif '_PiPi_' in stripping_line:
+     dtt.h1.TupleToolTISTOS.TriggerList = HadronTriggers
+# else: # TODO remove
+#     print('LOCAL:    ERROR WITH h1 TRIGGER ASSIGNMENT')
+
+dtt.h2.ToolList += [ "TupleToolTISTOS" ]
+dtt.h2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.h2.TupleToolTISTOS.Verbose = True
+if '_E_' in stripping_line or '_MuE_' in stripping_line:
+    dtt.h2.TupleToolTISTOS.TriggerList = ElectronTriggers
+elif '_EPi_' in stripping_line or '_PiPi_' in stripping_line:
+     dtt.h2.TupleToolTISTOS.TriggerList = HadronTriggers
+
+## MC truth value tupletools ##
+if simulation == True:
+    MCTruthTool = dtt.addTupleTool('TupleToolMCTruth') #Fill MC truth info if a link is present 
+    # head_TRUEID : true pid
+    MCTruthTool.ToolList = [
+        "MCTupleToolKinematic", 
+        # head_TRUEP[E|X|Y|Z] : true four vector momentum
+        # head_TRUEPT : true transverse momentum, PT
+        # head_TRUEORIGINVERTEX_[X|Y|Z] : position of the true origin vertex.
+        # head_TRUEENDVERTEX_[X|Y|Z] : position of the true end vertex (the first one)
+        # head_TRUEISSTABLE : MCAssociate has no daughters.
+        # head_TRUETAU : true propertime
+        "MCTupleToolHierarchy",
+        # head_MC_MOTHER_ID : true mc mother ID
+        # head_MC_MOTHER_KEY : true mc mother key
+        # head_MC_GD_MOTHER_ID : grand mother ID
+        # head_MC_GD_MOTHER_KEY : grand mother key
+        # head_MC_GD_GD_MOTHER_ID : grand grand mother ID
+        # head_MC_GD_GD_MOTHER_KEY : grand grand mother key
+    ]
+
+    ## Hybrid tupletool ##
+    hybrid_mc_dtt = dtt.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC')
+    hybrid_mc_dtt.Variables = {
+        'MCETA' : "MCETA", #pseudorapidity
+        'MCPHI' : "MCPHI", #asimuthal angle
+    }
+
+    MCBackgroundInfoTool = dtt.addTupleTool('TupleToolMCBackgroundInfo') #Fill the info from IBackgroundCategory. 
+    # head_BKGCAT : category
+
+    # add mcdecaytreetuple
+    
+    def Make_MCTuple(decay):
+        MCTuple = MCDecayTreeTuple("MCDecayTreeTuple")
+
+        MCTuple.Decay = decay
+        MCTuple.setDescriptorTemplate( decay )
+        MCTuple.ToolList = [
+            "MCTupleToolKinematic"
+            , "MCTupleToolHierarchy"
+            , "MCTupleToolAngles"
+            , "MCTupleToolPID"
+            , "TupleToolEventInfo"
+            , "TupleToolRecoStats"
+        ]
+        ## Hybrid tupletool ##
+        hybrid_mc_mcdtt = MCTuple.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC')
+        hybrid_mc_mcdtt.Variables = {
+            'MCETA' : "MCETA", #pseudorapidity
+            'MCPHI' : "MCPHI", #asimuthal angle
+        }
+        return MCTuple
+    
+
+    MCTuple = Make_MCTuple(mcdecay)
+
+#########################
+# ## Configure DaVinci ###
+from Configurables import GaudiSequencer
+MySequencer = GaudiSequencer('Sequence')
+if simulation == True:
+    MySequencer.Members = [event_node_killer, sc.sequence(), dtt, MCTuple]
+    # MySequencer.Members = [event_node_killer, sc.sequence(),dtt]
+else:
+    MySequencer.Members = [dtt]
+
+DaVinci().UserAlgorithms += [MySequencer]
+DaVinci().EvtMax = -1
+DaVinci().PrintFreq = 1000
diff --git a/lbtopktautau/2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py b/lbtopktautau/2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
new file mode 100644
index 0000000000000000000000000000000000000000..5cc09245ec15ed5cd864399a75181b07820090fa
--- /dev/null
+++ b/lbtopktautau/2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
@@ -0,0 +1,652 @@
+
+##########################################################
+# AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py
+simulation = False
+noPID = False
+no_restrip = False
+stripping_stream = 'Semileptonic'
+stripping_line = 'B2XTauTauLeptonic_Lb2pK_Mu_ReversePIDmu_line'
+decay = '(( Lambda_b0 -> ^(D0 -> ^mu+ ^mu-) ^(Lambda(1520)0 -> ^p+ ^K-) )) ||                                     (( Lambda_b~0 -> ^(D0 -> ^mu- ^mu+) ^(Lambda(1520)~0 -> ^p~- ^K+) ))                                   '
+branches = {'mother': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'jpsi': '(( Lambda_b0 -> ^(D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> ^(D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd1': '(( Lambda_b0 -> (D0 -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> ^mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd2': '(( Lambda_b0 -> (D0 -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- ^mu+) (Lambda(1520)~0 -> p~- K+) ))', 'inter': '(( Lambda_b0 -> (D0 -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) ^(Lambda(1520)~0 -> p~- K+) ))', 'h1': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> ^p~- K+) ))', 'h2': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- ^K+) ))'}
+year = '2017'
+mcdecay = 'N/A'
+# END AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py
+# From here on, the file dv_options_generic.py will be used
+# (Stripping will be added first for the lb2pkemu line)
+###########################################################
+
+try:
+    simulation = simulation
+    noPID = noPID
+    no_restrip = no_restrip
+    stripping_stream = stripping_stream
+    stripping_line = stripping_line
+    decay = decay
+    branches = branches
+    year = year
+    mcdecay = mcdecay
+
+except NameError as error:
+    raise RuntimeError("""{error} - most likely due to incorrect usage; don't run this file directly.
+                       The variables 'simulation', 'noPID', 'stripping_line', 'decay', 'branches', 'year', 'mcdecay'  have to
+                       be specified first. Correct usage is to run 'ganga_options_generic.py'""")
+
+# don't use f-strings as not supported pre python 3.6!
+print("Simulation = {0}".format(simulation))
+print("noPID = {0}".format(noPID))
+print("no_restrip = {0}".format(no_restrip))
+print("year = {0}".format(year))
+print("mcdecay descriptor = {0}".format(mcdecay))
+print("stripping stream = {0}".format(stripping_stream))
+print("stripping line = {0}".format(stripping_line))
+print("decay = {0}".format(decay))
+print("branches = {0}".format(branches))
+
+
+from Gaudi.Configuration import *
+from LHCbKernel.Configuration import *
+from DaVinci.Configuration import *
+from DecayTreeTuple.Configuration import *
+
+from Configurables import DaVinci, DecayTreeTuple, MCDecayTreeTuple
+from Configurables import TupleToolTISTOS
+from Configurables import EventNodeKiller, ProcStatusCheck
+from Configurables import LoKi__HDRFilter
+
+from StrippingConf.Configuration import StrippingConf, StrippingStream
+from StrippingSettings.Utils import strippingConfiguration
+from StrippingArchive.Utils import buildStreams
+from StrippingArchive import strippingArchive
+
+##############################################
+
+print("\n## Determined stripping line to be: \n ===>", stripping_line)
+
+print("\n## config determined")
+print("\n===> stream = ", stripping_stream)
+print("\n===> line = ", stripping_line)
+print("\n===> decay = ", decay)
+print("\n===> branches = ", branches)
+#################################
+# ## Stream and stripping line ###
+stream = stripping_stream
+line = stripping_line
+
+###########################
+# ## Restripping process ###
+
+# In the case that we are dealing with simulation, we may need to restrip due to the fact
+# that the stripping version for the simulation is different (older) than that of the
+# stripping line
+
+# In the case that we remove the PID requirements, this changes the restripping process
+# since we edit the config file to remove these requirements
+
+if simulation == True:
+    if no_restrip == False:
+        event_node_killer = EventNodeKiller('StripKiller')
+        event_node_killer.Nodes = ['/Event/AllStreams', '/Event/Strip']
+    ####################
+        if noPID == False: # conventional restrip
+            if year == '2016':
+                strip = 'stripping28r2p2'
+            elif year == '2017':
+                strip = 'stripping29r2p3'
+            elif year == '2018':
+                strip = 'stripping34r0p3'
+        
+            streams = buildStreams(stripping=strippingConfiguration(strip),
+                                   archive=strippingArchive(strip))
+
+            custom_stream = StrippingStream('AllStreams')
+            custom_line = 'Stripping'+line
+
+            for stream in streams:
+                for sline in stream.lines:
+                    if sline.name() == custom_line:
+                        custom_stream.appendLines([sline])
+        #####################
+        else: # remove PID requirements and restrip
+            # in this case we need to edit the config to remove PID requirements
+            # different stripping versions for different years
+            if year == '2016':
+                from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+            elif year == '2017':
+                from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+            elif year == '2018':
+                from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+
+            # print the unedited config file
+            print("OLD CONFIG below")
+            print(config['CONFIG'])
+            print("OLD CONFIG above")
+
+            # edit the config
+            config1 = config['CONFIG']
+            config1['MuonPID'] = -1001
+            config1['ElectronPID'] = -1001
+            config1['UseNoPIDsHadrons'] = True
+
+            # then print the edited config file
+            print("NEW CONFIG below")
+            print(config1)
+            print("NEW CONFIG above")
+
+            lb = builder('B2XTauTauLeptonic', config1)
+            custom_stream = StrippingStream('MyStream')
+            # Now we have the stream and the line and can add the lines to the stream
+            target_line = 'Stripping' + line
+            for sline in lb.lines():
+                if sline.name() == target_line:
+                    custom_stream.appendLines([sline])
+    #######################
+        filterBadEvents = ProcStatusCheck()
+        sc = StrippingConf(Streams=[custom_stream],
+                            MaxCandidates=10000,
+                            AcceptBadEvents=False,
+                            BadEventSelection=filterBadEvents)
+    
+        ### Fill tuple with DecayTreeTuple ###
+        dtt = DecayTreeTuple('DecayTreeTuple')
+        dtt.Inputs = ['/Event/Phys/{0}/Particles'.format(line)]    
+    else: # no restrip
+        ### Fill tuple with DecayTreeTuple ###
+        dtt = DecayTreeTuple('DecayTreeTuple')
+        dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)]    
+
+else: # data rather than simulation
+    ### Fill tuple with DecayTreeTuple ###
+    dtt = DecayTreeTuple('DecayTreeTuple')
+    dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)]     
+########################################
+# ## Define decay and create branches ###
+dtt.Decay = decay
+dtt.addBranches(branches)
+
+######################
+# ## Add tupletools ###
+# # Generic tupletools ##
+dtt.ToolList = [] #reset toollist to add verbose to geometry/kinematic
+
+SubMassTool = dtt.addTupleTool('TupleToolSubMass')
+
+#
+#    will create Sum_{p=2,max) C(N,p) new entries in the nTuple called [head]_M[ij...]
+#    Particle daughters are sorted by PID at each branch of the tree (cc-independant)
+#
+#**** Substitution property
+#
+#    usage : TupleTool.Substitution += ["pi+ => K+"] TupleTool.Substitution += ["K+ => pi+"]
+#    produce alternative mass with substituted PID pi<->K (cc is assumed)
+#
+#-change only one pion (K) at once in case of several pion (K) in the decay tree (producing separate output par pion (K) )
+#
+#**** DoubleSubstitution property
+#
+#    usage : TupleTool.DoubleSubstitution += ["K+/pi- => pi+/K-"] TupleTool.DoubleSubstitution += ["K+/K-" => pi+/pi-"]
+#    change all [K+pi-]cc ([K+K-]cc) pairs to (pi+K-)cc ([pi+pi-]cc)
+#    change only one pair at once in case of several pairs in the decay tree (producing separate output per pair)
+#
+#    "/" separator is not mandatory : K+pi- syntax is allowed (just a bit slower to parse)
+
+
+GeometryTool = dtt.addTupleTool('TupleToolGeometry') #Fill geometry related information for DecayTreeTuple
+GeometryTool.Verbose=True
+# head_MINIP : minimum impact parameter on any PV
+# head_MINIPCHI2 : minimum chi2 IP on all PVs
+# head_ENDVERTEX_[X|Y|Z] : decay vertex position for composite particles
+# head_ENDVERTEX_[X|Y|Z]ERR : decay vertex position error estimate for composite particles
+# head_ENDVERTEX_CHI2 : decay vertex chi2
+# head_ENDVERTEX_NDOF : decay vertex nDoF
+# head_OWNPV_[X|Y|Z] : related primary vertex position
+# head_OWNPV_[X|Y|Z]ERR : related primary vertex position error estimate for composite particles
+# head_OWNPV_CHI2 : related primary vertex chi2
+# head_OWNPV_NDOF : related primary vertex nDoF
+# head_IP_OWNPV : impact parameter with respect to the PhysDesktop::relatedVertex() considered particle
+# head_IPCHI2_OWNPV : impact parameter chi2 with respect to the relatedVertex() considered particle
+# head_FD_OWNPV : flight distance of composite particle wrt. the relatedVertex() considered particle
+# head_FDCHI2_OWNPV : flight distance significance in units of chi2 wrt. the relatedVertex() considered particle
+# head_DIRA_OWNPV : direction angle wrt. the PhysDesktop::relatedVertex() considered particle
+
+# Verbose being true gives:
+# head_TOPPV_[X|Y|Z] : PhysDesktop::relatedVertex() of the top of decay chain position
+# head_TOPPV_[X|Y|Z]ERR : PhysDesktop::relatedVertex() of the top of decay chain position error estimate
+# head_TOPPV_CHI2 : PhysDesktop::relatedVertex() of the top of decay chain chi2
+# head_TOPPV_NDOF : PhysDesktop::relatedVertex() of the top of decay chain nDoF
+# head_IP_TOPPV : impact parameter with respect to the PhysDesktop::relatedVertex() of the top of decay chain
+# head_IPCHI2_TOPPV : impact parameter chi2 with respect to the relatedVertex() of the top of decay chain
+# head_FD_TOPPV : flight distance of composite particle wrt. the relatedVertex() of the top of decay chain
+# head_FDCHI2_TOPPV : flight distance significance in units of chi2 wrt. the PhysDesktop::relatedVertex() of the top of decay chain
+# head_DIRA_TOPPV : direction angle wrt. the relatedVertex() of the top of decay chain
+# head_ORIVX_[X|Y|Z] : ancestor's related primary vertex position (when applicable)
+# head_ORIVX_[X|Y|Z]ERR : ancestor's related primary vertex position error estimate (when applicable)
+# head_ORIVX_CHI2 : ancestor's related primary vertex chi2 (when applicable)
+# head_ORIVX_NDOF : ancestor's related primary vertex nDoF (when applicable)
+# head_IP_ORIVX : impact parameter with respect to the ancestor's vertex (when applicable)
+# head_IPCHI2_ORIVX : impact parameter chi2 with respect to the ancestor's vertex (when applicable)
+# head_FD_ORIVX : flight distance of composite particle wrt. the ancestor's vertex (when applicable)
+# head_FDCHI2_ORIVX : flight distance significance in units of chi2 wrt. ancestor's vertex (when applicable)
+# head_DIRA_ORIVX : direction angle wrt. ancestor's vertex (when applicable)
+
+KinematicTool = dtt.addTupleTool('TupleToolKinematic') #Fill kinematic information for DecayTreeTuple
+KinematicTool.Verbose=True
+# head_P : momentum's amplitude
+# head_PT : transverse momentum
+# head_P[E|X|Y|Z] : four vector momentum
+# head_MM : measured mass (or assigned mass in case of 'basic' particle
+# head_M : mass calculated from momentum four-vector
+# head_MMERR : error on the measured mass (only for non-basic parts)
+
+# Verbose being true gives:
+# head_REFP[X|Y|Z]: one point the particle momentum extrapolation goes through
+# head_PreFitMass: Mass of 4-vectors of daughters, not yet extrapolated to the head decay vertex (only for composites). 
+#       This is the quantity used in ADAMASS or AM in CombineParticles.CombinationCut
+# prefix_AtVtx_P[X|Y|Z]: momentum information of basic particles at origin vertex position
+
+TrackInfoTool = dtt.addTupleTool('TupleToolTrackInfo') #Fill track information for DecayTreeTuple
+TrackInfoTool.Verbose=True
+# X_TRACK_CHI2NDOF : track chi2/ndof
+# X_TRACK_TYPE : track type
+# X_TRACK_PCHI2 : track Chi2 probability
+# X_TRACK_GhostProb : Ghost probability (run NeuralNetTmva to fill it)
+# X_TRACK_CloneDist : Only available for 2009 data
+
+# Verbose being true gives:
+# X_TRACK_CHI2 : track chi2
+# X_TRACK_NDOF : track ndof
+# X_TRACK_VeloCHI2NDOF : Track fit velo chi2/nDoF
+# X_TRACK_TCHI2NDOF : Track fit T chi2/nDoF
+# X_TRACK_VELO_UTID : hopefully unique double constructed from multiplying all Velo hit IDs
+# X_TRACK_TT_UTID : hopefully unique double constructed from multiplying all TT hit IDs
+# X_TRACK_IT_UTID : hopefully unique double constructed from multiplying all IT hit IDs
+# X_TRACK_OT_UTID : hopefully unique double constructed from multiplying all OT hit IDs
+# X_TRACK_VP_UTID : hopefully unique double constructed from multiplying all VP hit IDs
+# X_TRACK_UT_UTID : hopefully unique double constructed from multiplying all UT hit IDs
+# X_TRACK_FT_UTID : hopefully unique double constructed from multiplying all FT hit IDs
+# X_TRACK_nVeloHits : Number of Velo hits on the track
+# X_TRACK_nVeloRHits : Number of Velo R hits on the track
+# X_TRACK_nVeloPhiHits : Number of Velo phi hits on the track
+# X_TRACK_nVeloPileUpHits : Number of Velo pile-up hits on the track
+# X_TRACK_nTTHits : Number of TT hits on the track
+# X_TRACK_nITHits : Number of IT hits on the track
+# X_TRACK_nOTHits : Number of OT hits on the track
+# X_TRACK_nVPHits : Number of VP hits on the track
+# X_TRACK_nUTHits : Number of UT hits on the track
+# X_TRACK_nFTHits : Number of FT hits on the track
+# X_TRACK_FirstMeasurementX: x position of state at 'FirstMeasurement'
+# X_TRACK_FirstMeasurementY: y position of state at 'FirstMeasurement'
+# X_TRACK_FirstMeasurementZ: z position of state at 'FirstMeasurement'
+# X_TRACK_History: Algorithm which the track was made with
+# X_TRACK_qOverp : q/p of state at 'FirstMeasurement'
+# X_TRACK_Tx : x slope of state at 'FirstMeasurement'
+# X_TRACK_Ty : y slope of state at 'FirstMeasurement'
+
+EventInfoTool = dtt.addTupleTool('TupleToolEventInfo') #Event and Run number for DecayTreeTuple
+EventInfoTool.Verbose=True
+# runNumber: well, the run number
+# eventNumber:
+# BCID and BC type
+# Odin and Hlt TCKs
+# GPS time
+# If the property Mu is given it will fill the Mu of the run. A working dictionary can be 
+#       found at https://twiki.cern.ch/twiki/bin/view/LHCb/NuMuPileUp
+
+# if Verbose is on, also gps time in year,month,day,hour,min,second Note that months are 
+#       numbered [0-11]. That's a convention. Sorry.
+
+PropertimeTool = dtt.addTupleTool('TupleToolPropertime') #Fills the propertime for DecayTreeTuple
+# PropertimeTool.Verbose=True   
+# head_TAU
+# head_TAUERR
+# head_TAUCHI2
+
+RecoStatsTool = dtt.addTupleTool('TupleToolRecoStats') #Fills Reco stats, from RecSummary. 
+# RecoStatsTool.Verbose=True
+
+PidTool = dtt.addTupleTool('TupleToolPid') #DLL and PID information to be stored in a Tuple 
+# PidTool.Verbose=True
+# head_ID : particleID().pid();
+# For the long lived particles (isBasicParticle()).
+# head_PIDe : LHCb::ProtoParticle::CombDLLe
+# head_PIDmu : LHCb::ProtoParticle::CombDLLmu
+# head_PIDK : LHCb::ProtoParticle::CombDLLk
+# head_PIDp : LHCb::ProtoParticle::CombDLLp
+
+ANNPIDTool = dtt.addTupleTool('TupleToolANNPID') #ProbNN values for "Electron", "Muon", "Pion", "Kaon", "Proton", "Ghost"
+# ANNPIDTool.Verbose=True
+
+AnglesTool = dtt.addTupleTool('TupleToolAngles') #Fill MC Particle with decay angle in mother frame
+# AnglesTool.Verbose=True
+# head_CosTheta : angle in mother's frame
+# if WRTMother is false, will calculate angle in frame of top of tree
+
+PrimariesTool = dtt.addTupleTool('TupleToolPrimaries') #Primary vertices properties for DecayTreeTuple
+# PrimariesTool.Verbose=True
+# coordinates PVX, PVY, PVZ
+# errors PVXERR, PVYERR, PVZERR
+# vertex chi2 PVCHI
+# vertex ndf PVNDOF
+# Nb of tracks used to do the vertex PVNTRACKS
+
+## Isolation variables ##
+
+# cone isolation #
+ConeIsoTool = dtt.addTupleTool('TupleToolConeIsolation')
+# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians
+ConeIsoTool.MinConeSize = 0.6
+ConeIsoTool.MaxConeSize = 0.6
+# ConeIsoTool.SizeStep = 0.2
+# Fill asymmetry, delta, and component variables
+# ConeIsoTool.FillAsymmetry = True
+# ConeIsoTool.FillDeltas = True
+# ConeIsoTool.FillComponents = True
+
+
+# head_cc: charged cone
+# head_nc: neutral cone
+
+# head_XX_mult : number of objects inside the cone
+# head_XX_sPT : scalar-summed pT of the objects inside the cone
+# head_XX_vPT : vector-summed pT of the objects inside the cone
+# head_XX_P : x, y and z components of the cone momentum
+# head_XX_asy_P : momentum asymmetry between the head and the cone defined as (head_P - head_XX_P) / (head_P + head_XX_P)
+# head_XX_asy_P : x, y, z and transverse components of the momentum asymmetry
+# head_XX_deltaEta : difference in eta between the head and the cone
+# head_XX_deltaPhi : difference in phi between the head and the cone
+# head_XX_IT : transverse isolation of the head in the cone, defined as head_PT / (head_P + head_XX_P)_T
+# head_IT : transverse isolation of the head in the charged and neutral cones, defined as head_PT / (head_P + head_cc_P + head_nc_P)_T
+# head_cc_maxPt_Q : charge of the max-pT object in the charged cone
+# head_XX_maxPt_P : x, y, z (and e) components of the max-pT object momentum in the cone
+# head_MasshPi0: invariant mass of the seed-Pi0 combinations
+# head_Pi0_DeltaR: DeltaR between the seed and the pi0 directions
+# head_Pi0_E, head_Pi0_PX, head_Pi0_PY, head_Pi0_PZ: four momentum of the pi0
+# head_Pi0_M: invariant mass of the pi0
+# head_Pi0Ph1_CL, head_Pi0Ph2_CL: confidence levels of the (photon) pi0 daughters
+
+# track isolation #
+TrackIsoTool = dtt.addTupleTool('TupleToolTrackIsolation')
+# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians
+TrackIsoTool.MinConeAngle = 0.6
+TrackIsoTool.MaxConeAngle = 0.6
+# TrackIsoTool.StepSize = 0.2
+# fill asymmetry and DeltaAngles variables
+TrackIsoTool.FillAsymmetry = True
+# TrackIsoTool.FillDeltaAngles = True
+
+# Open up a cone around head, exclude all tracks that are in the decay descriptor 
+# (i.e. that belong to the decay you are looking for), build the variables with 
+# the remaining tracks.
+
+#     head_cmult : Number of tracks inside cone.
+#     head_cp : Summed p inside cone
+#     head_cpt : Summed pt inside cone
+#     head_cpx : Summed px inside cone
+#     head_cpy : Summed py inside cone
+#     head_cpz : Summed pz inside cone
+
+# If Verbose, or other flags are set:
+
+# Asymmetry variables
+
+#     head_pasy : (head_P - head_cp)/(head_P + head_cp)
+#     head_ptasy : (head_PT - head_cpt)/(head_PT + head_cpt)
+#     head_pxasy : (head_Px - head_cpx)/(head_Px + head_cpx)
+#     head_pyasy : (head_Py - head_cpy)/(head_Py + head_cpy)
+#     head_pzasy : (head_Pz - head_cpz)/(head_Pz + head_cpz) Delta angle variables
+#     head_DeltaEta : Difference in eta between summed tracks and head
+#     head_DeltaPhi : Difference in phi between summed tracks and head
+
+
+# MinConeAngle: Set the minimal deltaR of the cone (default = 0.5), in radians
+# MaxConeAngle: Set the maximum deltaR of the cone (default = 1.0), in radians
+# StepSize: Set the step of deltaR between two iterations (default = 0.1), in radians
+# TrackType: Set the type of tracks which are considered inside the cone (default = 3)
+# FillAsymmetry: Flag to fill the asymmetry variables (default = false)
+# FillDeltaAngles: Flag to fill the delta angle variables (default = false) 
+
+# vertex isolation #
+VtxIsoTool = dtt.addTupleTool('TupleToolVtxIsoln')
+
+# head_NOPARTWITHINDCHI2WDW : no. of non-signal particles that when added to vertex give delta chi2 < specified window
+# head_NOPARTWITHINCHI2WDW : no. of non-signal particles that when added to vertex give chi2 < specified window 
+# head_SMALLESTCHI2: chi2 of smallest chi2 combination with any of the input Particles 
+# head_SMALLESTDELTACHI2: delta chi2 of smallest delta chi2 combination with any of the input Particles
+#### updates:
+# (head)_NumVtxWithinChi2WindowOneTrack: number of particles that generate a vertex within a chi2 window
+# (head)_SmallestDeltaChi2OneTrack: smallest delta chi2 when adding one track
+# (head)_SmallestDeltaChi2MassOneTrack: mass of the candidate with the smallest delta chi2
+# (head)_SmallestDeltaChi2TwoTracks: smallest delta chi2 when adding one track to the combination 
+#       that has the smallest delta chi2 when adding one track
+# (head)_SmallestDeltaChi2MassTwoTracks: mass of the candidate with the smallest delta chi2 when adding 
+#       one track to the combination that has the smallest delta chi2 when adding one track
+
+## Hybrid tupletool ##
+all_hybrid = dtt.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_All')
+all_hybrid.Variables = {
+    'ETA' : "ETA", #pseudorapidity
+    'PHI' : "PHI", #asimuthal angle
+    'MINIPCHI2' : "MIPCHI2DV(PRIMARY)",
+    #The special version of LoKi::Particles::MinImpParChi2 functor which gets all the primary 
+    #vertices from desktop.
+    'MINIP' : "MIPDV(PRIMARY)",
+    #The special version of LoKi::Particles::MinImpPar functor which gets all the primary 
+    #vertices from desktop. 
+    'IPCHI2_OWNPV' : "BPVIPCHI2()",
+    #The special "context-dependent" version of LoKi::Particles::ImpParChi2 functor which gets 
+    #the related primary vertex from IPhysDesktop tool
+    'IP_OWNPV' : "BPVIP()",
+    #The special "context-dependent" version of LoKi::Particles::ImpPar functor which gets the 
+    #related primary vertex from IPhysDesktop tool.
+    'DIRA_OWNPV' : "BPVDIRA",
+    'ghost' : "TRGHP", #simple evaluator of "ghost probability"
+    'TrackCHI2DOF' : 'TRCHI2DOF',
+    'FD_CHI2' : "BPVVDCHI2",
+    #BPV = Adaptor to "best-primary-vertex", VDCHI2 = Evaluator of the chi2 of GEOMETRY distance
+    #between the particle "endVertex" and "the vertex". 
+    'VCHI2DOF' : 'VFASPF(VCHI2/VDOF)',
+    # #Decay tree fitter functions:
+    # 'DTF_CHI2NDOF'    : "DTF_CHI2NDOF( True )",
+    # #Simple evaluator of $\chi^2$ per degree of freedom for the decay tree fit.
+    # 'DTF_VCHI2NDOF'   : "DTF_FUN ( VFASPF(VCHI2/VDOF) , True )",
+    # #VCHI2 = evaluator of the Chi2 of the vertex / VDOF = evaluator of the number of degrees 
+    # #of freedom for the vertex
+    # 'DTF_MASS_JpsiConstr' : "DTF_FUN ( M , True , 'J/psi(1S)' )" , 
+    # 'DTF_MASS' : "DTF_FUN ( M , True )" ,
+    # 'DTF_CTAU"'        : "DTF_CTAU( 0, True )",
+    # #Evaluate $c\tau$ for the dauthter particle in the decay tree.
+    # 'DTF_CTAUS'       : "DTF_CTAUSIGNIFICANCE( 0, True )"
+    # #Evaluate $ \frac{c\tau}{\sigma \left( c\tau\right) } $ for the dauthter particle 
+    # #in the decay tree.
+}
+
+lb_hybrid = dtt.mother.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_Lb')
+lb_hybrid.Variables = {
+    'DOCAjpsiinter' : "DOCA(1,2)",
+    'DOCAmotherjpsi' : "DOCA(0,1)",
+    'DOCAmotherinter' : "DOCA(0,2)",
+    'DOCAjpsiinterCHI2' : "DOCACHI2(1,2)",
+    'DOCAmotherjpsiCHI2' : "DOCACHI2(0,1)",
+    'DOCAmotherinterCHI2' : "DOCACHI2(0,2)"
+}
+jpsi_hybrid = dtt.jpsi.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_jpsi')
+jpsi_hybrid.Variables = {
+    'DOCAd1d2' : "DOCA(1,2)",
+    'DOCAjpsid1' : "DOCA(0,1)",
+    'DOCAjpsid2' : "DOCA(0,2)",
+    'DOCAd1d2CHI2' : "DOCACHI2(1,2)",
+    'DOCAjpsid1CHI2' : "DOCACHI2(0,1)",
+    'DOCAjpsid2CHI2' : "DOCACHI2(0,2)"
+}
+inter_hybrid = dtt.inter.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_inter')
+inter_hybrid.Variables = {
+    #note that the end vertex of the intermediate hadron is also the end vertex of the lb
+    'DOCAh1h2' : "DOCA(1,2)",
+    'DOCAmotherh1' : "DOCA(0,1)",
+    'DOCAmotherh2' : "DOCA(0,2)",
+    'DOCAh1h2CHI2' : "DOCACHI2(1,2)",
+    'DOCAmotherh1CHI2' : "DOCACHI2(0,1)",
+    'DOCAmotherh2CHI2' : "DOCACHI2(0,2)"
+}
+
+################
+### Triggers ###
+# Add trigger list #
+
+L0Triggers = ['L0MuonDecision','L0DiMuonDecision','L0HadronDecision']
+Hlt1Triggers = [# muon lines
+                'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision',
+                # dimuon lines
+                'Hlt1DiMuonHighMassDecision','Hlt1DiMuonLowMassDecision',
+                # MVA lines
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision',
+                'Hlt1TwoTrackMVALooseDecision','Hlt1TwoTrackMVADecision'
+                ]
+Hlt2Triggers = [# topo lines
+                'Hlt2Topo2BodyDecision','Hlt2Topo3BodyDecision','Hlt2Topo4BodyDecision',
+                'Hlt2TopoMu2BodyDecision','Hlt2TopoMu3BodyDecision','Hlt2TopoMu4BodyDecision',
+                'Hlt2TopoMuMu2BodyDecision','Hlt2TopoMuMu3BodyDecision','Hlt2TopoMuMu4BodyDecision',
+                # muon lines
+                'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision','Hlt2SingleMuonLowPTDecision',
+                'Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision',
+                # dimuon lines
+                'Hlt2DiMuonDecision','Hlt2DiMuonJPsiDecision','Hlt2DiMuonDetachedDecision',
+                'Hlt2DiMuonDetachedHeavyDecision','Hlt2DiMuonDetachedJPsiDecision',
+                'Hlt2DiMuonDetachedPsi2SDecision','Hlt2DiMuonSoftDecision'
+                ]
+# Electrons in Sel
+if '_E_' in stripping_line or '_MuE_' in stripping_line or '_EPi_' in stripping_line:
+    L0Triggers += ["L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision"]
+    Hlt1Triggers += ["Hlt1SingleElectronNoIPDecision"]
+    Hlt2Triggers += ["Hlt2TopoE2BodyDecision","Hlt2TopoE3BodyDecision","Hlt2TopoE4BodyDecision", 
+                     "Hlt2TopoEE2BodyDecision","Hlt2TopoEE3BodyDecision","Hlt2TopoEE4BodyDecision", 
+                     "Hlt2TopoMuE2BodyDecision","Hlt2TopoMuE3BodyDecision","Hlt2TopoMuE4BodyDecision"
+                     ]
+
+AllTriggers = L0Triggers + Hlt1Triggers + Hlt2Triggers
+
+MuonTriggers = [# L0
+                'L0MuonDecision',
+                # Hlt1
+                'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision',
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision',
+                # Hlt2
+                'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision',
+                'Hlt2SingleMuonLowPTDecision','Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision'
+                ]
+HadronTriggers = [# L0
+                'L0HadronDecision',
+                # Hlt1
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision'
+                ]
+ElectronTriggers = [# L0
+                     "L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision", 
+                    # Hlt1
+                    "Hlt1SingleElectronNoIPDecision","Hlt1TrackMVADecision"]
+
+# TupleToolTISTOS #
+# It saves the trigger TIS/TOS decisions for each particle for each Hlt Selection
+dtt.mother.ToolList += [ "TupleToolTISTOS" ]
+dtt.mother.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.mother.TupleToolTISTOS.Verbose = True
+dtt.mother.TupleToolTISTOS.TriggerList = AllTriggers
+dtt.d2.ToolList += [ "TupleToolTISTOS" ]
+dtt.d2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.d2.TupleToolTISTOS.Verbose = True
+dtt.d2.TupleToolTISTOS.TriggerList = HadronTriggers
+dtt.d1.ToolList += [ "TupleToolTISTOS" ]
+dtt.d1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.d1.TupleToolTISTOS.Verbose = True
+dtt.d1.TupleToolTISTOS.TriggerList = HadronTriggers
+dtt.h1.ToolList += [ "TupleToolTISTOS" ]
+dtt.h1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.h1.TupleToolTISTOS.Verbose = True
+if '_Mu_' in stripping_line or '_MuE_' in stripping_line or '_MuPi_' in stripping_line:
+    dtt.h1.TupleToolTISTOS.TriggerList = MuonTriggers
+elif '_EPi_' in stripping_line:
+    dtt.h1.TupleToolTISTOS.TriggerList = ElectronTriggers
+elif '_PiPi_' in stripping_line:
+     dtt.h1.TupleToolTISTOS.TriggerList = HadronTriggers
+# else: # TODO remove
+#     print('LOCAL:    ERROR WITH h1 TRIGGER ASSIGNMENT')
+
+dtt.h2.ToolList += [ "TupleToolTISTOS" ]
+dtt.h2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.h2.TupleToolTISTOS.Verbose = True
+if '_E_' in stripping_line or '_MuE_' in stripping_line:
+    dtt.h2.TupleToolTISTOS.TriggerList = ElectronTriggers
+elif '_EPi_' in stripping_line or '_PiPi_' in stripping_line:
+     dtt.h2.TupleToolTISTOS.TriggerList = HadronTriggers
+
+## MC truth value tupletools ##
+if simulation == True:
+    MCTruthTool = dtt.addTupleTool('TupleToolMCTruth') #Fill MC truth info if a link is present 
+    # head_TRUEID : true pid
+    MCTruthTool.ToolList = [
+        "MCTupleToolKinematic", 
+        # head_TRUEP[E|X|Y|Z] : true four vector momentum
+        # head_TRUEPT : true transverse momentum, PT
+        # head_TRUEORIGINVERTEX_[X|Y|Z] : position of the true origin vertex.
+        # head_TRUEENDVERTEX_[X|Y|Z] : position of the true end vertex (the first one)
+        # head_TRUEISSTABLE : MCAssociate has no daughters.
+        # head_TRUETAU : true propertime
+        "MCTupleToolHierarchy",
+        # head_MC_MOTHER_ID : true mc mother ID
+        # head_MC_MOTHER_KEY : true mc mother key
+        # head_MC_GD_MOTHER_ID : grand mother ID
+        # head_MC_GD_MOTHER_KEY : grand mother key
+        # head_MC_GD_GD_MOTHER_ID : grand grand mother ID
+        # head_MC_GD_GD_MOTHER_KEY : grand grand mother key
+    ]
+
+    ## Hybrid tupletool ##
+    hybrid_mc_dtt = dtt.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC')
+    hybrid_mc_dtt.Variables = {
+        'MCETA' : "MCETA", #pseudorapidity
+        'MCPHI' : "MCPHI", #asimuthal angle
+    }
+
+    MCBackgroundInfoTool = dtt.addTupleTool('TupleToolMCBackgroundInfo') #Fill the info from IBackgroundCategory. 
+    # head_BKGCAT : category
+
+    # add mcdecaytreetuple
+    
+    def Make_MCTuple(decay):
+        MCTuple = MCDecayTreeTuple("MCDecayTreeTuple")
+
+        MCTuple.Decay = decay
+        MCTuple.setDescriptorTemplate( decay )
+        MCTuple.ToolList = [
+            "MCTupleToolKinematic"
+            , "MCTupleToolHierarchy"
+            , "MCTupleToolAngles"
+            , "MCTupleToolPID"
+            , "TupleToolEventInfo"
+            , "TupleToolRecoStats"
+        ]
+        ## Hybrid tupletool ##
+        hybrid_mc_mcdtt = MCTuple.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC')
+        hybrid_mc_mcdtt.Variables = {
+            'MCETA' : "MCETA", #pseudorapidity
+            'MCPHI' : "MCPHI", #asimuthal angle
+        }
+        return MCTuple
+    
+
+    MCTuple = Make_MCTuple(mcdecay)
+
+#########################
+# ## Configure DaVinci ###
+from Configurables import GaudiSequencer
+MySequencer = GaudiSequencer('Sequence')
+if simulation == True:
+    MySequencer.Members = [event_node_killer, sc.sequence(), dtt, MCTuple]
+    # MySequencer.Members = [event_node_killer, sc.sequence(),dtt]
+else:
+    MySequencer.Members = [dtt]
+
+DaVinci().UserAlgorithms += [MySequencer]
+DaVinci().EvtMax = -1
+DaVinci().PrintFreq = 1000
diff --git a/lbtopktautau/2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py b/lbtopktautau/2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b0c6f08fe070f6570cb427a450259e3e11de665
--- /dev/null
+++ b/lbtopktautau/2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
@@ -0,0 +1,652 @@
+
+##########################################################
+# AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py
+simulation = False
+noPID = False
+no_restrip = False
+stripping_stream = 'Semileptonic'
+stripping_line = 'B2XTauTauLeptonic_Lb2pK_Mu_ReversePIDmu_line'
+decay = '(( Lambda_b0 -> ^(D0 -> ^mu+ ^mu-) ^(Lambda(1520)0 -> ^p+ ^K-) )) ||                                     (( Lambda_b~0 -> ^(D0 -> ^mu- ^mu+) ^(Lambda(1520)~0 -> ^p~- ^K+) ))                                   '
+branches = {'mother': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'jpsi': '(( Lambda_b0 -> ^(D0 -> mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> ^(D0 -> mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd1': '(( Lambda_b0 -> (D0 -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> ^mu- mu+) (Lambda(1520)~0 -> p~- K+) ))', 'd2': '(( Lambda_b0 -> (D0 -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- ^mu+) (Lambda(1520)~0 -> p~- K+) ))', 'inter': '(( Lambda_b0 -> (D0 -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) ^(Lambda(1520)~0 -> p~- K+) ))', 'h1': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> ^p~- K+) ))', 'h2': '(( Lambda_b0 -> (D0 -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-) )) || (( Lambda_b~0 -> (D0 -> mu- mu+) (Lambda(1520)~0 -> p~- ^K+) ))'}
+year = '2018'
+mcdecay = 'N/A'
+# END AUTOMATICALLY GENERATED FILE IN ganga_options_generic.py
+# From here on, the file dv_options_generic.py will be used
+# (Stripping will be added first for the lb2pkemu line)
+###########################################################
+
+try:
+    simulation = simulation
+    noPID = noPID
+    no_restrip = no_restrip
+    stripping_stream = stripping_stream
+    stripping_line = stripping_line
+    decay = decay
+    branches = branches
+    year = year
+    mcdecay = mcdecay
+
+except NameError as error:
+    raise RuntimeError("""{error} - most likely due to incorrect usage; don't run this file directly.
+                       The variables 'simulation', 'noPID', 'stripping_line', 'decay', 'branches', 'year', 'mcdecay'  have to
+                       be specified first. Correct usage is to run 'ganga_options_generic.py'""")
+
+# don't use f-strings as not supported pre python 3.6!
+print("Simulation = {0}".format(simulation))
+print("noPID = {0}".format(noPID))
+print("no_restrip = {0}".format(no_restrip))
+print("year = {0}".format(year))
+print("mcdecay descriptor = {0}".format(mcdecay))
+print("stripping stream = {0}".format(stripping_stream))
+print("stripping line = {0}".format(stripping_line))
+print("decay = {0}".format(decay))
+print("branches = {0}".format(branches))
+
+
+from Gaudi.Configuration import *
+from LHCbKernel.Configuration import *
+from DaVinci.Configuration import *
+from DecayTreeTuple.Configuration import *
+
+from Configurables import DaVinci, DecayTreeTuple, MCDecayTreeTuple
+from Configurables import TupleToolTISTOS
+from Configurables import EventNodeKiller, ProcStatusCheck
+from Configurables import LoKi__HDRFilter
+
+from StrippingConf.Configuration import StrippingConf, StrippingStream
+from StrippingSettings.Utils import strippingConfiguration
+from StrippingArchive.Utils import buildStreams
+from StrippingArchive import strippingArchive
+
+##############################################
+
+print("\n## Determined stripping line to be: \n ===>", stripping_line)
+
+print("\n## config determined")
+print("\n===> stream = ", stripping_stream)
+print("\n===> line = ", stripping_line)
+print("\n===> decay = ", decay)
+print("\n===> branches = ", branches)
+#################################
+# ## Stream and stripping line ###
+stream = stripping_stream
+line = stripping_line
+
+###########################
+# ## Restripping process ###
+
+# In the case that we are dealing with simulation, we may need to restrip due to the fact
+# that the stripping version for the simulation is different (older) than that of the
+# stripping line
+
+# In the case that we remove the PID requirements, this changes the restripping process
+# since we edit the config file to remove these requirements
+
+if simulation == True:
+    if no_restrip == False:
+        event_node_killer = EventNodeKiller('StripKiller')
+        event_node_killer.Nodes = ['/Event/AllStreams', '/Event/Strip']
+    ####################
+        if noPID == False: # conventional restrip
+            if year == '2016':
+                strip = 'stripping28r2p2'
+            elif year == '2017':
+                strip = 'stripping29r2p3'
+            elif year == '2018':
+                strip = 'stripping34r0p3'
+        
+            streams = buildStreams(stripping=strippingConfiguration(strip),
+                                   archive=strippingArchive(strip))
+
+            custom_stream = StrippingStream('AllStreams')
+            custom_line = 'Stripping'+line
+
+            for stream in streams:
+                for sline in stream.lines:
+                    if sline.name() == custom_line:
+                        custom_stream.appendLines([sline])
+        #####################
+        else: # remove PID requirements and restrip
+            # in this case we need to edit the config to remove PID requirements
+            # different stripping versions for different years
+            if year == '2016':
+                from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping28r2p2.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+            elif year == '2017':
+                from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping29r2p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+            elif year == '2018':
+                from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import B2XTauTauLeptonicConf as builder
+                from StrippingArchive.Stripping34r0p3.StrippingRD.StrippingB2XTauTauLeptonic import default_config as config
+
+            # print the unedited config file
+            print("OLD CONFIG below")
+            print(config['CONFIG'])
+            print("OLD CONFIG above")
+
+            # edit the config
+            config1 = config['CONFIG']
+            config1['MuonPID'] = -1001
+            config1['ElectronPID'] = -1001
+            config1['UseNoPIDsHadrons'] = True
+
+            # then print the edited config file
+            print("NEW CONFIG below")
+            print(config1)
+            print("NEW CONFIG above")
+
+            lb = builder('B2XTauTauLeptonic', config1)
+            custom_stream = StrippingStream('MyStream')
+            # Now we have the stream and the line and can add the lines to the stream
+            target_line = 'Stripping' + line
+            for sline in lb.lines():
+                if sline.name() == target_line:
+                    custom_stream.appendLines([sline])
+    #######################
+        filterBadEvents = ProcStatusCheck()
+        sc = StrippingConf(Streams=[custom_stream],
+                            MaxCandidates=10000,
+                            AcceptBadEvents=False,
+                            BadEventSelection=filterBadEvents)
+    
+        ### Fill tuple with DecayTreeTuple ###
+        dtt = DecayTreeTuple('DecayTreeTuple')
+        dtt.Inputs = ['/Event/Phys/{0}/Particles'.format(line)]    
+    else: # no restrip
+        ### Fill tuple with DecayTreeTuple ###
+        dtt = DecayTreeTuple('DecayTreeTuple')
+        dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)]    
+
+else: # data rather than simulation
+    ### Fill tuple with DecayTreeTuple ###
+    dtt = DecayTreeTuple('DecayTreeTuple')
+    dtt.Inputs = ['/Event/{0}/Phys/{1}/Particles'.format(stream,line)]     
+########################################
+# ## Define decay and create branches ###
+dtt.Decay = decay
+dtt.addBranches(branches)
+
+######################
+# ## Add tupletools ###
+# # Generic tupletools ##
+dtt.ToolList = [] #reset toollist to add verbose to geometry/kinematic
+
+SubMassTool = dtt.addTupleTool('TupleToolSubMass')
+
+#
+#    will create Sum_{p=2,max) C(N,p) new entries in the nTuple called [head]_M[ij...]
+#    Particle daughters are sorted by PID at each branch of the tree (cc-independant)
+#
+#**** Substitution property
+#
+#    usage : TupleTool.Substitution += ["pi+ => K+"] TupleTool.Substitution += ["K+ => pi+"]
+#    produce alternative mass with substituted PID pi<->K (cc is assumed)
+#
+#-change only one pion (K) at once in case of several pion (K) in the decay tree (producing separate output par pion (K) )
+#
+#**** DoubleSubstitution property
+#
+#    usage : TupleTool.DoubleSubstitution += ["K+/pi- => pi+/K-"] TupleTool.DoubleSubstitution += ["K+/K-" => pi+/pi-"]
+#    change all [K+pi-]cc ([K+K-]cc) pairs to (pi+K-)cc ([pi+pi-]cc)
+#    change only one pair at once in case of several pairs in the decay tree (producing separate output per pair)
+#
+#    "/" separator is not mandatory : K+pi- syntax is allowed (just a bit slower to parse)
+
+
+GeometryTool = dtt.addTupleTool('TupleToolGeometry') #Fill geometry related information for DecayTreeTuple
+GeometryTool.Verbose=True
+# head_MINIP : minimum impact parameter on any PV
+# head_MINIPCHI2 : minimum chi2 IP on all PVs
+# head_ENDVERTEX_[X|Y|Z] : decay vertex position for composite particles
+# head_ENDVERTEX_[X|Y|Z]ERR : decay vertex position error estimate for composite particles
+# head_ENDVERTEX_CHI2 : decay vertex chi2
+# head_ENDVERTEX_NDOF : decay vertex nDoF
+# head_OWNPV_[X|Y|Z] : related primary vertex position
+# head_OWNPV_[X|Y|Z]ERR : related primary vertex position error estimate for composite particles
+# head_OWNPV_CHI2 : related primary vertex chi2
+# head_OWNPV_NDOF : related primary vertex nDoF
+# head_IP_OWNPV : impact parameter with respect to the PhysDesktop::relatedVertex() considered particle
+# head_IPCHI2_OWNPV : impact parameter chi2 with respect to the relatedVertex() considered particle
+# head_FD_OWNPV : flight distance of composite particle wrt. the relatedVertex() considered particle
+# head_FDCHI2_OWNPV : flight distance significance in units of chi2 wrt. the relatedVertex() considered particle
+# head_DIRA_OWNPV : direction angle wrt. the PhysDesktop::relatedVertex() considered particle
+
+# Verbose being true gives:
+# head_TOPPV_[X|Y|Z] : PhysDesktop::relatedVertex() of the top of decay chain position
+# head_TOPPV_[X|Y|Z]ERR : PhysDesktop::relatedVertex() of the top of decay chain position error estimate
+# head_TOPPV_CHI2 : PhysDesktop::relatedVertex() of the top of decay chain chi2
+# head_TOPPV_NDOF : PhysDesktop::relatedVertex() of the top of decay chain nDoF
+# head_IP_TOPPV : impact parameter with respect to the PhysDesktop::relatedVertex() of the top of decay chain
+# head_IPCHI2_TOPPV : impact parameter chi2 with respect to the relatedVertex() of the top of decay chain
+# head_FD_TOPPV : flight distance of composite particle wrt. the relatedVertex() of the top of decay chain
+# head_FDCHI2_TOPPV : flight distance significance in units of chi2 wrt. the PhysDesktop::relatedVertex() of the top of decay chain
+# head_DIRA_TOPPV : direction angle wrt. the relatedVertex() of the top of decay chain
+# head_ORIVX_[X|Y|Z] : ancestor's related primary vertex position (when applicable)
+# head_ORIVX_[X|Y|Z]ERR : ancestor's related primary vertex position error estimate (when applicable)
+# head_ORIVX_CHI2 : ancestor's related primary vertex chi2 (when applicable)
+# head_ORIVX_NDOF : ancestor's related primary vertex nDoF (when applicable)
+# head_IP_ORIVX : impact parameter with respect to the ancestor's vertex (when applicable)
+# head_IPCHI2_ORIVX : impact parameter chi2 with respect to the ancestor's vertex (when applicable)
+# head_FD_ORIVX : flight distance of composite particle wrt. the ancestor's vertex (when applicable)
+# head_FDCHI2_ORIVX : flight distance significance in units of chi2 wrt. ancestor's vertex (when applicable)
+# head_DIRA_ORIVX : direction angle wrt. ancestor's vertex (when applicable)
+
+KinematicTool = dtt.addTupleTool('TupleToolKinematic') #Fill kinematic information for DecayTreeTuple
+KinematicTool.Verbose=True
+# head_P : momentum's amplitude
+# head_PT : transverse momentum
+# head_P[E|X|Y|Z] : four vector momentum
+# head_MM : measured mass (or assigned mass in case of 'basic' particle
+# head_M : mass calculated from momentum four-vector
+# head_MMERR : error on the measured mass (only for non-basic parts)
+
+# Verbose being true gives:
+# head_REFP[X|Y|Z]: one point the particle momentum extrapolation goes through
+# head_PreFitMass: Mass of 4-vectors of daughters, not yet extrapolated to the head decay vertex (only for composites). 
+#       This is the quantity used in ADAMASS or AM in CombineParticles.CombinationCut
+# prefix_AtVtx_P[X|Y|Z]: momentum information of basic particles at origin vertex position
+
+TrackInfoTool = dtt.addTupleTool('TupleToolTrackInfo') #Fill track information for DecayTreeTuple
+TrackInfoTool.Verbose=True
+# X_TRACK_CHI2NDOF : track chi2/ndof
+# X_TRACK_TYPE : track type
+# X_TRACK_PCHI2 : track Chi2 probability
+# X_TRACK_GhostProb : Ghost probability (run NeuralNetTmva to fill it)
+# X_TRACK_CloneDist : Only available for 2009 data
+
+# Verbose being true gives:
+# X_TRACK_CHI2 : track chi2
+# X_TRACK_NDOF : track ndof
+# X_TRACK_VeloCHI2NDOF : Track fit velo chi2/nDoF
+# X_TRACK_TCHI2NDOF : Track fit T chi2/nDoF
+# X_TRACK_VELO_UTID : hopefully unique double constructed from multiplying all Velo hit IDs
+# X_TRACK_TT_UTID : hopefully unique double constructed from multiplying all TT hit IDs
+# X_TRACK_IT_UTID : hopefully unique double constructed from multiplying all IT hit IDs
+# X_TRACK_OT_UTID : hopefully unique double constructed from multiplying all OT hit IDs
+# X_TRACK_VP_UTID : hopefully unique double constructed from multiplying all VP hit IDs
+# X_TRACK_UT_UTID : hopefully unique double constructed from multiplying all UT hit IDs
+# X_TRACK_FT_UTID : hopefully unique double constructed from multiplying all FT hit IDs
+# X_TRACK_nVeloHits : Number of Velo hits on the track
+# X_TRACK_nVeloRHits : Number of Velo R hits on the track
+# X_TRACK_nVeloPhiHits : Number of Velo phi hits on the track
+# X_TRACK_nVeloPileUpHits : Number of Velo pile-up hits on the track
+# X_TRACK_nTTHits : Number of TT hits on the track
+# X_TRACK_nITHits : Number of IT hits on the track
+# X_TRACK_nOTHits : Number of OT hits on the track
+# X_TRACK_nVPHits : Number of VP hits on the track
+# X_TRACK_nUTHits : Number of UT hits on the track
+# X_TRACK_nFTHits : Number of FT hits on the track
+# X_TRACK_FirstMeasurementX: x position of state at 'FirstMeasurement'
+# X_TRACK_FirstMeasurementY: y position of state at 'FirstMeasurement'
+# X_TRACK_FirstMeasurementZ: z position of state at 'FirstMeasurement'
+# X_TRACK_History: Algorithm which the track was made with
+# X_TRACK_qOverp : q/p of state at 'FirstMeasurement'
+# X_TRACK_Tx : x slope of state at 'FirstMeasurement'
+# X_TRACK_Ty : y slope of state at 'FirstMeasurement'
+
+EventInfoTool = dtt.addTupleTool('TupleToolEventInfo') #Event and Run number for DecayTreeTuple
+EventInfoTool.Verbose=True
+# runNumber: well, the run number
+# eventNumber:
+# BCID and BC type
+# Odin and Hlt TCKs
+# GPS time
+# If the property Mu is given it will fill the Mu of the run. A working dictionary can be 
+#       found at https://twiki.cern.ch/twiki/bin/view/LHCb/NuMuPileUp
+
+# if Verbose is on, also gps time in year,month,day,hour,min,second Note that months are 
+#       numbered [0-11]. That's a convention. Sorry.
+
+PropertimeTool = dtt.addTupleTool('TupleToolPropertime') #Fills the propertime for DecayTreeTuple
+# PropertimeTool.Verbose=True   
+# head_TAU
+# head_TAUERR
+# head_TAUCHI2
+
+RecoStatsTool = dtt.addTupleTool('TupleToolRecoStats') #Fills Reco stats, from RecSummary. 
+# RecoStatsTool.Verbose=True
+
+PidTool = dtt.addTupleTool('TupleToolPid') #DLL and PID information to be stored in a Tuple 
+# PidTool.Verbose=True
+# head_ID : particleID().pid();
+# For the long lived particles (isBasicParticle()).
+# head_PIDe : LHCb::ProtoParticle::CombDLLe
+# head_PIDmu : LHCb::ProtoParticle::CombDLLmu
+# head_PIDK : LHCb::ProtoParticle::CombDLLk
+# head_PIDp : LHCb::ProtoParticle::CombDLLp
+
+ANNPIDTool = dtt.addTupleTool('TupleToolANNPID') #ProbNN values for "Electron", "Muon", "Pion", "Kaon", "Proton", "Ghost"
+# ANNPIDTool.Verbose=True
+
+AnglesTool = dtt.addTupleTool('TupleToolAngles') #Fill MC Particle with decay angle in mother frame
+# AnglesTool.Verbose=True
+# head_CosTheta : angle in mother's frame
+# if WRTMother is false, will calculate angle in frame of top of tree
+
+PrimariesTool = dtt.addTupleTool('TupleToolPrimaries') #Primary vertices properties for DecayTreeTuple
+# PrimariesTool.Verbose=True
+# coordinates PVX, PVY, PVZ
+# errors PVXERR, PVYERR, PVZERR
+# vertex chi2 PVCHI
+# vertex ndf PVNDOF
+# Nb of tracks used to do the vertex PVNTRACKS
+
+## Isolation variables ##
+
+# cone isolation #
+ConeIsoTool = dtt.addTupleTool('TupleToolConeIsolation')
+# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians
+ConeIsoTool.MinConeSize = 0.6
+ConeIsoTool.MaxConeSize = 0.6
+# ConeIsoTool.SizeStep = 0.2
+# Fill asymmetry, delta, and component variables
+# ConeIsoTool.FillAsymmetry = True
+# ConeIsoTool.FillDeltas = True
+# ConeIsoTool.FillComponents = True
+
+
+# head_cc: charged cone
+# head_nc: neutral cone
+
+# head_XX_mult : number of objects inside the cone
+# head_XX_sPT : scalar-summed pT of the objects inside the cone
+# head_XX_vPT : vector-summed pT of the objects inside the cone
+# head_XX_P : x, y and z components of the cone momentum
+# head_XX_asy_P : momentum asymmetry between the head and the cone defined as (head_P - head_XX_P) / (head_P + head_XX_P)
+# head_XX_asy_P : x, y, z and transverse components of the momentum asymmetry
+# head_XX_deltaEta : difference in eta between the head and the cone
+# head_XX_deltaPhi : difference in phi between the head and the cone
+# head_XX_IT : transverse isolation of the head in the cone, defined as head_PT / (head_P + head_XX_P)_T
+# head_IT : transverse isolation of the head in the charged and neutral cones, defined as head_PT / (head_P + head_cc_P + head_nc_P)_T
+# head_cc_maxPt_Q : charge of the max-pT object in the charged cone
+# head_XX_maxPt_P : x, y, z (and e) components of the max-pT object momentum in the cone
+# head_MasshPi0: invariant mass of the seed-Pi0 combinations
+# head_Pi0_DeltaR: DeltaR between the seed and the pi0 directions
+# head_Pi0_E, head_Pi0_PX, head_Pi0_PY, head_Pi0_PZ: four momentum of the pi0
+# head_Pi0_M: invariant mass of the pi0
+# head_Pi0Ph1_CL, head_Pi0Ph2_CL: confidence levels of the (photon) pi0 daughters
+
+# track isolation #
+TrackIsoTool = dtt.addTupleTool('TupleToolTrackIsolation')
+# choose cones to have a deltaR of 0.5, 0.7, 0.9 radians
+TrackIsoTool.MinConeAngle = 0.6
+TrackIsoTool.MaxConeAngle = 0.6
+# TrackIsoTool.StepSize = 0.2
+# fill asymmetry and DeltaAngles variables
+TrackIsoTool.FillAsymmetry = True
+# TrackIsoTool.FillDeltaAngles = True
+
+# Open up a cone around head, exclude all tracks that are in the decay descriptor 
+# (i.e. that belong to the decay you are looking for), build the variables with 
+# the remaining tracks.
+
+#     head_cmult : Number of tracks inside cone.
+#     head_cp : Summed p inside cone
+#     head_cpt : Summed pt inside cone
+#     head_cpx : Summed px inside cone
+#     head_cpy : Summed py inside cone
+#     head_cpz : Summed pz inside cone
+
+# If Verbose, or other flags are set:
+
+# Asymmetry variables
+
+#     head_pasy : (head_P - head_cp)/(head_P + head_cp)
+#     head_ptasy : (head_PT - head_cpt)/(head_PT + head_cpt)
+#     head_pxasy : (head_Px - head_cpx)/(head_Px + head_cpx)
+#     head_pyasy : (head_Py - head_cpy)/(head_Py + head_cpy)
+#     head_pzasy : (head_Pz - head_cpz)/(head_Pz + head_cpz) Delta angle variables
+#     head_DeltaEta : Difference in eta between summed tracks and head
+#     head_DeltaPhi : Difference in phi between summed tracks and head
+
+
+# MinConeAngle: Set the minimal deltaR of the cone (default = 0.5), in radians
+# MaxConeAngle: Set the maximum deltaR of the cone (default = 1.0), in radians
+# StepSize: Set the step of deltaR between two iterations (default = 0.1), in radians
+# TrackType: Set the type of tracks which are considered inside the cone (default = 3)
+# FillAsymmetry: Flag to fill the asymmetry variables (default = false)
+# FillDeltaAngles: Flag to fill the delta angle variables (default = false) 
+
+# vertex isolation #
+VtxIsoTool = dtt.addTupleTool('TupleToolVtxIsoln')
+
+# head_NOPARTWITHINDCHI2WDW : no. of non-signal particles that when added to vertex give delta chi2 < specified window
+# head_NOPARTWITHINCHI2WDW : no. of non-signal particles that when added to vertex give chi2 < specified window 
+# head_SMALLESTCHI2: chi2 of smallest chi2 combination with any of the input Particles 
+# head_SMALLESTDELTACHI2: delta chi2 of smallest delta chi2 combination with any of the input Particles
+#### updates:
+# (head)_NumVtxWithinChi2WindowOneTrack: number of particles that generate a vertex within a chi2 window
+# (head)_SmallestDeltaChi2OneTrack: smallest delta chi2 when adding one track
+# (head)_SmallestDeltaChi2MassOneTrack: mass of the candidate with the smallest delta chi2
+# (head)_SmallestDeltaChi2TwoTracks: smallest delta chi2 when adding one track to the combination 
+#       that has the smallest delta chi2 when adding one track
+# (head)_SmallestDeltaChi2MassTwoTracks: mass of the candidate with the smallest delta chi2 when adding 
+#       one track to the combination that has the smallest delta chi2 when adding one track
+
+## Hybrid tupletool ##
+all_hybrid = dtt.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_All')
+all_hybrid.Variables = {
+    'ETA' : "ETA", #pseudorapidity
+    'PHI' : "PHI", #asimuthal angle
+    'MINIPCHI2' : "MIPCHI2DV(PRIMARY)",
+    #The special version of LoKi::Particles::MinImpParChi2 functor which gets all the primary 
+    #vertices from desktop.
+    'MINIP' : "MIPDV(PRIMARY)",
+    #The special version of LoKi::Particles::MinImpPar functor which gets all the primary 
+    #vertices from desktop. 
+    'IPCHI2_OWNPV' : "BPVIPCHI2()",
+    #The special "context-dependent" version of LoKi::Particles::ImpParChi2 functor which gets 
+    #the related primary vertex from IPhysDesktop tool
+    'IP_OWNPV' : "BPVIP()",
+    #The special "context-dependent" version of LoKi::Particles::ImpPar functor which gets the 
+    #related primary vertex from IPhysDesktop tool.
+    'DIRA_OWNPV' : "BPVDIRA",
+    'ghost' : "TRGHP", #simple evaluator of "ghost probability"
+    'TrackCHI2DOF' : 'TRCHI2DOF',
+    'FD_CHI2' : "BPVVDCHI2",
+    #BPV = Adaptor to "best-primary-vertex", VDCHI2 = Evaluator of the chi2 of GEOMETRY distance
+    #between the particle "endVertex" and "the vertex". 
+    'VCHI2DOF' : 'VFASPF(VCHI2/VDOF)',
+    # #Decay tree fitter functions:
+    # 'DTF_CHI2NDOF'    : "DTF_CHI2NDOF( True )",
+    # #Simple evaluator of $\chi^2$ per degree of freedom for the decay tree fit.
+    # 'DTF_VCHI2NDOF'   : "DTF_FUN ( VFASPF(VCHI2/VDOF) , True )",
+    # #VCHI2 = evaluator of the Chi2 of the vertex / VDOF = evaluator of the number of degrees 
+    # #of freedom for the vertex
+    # 'DTF_MASS_JpsiConstr' : "DTF_FUN ( M , True , 'J/psi(1S)' )" , 
+    # 'DTF_MASS' : "DTF_FUN ( M , True )" ,
+    # 'DTF_CTAU"'        : "DTF_CTAU( 0, True )",
+    # #Evaluate $c\tau$ for the dauthter particle in the decay tree.
+    # 'DTF_CTAUS'       : "DTF_CTAUSIGNIFICANCE( 0, True )"
+    # #Evaluate $ \frac{c\tau}{\sigma \left( c\tau\right) } $ for the dauthter particle 
+    # #in the decay tree.
+}
+
+lb_hybrid = dtt.mother.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_Lb')
+lb_hybrid.Variables = {
+    'DOCAjpsiinter' : "DOCA(1,2)",
+    'DOCAmotherjpsi' : "DOCA(0,1)",
+    'DOCAmotherinter' : "DOCA(0,2)",
+    'DOCAjpsiinterCHI2' : "DOCACHI2(1,2)",
+    'DOCAmotherjpsiCHI2' : "DOCACHI2(0,1)",
+    'DOCAmotherinterCHI2' : "DOCACHI2(0,2)"
+}
+jpsi_hybrid = dtt.jpsi.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_jpsi')
+jpsi_hybrid.Variables = {
+    'DOCAd1d2' : "DOCA(1,2)",
+    'DOCAjpsid1' : "DOCA(0,1)",
+    'DOCAjpsid2' : "DOCA(0,2)",
+    'DOCAd1d2CHI2' : "DOCACHI2(1,2)",
+    'DOCAjpsid1CHI2' : "DOCACHI2(0,1)",
+    'DOCAjpsid2CHI2' : "DOCACHI2(0,2)"
+}
+inter_hybrid = dtt.inter.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_inter')
+inter_hybrid.Variables = {
+    #note that the end vertex of the intermediate hadron is also the end vertex of the lb
+    'DOCAh1h2' : "DOCA(1,2)",
+    'DOCAmotherh1' : "DOCA(0,1)",
+    'DOCAmotherh2' : "DOCA(0,2)",
+    'DOCAh1h2CHI2' : "DOCACHI2(1,2)",
+    'DOCAmotherh1CHI2' : "DOCACHI2(0,1)",
+    'DOCAmotherh2CHI2' : "DOCACHI2(0,2)"
+}
+
+################
+### Triggers ###
+# Add trigger list #
+
+L0Triggers = ['L0MuonDecision','L0DiMuonDecision','L0HadronDecision']
+Hlt1Triggers = [# muon lines
+                'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision',
+                # dimuon lines
+                'Hlt1DiMuonHighMassDecision','Hlt1DiMuonLowMassDecision',
+                # MVA lines
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision',
+                'Hlt1TwoTrackMVALooseDecision','Hlt1TwoTrackMVADecision'
+                ]
+Hlt2Triggers = [# topo lines
+                'Hlt2Topo2BodyDecision','Hlt2Topo3BodyDecision','Hlt2Topo4BodyDecision',
+                'Hlt2TopoMu2BodyDecision','Hlt2TopoMu3BodyDecision','Hlt2TopoMu4BodyDecision',
+                'Hlt2TopoMuMu2BodyDecision','Hlt2TopoMuMu3BodyDecision','Hlt2TopoMuMu4BodyDecision',
+                # muon lines
+                'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision','Hlt2SingleMuonLowPTDecision',
+                'Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision',
+                # dimuon lines
+                'Hlt2DiMuonDecision','Hlt2DiMuonJPsiDecision','Hlt2DiMuonDetachedDecision',
+                'Hlt2DiMuonDetachedHeavyDecision','Hlt2DiMuonDetachedJPsiDecision',
+                'Hlt2DiMuonDetachedPsi2SDecision','Hlt2DiMuonSoftDecision'
+                ]
+# Electrons in Sel
+if '_E_' in stripping_line or '_MuE_' in stripping_line or '_EPi_' in stripping_line:
+    L0Triggers += ["L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision"]
+    Hlt1Triggers += ["Hlt1SingleElectronNoIPDecision"]
+    Hlt2Triggers += ["Hlt2TopoE2BodyDecision","Hlt2TopoE3BodyDecision","Hlt2TopoE4BodyDecision", 
+                     "Hlt2TopoEE2BodyDecision","Hlt2TopoEE3BodyDecision","Hlt2TopoEE4BodyDecision", 
+                     "Hlt2TopoMuE2BodyDecision","Hlt2TopoMuE3BodyDecision","Hlt2TopoMuE4BodyDecision"
+                     ]
+
+AllTriggers = L0Triggers + Hlt1Triggers + Hlt2Triggers
+
+MuonTriggers = [# L0
+                'L0MuonDecision',
+                # Hlt1
+                'Hlt1TrackMuonDecision','Hlt1SingleMuonNoIPDecision','Hlt1SingleMuonHighPTDecision',
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision','Hlt1TrackMuonMVADecision',
+                # Hlt2
+                'Hlt2SingleMuonDecision','Hlt2SingleMuonHighPTDecision',
+                'Hlt2SingleMuonLowPTDecision','Hlt2SingleMuonRareDecision','Hlt2SingleMuonVHighPTDecision'
+                ]
+HadronTriggers = [# L0
+                'L0HadronDecision',
+                # Hlt1
+                'Hlt1TrackMVADecision','Hlt1TrackMVALooseDecision'
+                ]
+ElectronTriggers = [# L0
+                     "L0ElectronDecision","L0ElectronHiDecision","L0PhotonDecision","L0PhotonHiDecision", 
+                    # Hlt1
+                    "Hlt1SingleElectronNoIPDecision","Hlt1TrackMVADecision"]
+
+# TupleToolTISTOS #
+# It saves the trigger TIS/TOS decisions for each particle for each Hlt Selection
+dtt.mother.ToolList += [ "TupleToolTISTOS" ]
+dtt.mother.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.mother.TupleToolTISTOS.Verbose = True
+dtt.mother.TupleToolTISTOS.TriggerList = AllTriggers
+dtt.d2.ToolList += [ "TupleToolTISTOS" ]
+dtt.d2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.d2.TupleToolTISTOS.Verbose = True
+dtt.d2.TupleToolTISTOS.TriggerList = HadronTriggers
+dtt.d1.ToolList += [ "TupleToolTISTOS" ]
+dtt.d1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.d1.TupleToolTISTOS.Verbose = True
+dtt.d1.TupleToolTISTOS.TriggerList = HadronTriggers
+dtt.h1.ToolList += [ "TupleToolTISTOS" ]
+dtt.h1.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.h1.TupleToolTISTOS.Verbose = True
+if '_Mu_' in stripping_line or '_MuE_' in stripping_line or '_MuPi_' in stripping_line:
+    dtt.h1.TupleToolTISTOS.TriggerList = MuonTriggers
+elif '_EPi_' in stripping_line:
+    dtt.h1.TupleToolTISTOS.TriggerList = ElectronTriggers
+elif '_PiPi_' in stripping_line:
+     dtt.h1.TupleToolTISTOS.TriggerList = HadronTriggers
+# else: # TODO remove
+#     print('LOCAL:    ERROR WITH h1 TRIGGER ASSIGNMENT')
+
+dtt.h2.ToolList += [ "TupleToolTISTOS" ]
+dtt.h2.addTool( TupleToolTISTOS, name = "TupleToolTISTOS" )
+dtt.h2.TupleToolTISTOS.Verbose = True
+if '_E_' in stripping_line or '_MuE_' in stripping_line:
+    dtt.h2.TupleToolTISTOS.TriggerList = ElectronTriggers
+elif '_EPi_' in stripping_line or '_PiPi_' in stripping_line:
+     dtt.h2.TupleToolTISTOS.TriggerList = HadronTriggers
+
+## MC truth value tupletools ##
+if simulation == True:
+    MCTruthTool = dtt.addTupleTool('TupleToolMCTruth') #Fill MC truth info if a link is present 
+    # head_TRUEID : true pid
+    MCTruthTool.ToolList = [
+        "MCTupleToolKinematic", 
+        # head_TRUEP[E|X|Y|Z] : true four vector momentum
+        # head_TRUEPT : true transverse momentum, PT
+        # head_TRUEORIGINVERTEX_[X|Y|Z] : position of the true origin vertex.
+        # head_TRUEENDVERTEX_[X|Y|Z] : position of the true end vertex (the first one)
+        # head_TRUEISSTABLE : MCAssociate has no daughters.
+        # head_TRUETAU : true propertime
+        "MCTupleToolHierarchy",
+        # head_MC_MOTHER_ID : true mc mother ID
+        # head_MC_MOTHER_KEY : true mc mother key
+        # head_MC_GD_MOTHER_ID : grand mother ID
+        # head_MC_GD_MOTHER_KEY : grand mother key
+        # head_MC_GD_GD_MOTHER_ID : grand grand mother ID
+        # head_MC_GD_GD_MOTHER_KEY : grand grand mother key
+    ]
+
+    ## Hybrid tupletool ##
+    hybrid_mc_dtt = dtt.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC')
+    hybrid_mc_dtt.Variables = {
+        'MCETA' : "MCETA", #pseudorapidity
+        'MCPHI' : "MCPHI", #asimuthal angle
+    }
+
+    MCBackgroundInfoTool = dtt.addTupleTool('TupleToolMCBackgroundInfo') #Fill the info from IBackgroundCategory. 
+    # head_BKGCAT : category
+
+    # add mcdecaytreetuple
+    
+    def Make_MCTuple(decay):
+        MCTuple = MCDecayTreeTuple("MCDecayTreeTuple")
+
+        MCTuple.Decay = decay
+        MCTuple.setDescriptorTemplate( decay )
+        MCTuple.ToolList = [
+            "MCTupleToolKinematic"
+            , "MCTupleToolHierarchy"
+            , "MCTupleToolAngles"
+            , "MCTupleToolPID"
+            , "TupleToolEventInfo"
+            , "TupleToolRecoStats"
+        ]
+        ## Hybrid tupletool ##
+        hybrid_mc_mcdtt = MCTuple.addTupleTool('LoKi::Hybrid::MCTupleTool/LoKi_All_MC')
+        hybrid_mc_mcdtt.Variables = {
+            'MCETA' : "MCETA", #pseudorapidity
+            'MCPHI' : "MCPHI", #asimuthal angle
+        }
+        return MCTuple
+    
+
+    MCTuple = Make_MCTuple(mcdecay)
+
+#########################
+# ## Configure DaVinci ###
+from Configurables import GaudiSequencer
+MySequencer = GaudiSequencer('Sequence')
+if simulation == True:
+    MySequencer.Members = [event_node_killer, sc.sequence(), dtt, MCTuple]
+    # MySequencer.Members = [event_node_killer, sc.sequence(),dtt]
+else:
+    MySequencer.Members = [dtt]
+
+DaVinci().UserAlgorithms += [MySequencer]
+DaVinci().EvtMax = -1
+DaVinci().PrintFreq = 1000
diff --git a/lbtopktautau/info.yaml b/lbtopktautau/info.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..602080acb4bbe23128b3cd39759a35cbf1660c9e
--- /dev/null
+++ b/lbtopktautau/info.yaml
@@ -0,0 +1,43 @@
+defaults:
+  wg: RD
+  output: ntuples.root
+  inform:
+  - lmadhanm@hep.phy.cam.ac.uk
+  - joshua.james.bex@cern.ch
+  automatically_configure: 'True'
+MD_2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu:
+  application: DaVinci/v46r5
+  input:
+    bk_query: /LHCb/Collision16/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco16/Stripping28r2p2/90000000/SEMILEPTONIC.DST
+  options:
+  - 2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
+MU_2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu:
+  application: DaVinci/v46r5
+  input:
+    bk_query: /LHCb/Collision16/Beam6500GeV-VeloClosed-MagUp/Real Data/Reco16/Stripping28r2p2/90000000/SEMILEPTONIC.DST
+  options:
+  - 2016_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
+MD_2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu:
+  application: DaVinci/v46r5
+  input:
+    bk_query: /LHCb/Collision17/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco17/Stripping29r2p3/90000000/SEMILEPTONIC.DST
+  options:
+  - 2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
+MU_2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu:
+  application: DaVinci/v46r5
+  input:
+    bk_query: /LHCb/Collision17/Beam6500GeV-VeloClosed-MagUp/Real Data/Reco17/Stripping29r2p3/90000000/SEMILEPTONIC.DST
+  options:
+  - 2017_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
+MD_2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu:
+  application: DaVinci/v46r5
+  input:
+    bk_query: /LHCb/Collision18/Beam6500GeV-VeloClosed-MagDown/Real Data/Reco18/Stripping34r0p3/90000000/SEMILEPTONIC.DST
+  options:
+  - 2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py
+MU_2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu:
+  application: DaVinci/v46r5
+  input:
+    bk_query: /LHCb/Collision18/Beam6500GeV-VeloClosed-MagUp/Real Data/Reco18/Stripping34r0p3/90000000/SEMILEPTONIC.DST
+  options:
+  - 2018_LbtopKtautau_data_Lb2pK_Mu_ReversePIDmu.py