From 7969203b2b86147569e7c6b70e9ee55183c4d630 Mon Sep 17 00:00:00 2001
From: Chengdong Fu <fucd@ihep.ac.cn>
Date: Tue, 18 Aug 2020 16:30:31 +0800
Subject: [PATCH] first import from ILCSoft & merge KiTrack and KiTrackMarlin

---
 Utilities/KiTrack/CMakeLists.txt              |  21 +
 Utilities/KiTrack/Criteria/Criteria.h         | 110 ++++
 Utilities/KiTrack/Criteria/ICriterion.h       |  68 ++
 Utilities/KiTrack/ILDImpl/FTDHit01.h          |  21 +
 Utilities/KiTrack/ILDImpl/FTDHitSimple.h      |  45 ++
 .../KiTrack/ILDImpl/FTDNeighborPetalSecCon.h  |  46 ++
 .../KiTrack/ILDImpl/FTDSectorConnector.h      |  55 ++
 Utilities/KiTrack/ILDImpl/FTDTrack.h          |  71 +++
 Utilities/KiTrack/ILDImpl/IFTDHit.h           |  49 ++
 Utilities/KiTrack/ILDImpl/SectorSystemFTD.h   |  93 +++
 Utilities/KiTrack/ILDImpl/SectorSystemVXD.h   |  89 +++
 Utilities/KiTrack/ILDImpl/VXDHitSimple.h      |  44 ++
 Utilities/KiTrack/KiTrack/Automaton.h         | 215 +++++++
 Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h | 129 ++++
 Utilities/KiTrack/KiTrack/IHit.h              |  89 +++
 Utilities/KiTrack/KiTrack/ISectorConnector.h  |  40 ++
 Utilities/KiTrack/KiTrack/ISectorSystem.h     |  56 ++
 Utilities/KiTrack/KiTrack/ITrack.h            |  47 ++
 Utilities/KiTrack/KiTrack/KiTrackExceptions.h | 105 +++
 Utilities/KiTrack/KiTrack/Segment.h           |  99 +++
 Utilities/KiTrack/KiTrack/SegmentBuilder.h    |  94 +++
 Utilities/KiTrack/KiTrack/Subset.h            |  58 ++
 Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h  | 399 ++++++++++++
 Utilities/KiTrack/KiTrack/SubsetSimple.h      | 186 ++++++
 Utilities/KiTrack/Tools/FTDHelixFitter.h      |  65 ++
 Utilities/KiTrack/Tools/Fitter.h              | 129 ++++
 Utilities/KiTrack/Tools/KiTrackMarlinTools.h  |  97 +++
 .../KiTrack/src/Criteria/Crit2_DeltaPhi.cc    |  84 +++
 .../KiTrack/src/Criteria/Crit2_DeltaPhi.h     |  38 ++
 .../KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc |  78 +++
 .../KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h  |  38 ++
 .../KiTrack/src/Criteria/Crit2_DeltaRho.cc    |  81 +++
 .../KiTrack/src/Criteria/Crit2_DeltaRho.h     |  36 ++
 .../src/Criteria/Crit2_DeltaTheta_MV.cc       |  84 +++
 .../src/Criteria/Crit2_DeltaTheta_MV.h        |  38 ++
 .../KiTrack/src/Criteria/Crit2_Distance_MV.cc |  74 +++
 .../KiTrack/src/Criteria/Crit2_Distance_MV.h  |  38 ++
 .../KiTrack/src/Criteria/Crit2_HelixWithIP.cc | 125 ++++
 .../KiTrack/src/Criteria/Crit2_HelixWithIP.h  |  43 ++
 .../KiTrack/src/Criteria/Crit2_RZRatio.cc     |  82 +++
 .../KiTrack/src/Criteria/Crit2_RZRatio.h      |  35 +
 .../src/Criteria/Crit2_StraightTrackRatio.cc  |  90 +++
 .../src/Criteria/Crit2_StraightTrackRatio.h   |  41 ++
 .../KiTrack/src/Criteria/Crit3_2DAngle.cc     | 121 ++++
 .../KiTrack/src/Criteria/Crit3_2DAngle.h      |  36 ++
 .../src/Criteria/Crit3_2DAngleTimesR.cc       | 134 ++++
 .../src/Criteria/Crit3_2DAngleTimesR.h        |  36 ++
 .../KiTrack/src/Criteria/Crit3_3DAngle.cc     | 124 ++++
 .../KiTrack/src/Criteria/Crit3_3DAngle.h      |  36 ++
 .../src/Criteria/Crit3_3DAngleTimesR.cc       | 136 ++++
 .../src/Criteria/Crit3_3DAngleTimesR.h        |  36 ++
 .../src/Criteria/Crit3_ChangeRZRatio.cc       |  91 +++
 .../src/Criteria/Crit3_ChangeRZRatio.h        |  48 ++
 .../src/Criteria/Crit3_IPCircleDist.cc        |  90 +++
 .../KiTrack/src/Criteria/Crit3_IPCircleDist.h |  47 ++
 .../src/Criteria/Crit3_IPCircleDistTimesR.cc  |  90 +++
 .../src/Criteria/Crit3_IPCircleDistTimesR.h   |  40 ++
 .../KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc |  93 +++
 .../KiTrack/src/Criteria/Crit3_NoZigZag_MV.h  |  39 ++
 Utilities/KiTrack/src/Criteria/Crit3_PT.cc    |  99 +++
 Utilities/KiTrack/src/Criteria/Crit3_PT.h     |  48 ++
 Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc |  99 +++
 Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h  |  48 ++
 .../src/Criteria/Crit4_2DAngleChange.cc       | 101 +++
 .../src/Criteria/Crit4_2DAngleChange.h        |  35 +
 .../src/Criteria/Crit4_3DAngleChange.cc       | 101 +++
 .../src/Criteria/Crit4_3DAngleChange.h        |  35 +
 .../src/Criteria/Crit4_3DAngleChangeNormed.cc | 124 ++++
 .../src/Criteria/Crit4_3DAngleChangeNormed.h  |  35 +
 .../src/Criteria/Crit4_DistOfCircleCenters.cc | 110 ++++
 .../src/Criteria/Crit4_DistOfCircleCenters.h  |  35 +
 .../src/Criteria/Crit4_DistToExtrapolation.cc | 119 ++++
 .../src/Criteria/Crit4_DistToExtrapolation.h  |  37 ++
 .../KiTrack/src/Criteria/Crit4_NoZigZag.cc    | 108 ++++
 .../KiTrack/src/Criteria/Crit4_NoZigZag.h     |  39 ++
 .../src/Criteria/Crit4_PhiZRatioChange.cc     | 120 ++++
 .../src/Criteria/Crit4_PhiZRatioChange.h      |  35 +
 .../KiTrack/src/Criteria/Crit4_RChange.cc     |  97 +++
 .../KiTrack/src/Criteria/Crit4_RChange.h      |  35 +
 Utilities/KiTrack/src/Criteria/Criteria.cc    | 278 ++++++++
 .../KiTrack/src/Criteria/SimpleCircle.cc      |  90 +++
 Utilities/KiTrack/src/Criteria/SimpleCircle.h |  55 ++
 Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc#   | 132 ++++
 Utilities/KiTrack/src/ILDImpl/FTDHit01.cc     |  44 ++
 Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc |  30 +
 .../src/ILDImpl/FTDNeighborPetalSecCon.cc     |  56 ++
 .../KiTrack/src/ILDImpl/FTDSectorConnector.cc |  92 +++
 Utilities/KiTrack/src/ILDImpl/FTDTrack.cc     | 132 ++++
 Utilities/KiTrack/src/ILDImpl/IMiniVector.h   |  63 ++
 Utilities/KiTrack/src/ILDImpl/IVXDHit.h       |  53 ++
 Utilities/KiTrack/src/ILDImpl/MiniVector.cc   | 139 ++++
 Utilities/KiTrack/src/ILDImpl/MiniVector.h    |  67 ++
 .../KiTrack/src/ILDImpl/MiniVectorHit01.cc    |  59 ++
 .../KiTrack/src/ILDImpl/MiniVectorHit01.h     |  16 +
 .../KiTrack/src/ILDImpl/SectorSystemFTD.cc    | 183 ++++++
 .../KiTrack/src/ILDImpl/SectorSystemVXD.cc    | 201 ++++++
 Utilities/KiTrack/src/ILDImpl/VXDHit01.cc     |  67 ++
 Utilities/KiTrack/src/ILDImpl/VXDHit01.h      |  23 +
 Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc |  29 +
 .../KiTrack/src/ILDImpl/VXDSectorConnector.cc | 100 +++
 .../KiTrack/src/ILDImpl/VXDSectorConnector.h  |  51 ++
 Utilities/KiTrack/src/ILDImpl/VXDTrack.cc     | 201 ++++++
 Utilities/KiTrack/src/ILDImpl/VXDTrack.h      |  89 +++
 Utilities/KiTrack/src/KiTrack/Automaton.cc    | 498 +++++++++++++++
 .../KiTrack/src/KiTrack/HopfieldNeuralNet.cc  | 217 +++++++
 Utilities/KiTrack/src/KiTrack/IHit.cc         |  28 +
 Utilities/KiTrack/src/KiTrack/Segment.cc      |  67 ++
 .../KiTrack/src/KiTrack/SegmentBuilder.cc     | 117 ++++
 Utilities/KiTrack/src/Tools/FTDHelixFitter.cc | 124 ++++
 Utilities/KiTrack/src/Tools/Fitter.cc         | 598 ++++++++++++++++++
 .../src/Tools/KiTrackMarlinCEDTools.cc.bak    | 122 ++++
 .../KiTrack/src/Tools/KiTrackMarlinCEDTools.h |  31 +
 .../KiTrack/src/Tools/KiTrackMarlinTools.cc   | 262 ++++++++
 Utilities/KiTrack/src/Tools/Timer.cc          | 127 ++++
 Utilities/KiTrack/src/Tools/Timer.h           |  22 +
 .../KiTrack/src/Tools/VXDHelixFitter.cc.bak   | 190 ++++++
 Utilities/KiTrack/src/Tools/VXDHelixFitter.h  |  82 +++
 117 files changed, 10917 insertions(+)
 create mode 100644 Utilities/KiTrack/CMakeLists.txt
 create mode 100644 Utilities/KiTrack/Criteria/Criteria.h
 create mode 100644 Utilities/KiTrack/Criteria/ICriterion.h
 create mode 100644 Utilities/KiTrack/ILDImpl/FTDHit01.h
 create mode 100644 Utilities/KiTrack/ILDImpl/FTDHitSimple.h
 create mode 100644 Utilities/KiTrack/ILDImpl/FTDNeighborPetalSecCon.h
 create mode 100644 Utilities/KiTrack/ILDImpl/FTDSectorConnector.h
 create mode 100644 Utilities/KiTrack/ILDImpl/FTDTrack.h
 create mode 100644 Utilities/KiTrack/ILDImpl/IFTDHit.h
 create mode 100644 Utilities/KiTrack/ILDImpl/SectorSystemFTD.h
 create mode 100644 Utilities/KiTrack/ILDImpl/SectorSystemVXD.h
 create mode 100644 Utilities/KiTrack/ILDImpl/VXDHitSimple.h
 create mode 100644 Utilities/KiTrack/KiTrack/Automaton.h
 create mode 100644 Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h
 create mode 100644 Utilities/KiTrack/KiTrack/IHit.h
 create mode 100644 Utilities/KiTrack/KiTrack/ISectorConnector.h
 create mode 100644 Utilities/KiTrack/KiTrack/ISectorSystem.h
 create mode 100644 Utilities/KiTrack/KiTrack/ITrack.h
 create mode 100644 Utilities/KiTrack/KiTrack/KiTrackExceptions.h
 create mode 100644 Utilities/KiTrack/KiTrack/Segment.h
 create mode 100644 Utilities/KiTrack/KiTrack/SegmentBuilder.h
 create mode 100644 Utilities/KiTrack/KiTrack/Subset.h
 create mode 100644 Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h
 create mode 100644 Utilities/KiTrack/KiTrack/SubsetSimple.h
 create mode 100644 Utilities/KiTrack/Tools/FTDHelixFitter.h
 create mode 100644 Utilities/KiTrack/Tools/Fitter.h
 create mode 100644 Utilities/KiTrack/Tools/KiTrackMarlinTools.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_RZRatio.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_RZRatio.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_2DAngle.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_2DAngle.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_3DAngle.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_3DAngle.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_PT.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_PT.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_RChange.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/Crit4_RChange.h
 create mode 100644 Utilities/KiTrack/src/Criteria/Criteria.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/SimpleCircle.cc
 create mode 100644 Utilities/KiTrack/src/Criteria/SimpleCircle.h
 create mode 100644 Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc#
 create mode 100644 Utilities/KiTrack/src/ILDImpl/FTDHit01.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/FTDNeighborPetalSecCon.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/FTDSectorConnector.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/FTDTrack.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/IMiniVector.h
 create mode 100644 Utilities/KiTrack/src/ILDImpl/IVXDHit.h
 create mode 100644 Utilities/KiTrack/src/ILDImpl/MiniVector.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/MiniVector.h
 create mode 100644 Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.h
 create mode 100644 Utilities/KiTrack/src/ILDImpl/SectorSystemFTD.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/SectorSystemVXD.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/VXDHit01.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/VXDHit01.h
 create mode 100644 Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.h
 create mode 100644 Utilities/KiTrack/src/ILDImpl/VXDTrack.cc
 create mode 100644 Utilities/KiTrack/src/ILDImpl/VXDTrack.h
 create mode 100644 Utilities/KiTrack/src/KiTrack/Automaton.cc
 create mode 100644 Utilities/KiTrack/src/KiTrack/HopfieldNeuralNet.cc
 create mode 100644 Utilities/KiTrack/src/KiTrack/IHit.cc
 create mode 100644 Utilities/KiTrack/src/KiTrack/Segment.cc
 create mode 100644 Utilities/KiTrack/src/KiTrack/SegmentBuilder.cc
 create mode 100644 Utilities/KiTrack/src/Tools/FTDHelixFitter.cc
 create mode 100644 Utilities/KiTrack/src/Tools/Fitter.cc
 create mode 100644 Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.cc.bak
 create mode 100644 Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.h
 create mode 100644 Utilities/KiTrack/src/Tools/KiTrackMarlinTools.cc
 create mode 100644 Utilities/KiTrack/src/Tools/Timer.cc
 create mode 100644 Utilities/KiTrack/src/Tools/Timer.h
 create mode 100644 Utilities/KiTrack/src/Tools/VXDHelixFitter.cc.bak
 create mode 100644 Utilities/KiTrack/src/Tools/VXDHelixFitter.h

diff --git a/Utilities/KiTrack/CMakeLists.txt b/Utilities/KiTrack/CMakeLists.txt
new file mode 100644
index 00000000..ba301e6f
--- /dev/null
+++ b/Utilities/KiTrack/CMakeLists.txt
@@ -0,0 +1,21 @@
+gaudi_subdir(KiTrack v0r0)
+
+find_package(ROOT REQUIRED)
+find_package(CLHEP REQUIRED)
+#find_package(DD4hep REQUIRED)
+find_package(GSL REQUIRED)
+find_package(EDM4HEP REQUIRED)
+find_package(LCIO REQUIRED)
+
+gaudi_depends_on_subdirs(Service/TrackSystemSvc Utilities/DataHelper)
+
+set(KiTrackLib_srcs src/KiTrack/*.cc src/Criteria/*.cc src/ILDImpl/*.cc src/Tools/*.cc)
+
+#gaudi_install_headers(src)
+include_directories(src)
+
+gaudi_add_library(KiTrackLib ${KiTrackLib_srcs}
+    PUBLIC_HEADERS KiTrack 
+    LINK_LIBRARIES DataHelperLib TrackSystemSvcLib ROOT CLHEP GSL EDM4HEP::edm4hep LCIO
+    #              DD4hep
+)
diff --git a/Utilities/KiTrack/Criteria/Criteria.h b/Utilities/KiTrack/Criteria/Criteria.h
new file mode 100644
index 00000000..b0ec231b
--- /dev/null
+++ b/Utilities/KiTrack/Criteria/Criteria.h
@@ -0,0 +1,110 @@
+#ifndef Criteria_h
+#define Criteria_h
+/*
+#include "Criteria/Crit2_RZRatio.h"
+#include "Criteria/Crit2_StraightTrackRatio.h"
+#include "Criteria/Crit2_DeltaPhi.h"
+#include "Criteria/Crit2_HelixWithIP.h"
+#include "Criteria/Crit2_DeltaRho.h"
+
+#include "Criteria/Crit3_ChangeRZRatio.h"  
+#include "Criteria/Crit3_PT.h"
+#include "Criteria/Crit3_2DAngle.h"
+#include "Criteria/Crit3_2DAngleTimesR.h"
+#include "Criteria/Crit3_3DAngle.h"
+#include "Criteria/Crit3_3DAngleTimesR.h"
+#include "Criteria/Crit3_IPCircleDist.h"  
+#include "Criteria/Crit3_IPCircleDistTimesR.h"
+
+#include "Criteria/Crit4_2DAngleChange.h"    
+#include "Criteria/Crit4_3DAngleChange.h" 
+#include "Criteria/Crit4_3DAngleChangeNormed.h"
+#include "Criteria/Crit4_DistToExtrapolation.h"  
+#include "Criteria/Crit4_PhiZRatioChange.h"
+#include "Criteria/Crit4_DistOfCircleCenters.h"
+#include "Criteria/Crit4_NoZigZag.h"
+#include "Criteria/Crit4_RChange.h"
+
+// Criteria for Mini - Vector based Cellular Automaton for VXD
+#include "Criteria/Crit2_DeltaPhi_MV.h"
+#include "Criteria/Crit2_Distance_MV.h"
+#include "Criteria/Crit2_DeltaTheta_MV.h"
+#include "Criteria/Crit3_NoZigZag_MV.h"
+#include "Criteria/Crit3_PT_MV.h"
+*/
+
+#include <vector>
+#include <set>
+#include <string>
+
+namespace KiTrack{
+  class ICriterion;
+   /*
+    * Information about all Criteria.
+    * 
+    * For example bundles the includes.
+    * 
+    * Author: Robin Glattauer, HEPHY
+    */   
+   class Criteria {
+      
+      
+      
+   public:
+      
+      /** @return a vector of strings that represent all types of criteria stored.
+       * For example: "2Hit" or "3Hit" or "4Hit"
+       */
+      static std::set< std::string > getTypes();
+      
+            
+      /** @return a vector of all Criteria of a certain type
+       * 
+       * @param type the type of Criteria, that is wanted (e.g. "2Hit")
+       */
+      static std::set< std::string > getCriteriaNames( std::string type );
+      
+      /** @return the names of all Criteria in a set
+       */
+      static std::set< std::string > getAllCriteriaNames();
+      
+      /** A convenience method to get all the criteria in a vector (gives the same result as getAllCriteriaNames, but
+       * instead of a set, returns it as a vector)
+       * 
+       * @return the names of all Criteria in a vector
+       */
+      static std::vector< std::string > getAllCriteriaNamesVec();
+      
+      
+      /**
+       * Creates a Criterion with the name and the min and max values
+       * 
+       * @return a "new" Criterion (i.e. needs to be deleted later on)
+       */
+      static ICriterion* createCriterion( std::string critName , float min=0. , float max=0. ) ;
+      
+      /**
+       * Sets values for the passed referneced floats left and right. They indicate how
+       * the specified criterion should be cut, if necessary. Say you want for example
+       * a 99% quantile, so that 99% of your true tracks are within it.
+       * A criterion like the angle between two segments then needs to define a boarder like:
+       * between an angle of 1° and of 9° there will be 99%.
+       * So 1% is outside. But should 1% be the ones with a bigger angle or with a smaller angle or should
+       * this be 50:50? 
+       * 
+       * This is defined by left and right. Left is the proportion, that is taken away on the left side and
+       * right is the one that is taken away on the right side.
+       * In the case of an angle we will most probably have lots around 0° and a long tail to the right, so
+       * left = 0 and right = 1 seems like a good idea.
+       * Standard is of course 0.5 and 0.5
+       */
+      static void getLeftRight( std::string critName, float & left, float & right );
+      
+   
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/Criteria/ICriterion.h b/Utilities/KiTrack/Criteria/ICriterion.h
new file mode 100644
index 00000000..1ff8f950
--- /dev/null
+++ b/Utilities/KiTrack/Criteria/ICriterion.h
@@ -0,0 +1,68 @@
+#ifndef ICriterion_h
+#define ICriterion_h
+
+#include <vector>
+#include <map>
+#include <string>
+
+#include "KiTrack/Segment.h"
+#include "KiTrack/KiTrackExceptions.h"
+
+
+
+namespace KiTrack{
+
+
+   /** An Interface for Criteria.
+    * 
+    * A Criterion is a class, that is able to take two Segments and check whether they are compatible or not.
+    */   
+   class ICriterion{
+
+
+   public: 
+      
+      /** @return If the two Segments are compatible with each other, i.e. could be combined to a longer Segment or a 
+       * track.
+       */
+      virtual bool areCompatible( Segment* parent , Segment* child ) = 0;
+      
+      
+      /** @return A map, where the calculated values are stored. The keys are the names of the values.
+       */
+      std::map < std::string , float > getMapOfValues() {return _map_name_value; };
+      
+      
+      virtual ~ICriterion(){};
+      
+      /** Sets, whether the calculated values shall be saved in a map
+       */
+      void setSaveValues( bool saveValues ){ _saveValues = saveValues;}
+      
+      
+      /** @return the name of the criterion */
+      std::string getName(){return _name;}
+      
+      /** @return the type of the criterion */
+      std::string getType(){return _type;}
+     
+   protected:
+      
+      
+      std::map < std::string , float > _map_name_value{};
+      
+      bool _saveValues{};
+      
+      std::string _name{};
+      std::string _type{};
+      
+   };
+   
+}
+
+
+#endif
+
+
+
+
diff --git a/Utilities/KiTrack/ILDImpl/FTDHit01.h b/Utilities/KiTrack/ILDImpl/FTDHit01.h
new file mode 100644
index 00000000..6750231e
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/FTDHit01.h
@@ -0,0 +1,21 @@
+#ifndef FTDHit01_h
+#define FTDHit01_h
+
+#include "ILDImpl/IFTDHit.h"
+
+namespace KiTrackMarlin{
+  /** A class for hits in the FTD (the 01 is just for historical reasons and may be renamed)
+   * 
+   * - The side is according to CellID0.
+   * - Layer is set according to CellID0 +1 (so we can use layer 0 for the IP)
+   * - Module is set according to CellID0.
+   * - Sensor is set according to CellID0 -1. (because currently sensors of the FTD start with 1 in the CellID0, if this changes, this has to be modified)
+   */   
+  class FTDHit01 : public IFTDHit{
+  public:
+      
+    FTDHit01( edm4hep::TrackerHit trackerHit , const SectorSystemFTD* const sectorSystemFTD );
+  };
+}
+#endif
+
diff --git a/Utilities/KiTrack/ILDImpl/FTDHitSimple.h b/Utilities/KiTrack/ILDImpl/FTDHitSimple.h
new file mode 100644
index 00000000..36219730
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/FTDHitSimple.h
@@ -0,0 +1,45 @@
+#ifndef FTDHitSimple_h
+#define FTDHitSimple_h
+
+#include "KiTrack/IHit.h"
+
+#include "ILDImpl/SectorSystemFTD.h"
+
+
+
+namespace KiTrackMarlin{
+   
+   
+   /** A hit 
+    */   
+   class FTDHitSimple : public IHit{
+      
+      
+   public:
+      
+      FTDHitSimple( float x , float y , float z , int side, unsigned layer , unsigned module, unsigned sensor, const SectorSystemFTD* const sectorSystemFTD );
+      
+      
+      
+      virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemFTD; };
+      
+      virtual ~FTDHitSimple(){}
+      
+   private:
+      
+      int _side;
+      unsigned _layer;
+      unsigned _module;
+      unsigned _sensor;
+      
+      const SectorSystemFTD* _sectorSystemFTD;
+      
+      void calculateSector(){ _sector = _sectorSystemFTD->getSector( _side, _layer , _module , _sensor ); }
+      
+   };
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/ILDImpl/FTDNeighborPetalSecCon.h b/Utilities/KiTrack/ILDImpl/FTDNeighborPetalSecCon.h
new file mode 100644
index 00000000..07bfced5
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/FTDNeighborPetalSecCon.h
@@ -0,0 +1,46 @@
+#ifndef FTDNeighborPetalSecCon_h
+#define FTDNeighborPetalSecCon_h
+
+#include "KiTrack/ISectorConnector.h"
+
+#include "ILDImpl/SectorSystemFTD.h"
+
+
+
+namespace KiTrackMarlin{
+   
+   /** Used to connect two sectors.
+    * 
+    * Allows:
+    * 
+    * - Connections to the neighbouring petals (the one to the left and the one to the right on the same layer and side)
+    * 
+    */   
+   class FTDNeighborPetalSecCon : public ISectorConnector{
+      
+      
+   public:
+      
+      /**
+       * 
+       */
+      FTDNeighborPetalSecCon ( const SectorSystemFTD* sectorSystemFTD );
+      
+      virtual std::set <int>  getTargetSectors ( int sector );
+      
+      virtual ~FTDNeighborPetalSecCon(){};
+      
+   private:
+      
+      const SectorSystemFTD* _sectorSystemFTD;
+      
+      
+      
+   };
+   
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/ILDImpl/FTDSectorConnector.h b/Utilities/KiTrack/ILDImpl/FTDSectorConnector.h
new file mode 100644
index 00000000..8aaf4bfd
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/FTDSectorConnector.h
@@ -0,0 +1,55 @@
+#ifndef FTDSectorConnector_h
+#define FTDSectorConnector_h
+
+#include "KiTrack/ISectorConnector.h"
+
+#include "ILDImpl/SectorSystemFTD.h"
+
+
+
+namespace KiTrackMarlin{
+   
+   /** Used to connect two sectors on the FTD.
+    * 
+    * 
+    * Allows:
+    * 
+    * - going to layers on the inside (how far see constructor)
+    * - going to same petal or petals around (how far see constructor)
+    * - jumping to the IP (from where see constructor)
+    */   
+   class FTDSectorConnector : public ISectorConnector{
+      
+      
+   public:
+      
+      /** @param layerStepMax the maximum distance of the next layer on the inside
+       * 
+       *  @param petalStepMax the maximum distance of the next petal (in + and - direction )
+       * 
+       *  @param lastLayerToIP the highest layer from where a direct jump to the IP is allowed
+       */
+      FTDSectorConnector ( const SectorSystemFTD* sectorSystemFTD , unsigned layerStepMax , unsigned petalStepMax , unsigned lastLayerToIP);
+      
+      /** @return a set of all sectors that are connected to the passed sector */
+      virtual std::set <int>  getTargetSectors ( int sector );
+      
+      virtual ~FTDSectorConnector(){};
+      
+   private:
+      
+      const SectorSystemFTD* _sectorSystemFTD;
+      
+      unsigned _layerStepMax;
+      unsigned _petalStepMax;
+      unsigned _lastLayerToIP;
+      
+      
+   };
+   
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/ILDImpl/FTDTrack.h b/Utilities/KiTrack/ILDImpl/FTDTrack.h
new file mode 100644
index 00000000..3db4c908
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/FTDTrack.h
@@ -0,0 +1,71 @@
+#ifndef FTDTrack_h
+#define FTDTrack_h
+
+//#include "IMPL/TrackImpl.h"
+//#include "MarlinTrk/IMarlinTrkSystem.h"
+//#include "MarlinTrk/IMarlinTrack.h"
+#include "edm4hep/Track.h"
+#include "TrackSystemSvc/IMarlinTrkSystem.h"
+
+#include <vector>
+
+#include "ILDImpl/IFTDHit.h"
+#include "KiTrack/ITrack.h"
+
+#include "Tools/Fitter.h"
+
+
+namespace KiTrackMarlin{
+  /** A class for ITracks containing an lcio::Track at core
+   */
+  class FTDTrack : public ITrack {
+  public:
+    /** @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks
+     */
+    FTDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem );
+    
+    /** @param hits The hits the track consists of 
+     * @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks
+     */
+    FTDTrack( std::vector< IFTDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem );
+    FTDTrack( const FTDTrack& f );
+    FTDTrack & operator= (const FTDTrack & f);
+        
+    /** @return a track in the lcio format
+     */
+    edm4hep::Track* getLcioTrack(){ return ( _lcioTrack );}
+        
+    void addHit( IFTDHit* hit );
+    
+    virtual double getNdf() const { return _lcioTrack->getNdf(); }
+    virtual double getChi2() const { return _lcioTrack->getChi2(); }
+    virtual double getChi2Prob() const { return _chi2Prob; }
+    
+    virtual std::vector< IHit* > getHits() const { std::vector<IHit*> hits; 
+      for(unsigned i=0; i<_hits.size();i++) hits.push_back( _hits[i] ); 
+      return hits; }
+    
+    virtual double getQI() const;
+            
+    /** Fits the track and sets chi2, Ndf etc.
+     */
+    virtual void fit() ;
+    
+    virtual ~FTDTrack(){ delete _lcioTrack; }
+    
+  protected:
+    /** the hits the track consists of
+     */
+    std::vector< IFTDHit* > _hits;
+      
+    edm4hep::Track*  _lcioTrack;
+    
+    // for fitting
+    MarlinTrk::IMarlinTrkSystem* _trkSystem;
+    
+    double _chi2Prob;
+  };
+}
+#endif
+
+
diff --git a/Utilities/KiTrack/ILDImpl/IFTDHit.h b/Utilities/KiTrack/ILDImpl/IFTDHit.h
new file mode 100644
index 00000000..33b817bf
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/IFTDHit.h
@@ -0,0 +1,49 @@
+#ifndef IFTDHit_h
+#define IFTDHit_h
+
+
+#include "edm4hep/TrackerHit.h"
+
+#include "KiTrack/IHit.h"
+
+#include "ILDImpl/SectorSystemFTD.h"
+
+namespace KiTrackMarlin{
+  /** An interface for a hit for the ILD using an lcio TrackerHit as basis.
+   * 
+   * It comes along with a side, layer, module and a sensor.
+   */   
+  class IFTDHit : public IHit{
+  public:
+        
+    edm4hep::TrackerHit* getTrackerHit() { return &_trackerHit; };
+            
+    int getSide() { return _side; }
+    unsigned getModule() { return _module; }
+    unsigned getSensor() { return _sensor; }
+    
+    void setSide( int side ){ _side = side; calculateSector();}
+    void setLayer( unsigned layer ){ _layer = layer; calculateSector();}
+    void setModule( unsigned module ){ _module = module; calculateSector();}
+    void setSensor( unsigned sensor ){ _layer = sensor; calculateSector();}
+          
+    virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemFTD; };
+    
+  protected:
+    
+    edm4hep::TrackerHit _trackerHit;
+            
+    int _side;
+    unsigned _layer;
+    unsigned _module;
+    unsigned _sensor;
+    
+    const SectorSystemFTD* _sectorSystemFTD;
+    
+    /** Calculates and sets the sector number
+     */
+    void calculateSector(){ _sector = _sectorSystemFTD->getSector( _side, _layer , _module , _sensor ); }
+  };
+}
+#endif
+
diff --git a/Utilities/KiTrack/ILDImpl/SectorSystemFTD.h b/Utilities/KiTrack/ILDImpl/SectorSystemFTD.h
new file mode 100644
index 00000000..9f83b895
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/SectorSystemFTD.h
@@ -0,0 +1,93 @@
+#ifndef SectorSystemFTD_h
+#define SectorSystemFTD_h
+
+#include "KiTrack/ISectorSystem.h"
+
+using namespace KiTrack;
+
+namespace KiTrackMarlin{
+
+   /** A Sector System class for the Forward Tracking Disks FTD in the ILD.
+    * 
+    * It calculates sectors from the side, layer, sensor and module and vice versa.
+    * 
+    * @param side: +1 for forward, -1 for backward
+    * 
+    * @param layer: layer of FTD: 0 is the layer of the IP, 1 is the first FTD disk and so on.
+    * 
+    * @param module: module
+    * 
+    * @param sensor: the sensor on the module
+    * 
+    * 
+    */ 
+   class SectorSystemFTD : public ISectorSystem{
+      
+      
+   public:
+      
+      /**Constructor
+       * 
+       * @param nLayers the number of possible layers. The layers from 0 to n-1 will be available. Keep in mind,
+       * that layer 0 is used for the IP.
+       * 
+       * @param nModules the number of modules per disk.
+       * 
+       * @param nSensors the number of sensors on one module.
+       */
+      SectorSystemFTD( unsigned nLayers , unsigned nModules , unsigned nSensors );
+      
+      
+      /** Calculates the sector number corresponding to the passed parameters
+       */
+      int getSector( int side, unsigned layer , unsigned module , unsigned sensor ) const ;
+      
+      
+      /** Virtual, because this method is demanded by the Interface ISectorSystem
+       * 
+       * @return the layer corresponding to the passed sector number
+       */
+      virtual unsigned getLayer( int sector ) const ;
+      
+      
+      /** @return some information on the sector as string */
+      virtual std::string getInfoOnSector( int sector ) const;
+      
+      /** @return the side the sector is on (+1 = forward, -1 = backward)
+       */
+      int getSide( int sector ) const ;
+      
+      /** @return the module of the sector
+       */
+      unsigned getModule( int sector ) const ; 
+      
+      /** @return the sensor of the sector
+       */
+      unsigned getSensor( int sector ) const ;
+      
+      
+      
+      unsigned getNumberOfModules() const { return _nModules; }
+      unsigned getNumberOfSensors() const { return _nSensors; }
+      
+      virtual ~SectorSystemFTD(){}
+      
+   private:
+      
+      unsigned _nModules;
+      unsigned _nSensors;
+      
+      int _sectorMax;
+      
+      void checkSectorIsInRange( int sector ) const ;
+      
+   };
+
+
+
+}
+
+
+#endif
+
+
diff --git a/Utilities/KiTrack/ILDImpl/SectorSystemVXD.h b/Utilities/KiTrack/ILDImpl/SectorSystemVXD.h
new file mode 100644
index 00000000..6852f63a
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/SectorSystemVXD.h
@@ -0,0 +1,89 @@
+#ifndef SectorSystemVXD_h
+#define SectorSystemVXD_h
+
+#include "KiTrack/ISectorSystem.h"
+
+#include <vector>
+
+using namespace KiTrack;
+
+namespace KiTrackMarlin{
+
+   /** A Sector System class for the Forward Tracking Disks FTD in the ILD.
+    * 
+    * It calculates sectors from the side, layer, sensor and module and vice versa.
+    * 
+    * @param side: +1 for forward, -1 for backward
+    * 
+    * @param layer: layer of FTD: 0 is the layer of the IP, 1 is the first FTD disk and so on.
+    * 
+    * @param module: module
+    * 
+    * @param sensor: the sensor on the module
+    * 
+    * 
+    */ 
+   class SectorSystemVXD : public ISectorSystem{
+      
+      
+   public:
+      
+      /**Constructor
+       * 
+       * @param nLayers the number of possible layers. The layers from 0 to n-1 will be available. Keep in mind,
+       * that layer 0 is used for the IP.
+       * 
+       * @param nModules the number of modules per disk.
+       * 
+       * @param nSensors the number of sensors on one module.
+       */
+    SectorSystemVXD( unsigned nLayers , unsigned nDivisionsInPhi , unsigned nDivisionsInTheta );
+      
+
+      /** Virtual, because this method is demanded by the Interface ISectorSystem
+       * 
+       * @return the layer corresponding to the passed sector number
+       */
+      virtual unsigned getLayer( int sector ) const ;
+      
+      virtual unsigned getPhi( int sector ) const ;
+
+      virtual unsigned getTheta( int sector ) const ;
+
+      /** @return some information on the sector as string */
+      virtual std::string getInfoOnSector( int sector) const;
+
+
+      /** Calculates the sector number corresponding to the passed parameters
+       */
+      int getSector( int layer, int phi, int theta ) const ;
+
+      int getSector( int layer, double phi, double cosTheta ) const ;
+      
+      unsigned getPhiSectors() const ;
+
+      unsigned getThetaSectors() const ;
+
+      unsigned getNLayers() const ;
+
+      virtual ~SectorSystemVXD(){}
+      
+   private:
+      
+      int _sectorMax;
+      unsigned _nLayers;
+      unsigned _nDivisionsInPhi ;
+      unsigned _nDivisionsInTheta ;
+      
+      void checkSectorIsInRange( int sector ) const ;
+      
+   };
+
+
+
+}
+
+
+#endif
+
+
diff --git a/Utilities/KiTrack/ILDImpl/VXDHitSimple.h b/Utilities/KiTrack/ILDImpl/VXDHitSimple.h
new file mode 100644
index 00000000..fc464eef
--- /dev/null
+++ b/Utilities/KiTrack/ILDImpl/VXDHitSimple.h
@@ -0,0 +1,44 @@
+#ifndef VXDHitSimple_h
+#define VXDHitSimple_h
+
+#include "KiTrack/IHit.h"
+
+#include "ILDImpl/SectorSystemVXD.h"
+
+
+
+namespace KiTrackMarlin{
+   
+   
+   /** A hit 
+    */   
+   class VXDHitSimple : public IHit{
+      
+      
+   public:
+      
+      VXDHitSimple( float x , float y , float z , int layer , int phi, int theta, const SectorSystemVXD* const sectorSystemVXD );
+      
+      
+      
+      virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; };
+      
+      virtual ~VXDHitSimple(){}
+      
+   private:
+      
+      int _layer;
+      int _phi;
+      int _theta;
+      
+      const SectorSystemVXD* _sectorSystemVXD;
+      
+      //void calculateSector(){ _sector = _sectorSystemVXD->getSector( _side, _layer , _module , _sensor ); }
+      
+   };
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/KiTrack/Automaton.h b/Utilities/KiTrack/KiTrack/Automaton.h
new file mode 100644
index 00000000..249aa354
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/Automaton.h
@@ -0,0 +1,215 @@
+#ifndef Automaton_h
+#define Automaton_h
+
+#include <vector>
+#include "KiTrack/Segment.h"
+#include "Criteria/ICriterion.h"
+
+
+
+namespace KiTrack{
+   
+   
+   /** A class for the cellular automaton.
+    * 
+    * For detailed info on the Cellular Automaton and its use for track reconstruction see 
+    * <a href="../CellularAutomaton.pdf">Introduction to the Cellular Automaton</a>
+    * 
+    * <h3>About the class </h3>
+    * 
+    * This Cellular Automaton is specifically designed for track reconstruction, so it differs in the functionality
+    * from other Cellular Automata, like those used for simulation of biological cells.
+    * 
+    * The basic information on how the CA works and what it needs is describet in the pdf above. Here I'll only sum up
+    * the basics of this class.
+    * 
+    * The cells the Cellular Automaton deals with are here called segments as we deal with track reconstruction.
+    * These are the main information entities the CA deals with and therefore the most important member variable is 
+    * a container of these segments. (For more details on the segments see the doxygen of the Segment class)
+    * To sum it up: Segments consist of hits. So they are a bit like tracks. Or if they only consist of one single hit
+    * (so called 1-hit-segments) then they are like hits. 
+    * But there a few features that distinguish them from hits or tracks
+    *   - They can have parents and children. These are simply segments on top or below them. The idea is, that all
+    * segments on the inside are stored as children if they could belong to the same track. And the same for all segments
+    * on the outside possible belonging to the same track (the parents). So if we start at a segment and go to a child
+    * and on to a grandchild and so on, we follow a possible track. If we erase those connections we decrease the number
+    * of possible tracks.
+    *   - Segments must have a layer marking where it is. (layer 0: inside, higher layers further outside). This is a
+    * feature needed by the Automaton. Because it is an algorithm with discrete entities, we need some sort of discrete 
+    * ordering. (If we for example had a Cellular Automaton for simulation of 2 dimensional cells and we arranged the 
+    * cells for example on a chessboard, we always know the next cells. Here we have a 1 dimensional situation so we use
+    * layers)
+    *   - Segments have states: this is simply an integer number (an unsigned to be more precise). It is needed by the 
+    * Automaton to find connections that go all the way through (see pdf!)
+    *
+    * The Segments can be added via the addSegment() method and are stored layerwise.
+    * 
+    * Once the Segments are all stored in the Cellular Automaton it can perform.
+    * Via the method doAutomaton() it raises the states of the Segments until no change happens anymore.
+    * When this is done Segments not connected all the way through can be discarded by the method 
+    * cleanBadStates(). This reduces the number of possible tracks.
+    * 
+    * To get an initial Cellular Automaton to start with, the class SegmentBuilder can be used.
+    * (It takes hits builds segments from them and establishes the first parent-child relations)
+    * 
+    * In order to sort out even more it is possible to go to longer segments. So instead of checking 1-hit-segments,
+    * we can have a look at 2-hit-segments or 3-hit-segments. (And sort out much more along the way)
+    * For this the method lengthenSegments() is used. It combines connected segments and creates segments from them,
+    * that are exactly one hit longer. And then it is again time for connecting them.
+    * (I distinguish here between connecting: "storing the link" and combining: "making 1 new segment out of two others")
+    * 
+    * When segments are connected only connections that make sense are made. This is really important! If we don't make
+    * assumptions here, what Segments could belong together (i.e. could form a sensible track) we get lost in combinatorics.
+    * For this the so called Criteria are used. Via the method addCriterion() (or addCriteria() ) they can be added
+    * to the Cellular Automaton. All a Criterion does (see the Criterion doxygen for more info) is to say whether two
+    * Segments would give a good match. These criteria can be anything that makes sense in distinguishing between 
+    * real tracks and combinatorial background. For example if the segments are already long enough (already little tracks)
+    * one can compare the radius of their helices or the angle under which they meet and so on. 
+    * 
+    * Once we have longer segments we can again use the doAutomaton() method and then cleanBadStates(). Then we lenghten
+    * them once more and so on.
+    * 
+    * Between two such runs, one should of course clear the old Criteria with clearCriteria and reset the states of the
+    * Segments with resetStates().
+    *
+    * That's it. In the end, when nothing more is to be done in the Cellular Automaton, we need to extract the track
+    * candidates, it found. This is done via the getTracks() method. 
+    *
+    */ 
+   class Automaton{
+      
+      
+     
+   public:
+      
+      Automaton(): _nConnections(0){}
+      
+      /**
+       * delete all the segments
+       */
+      ~Automaton();
+      
+      
+      /** Adds a segment to the automaton.\
+       * Take care to set the layer of the segment before adding!
+       */
+      void addSegment ( Segment* segment );
+      
+      /**Lengthens the segments by one via adding the first hit of the next segment it is connected to
+       * to it.
+       * Also connects those longer segments with each other. ( one becomes a parent and one a child )
+       * Segments that don't have connected segments to use to get longer, will die here. 
+       */
+      void lengthenSegments();
+      
+      /**Adds a criteria to the automaton. So it will be used, when the methods doAutomaton()
+       * or cleanBadConnections() are called.
+       */
+      void addCriterion ( ICriterion* criterion ){ _criteria.push_back( criterion ); }
+      void addCriteria ( std::vector< ICriterion* > criteria ){ _criteria.insert( _criteria.end() , criteria.begin() , criteria.end() ); }
+      void clearCriteria() { _criteria.clear(); };
+      
+      /** Does iteration until the states of the segments don't change anymore.
+       * 
+       * In one iteration all segments are checked, if they have a neighbor.
+       * A neighbor:
+       * - has the same state
+       * - fulfills all the criteria (this is automatically provided, because in lengthenSegments only connections that fullfill the Criteria are made)
+       * 
+       * If it has a neighbor its state will be raised by one at the end of the iteration.
+       * (At the end only in theory: in the program it will be during the iteration, but
+       * in a way, that it doesn't affect other segments)
+       * 
+       * When after an iteration the states didn't change, it stops.
+       */
+      void doAutomaton();
+      
+      /**
+       * Erases all segments that don't have a state corresponding to their layer.
+       * 
+       * After the automaton is performed every segment, that has a neighbor, that has a neighbor, that...
+       * ...that reaches layer 0 should have a state equal to its layer. All the others are not connected
+       * to layer 0. All those get deleted by this method.
+       * (Of course all the connections to them are erased as well)
+       */
+      void cleanBadStates();
+      
+      /**
+       * Erase alls connections between segments, that don't satisfy the criteria.
+       */
+      void cleanBadConnections();
+      
+      /**Resets all the states of the segmens to 0 by calling the resetState() method of the segment
+       * Also sets all segments back to active.
+       */
+      void resetStates();
+      
+      
+      
+      /** Get all the possible tracks in the automaton.
+       * 
+       * Tracks are built by starting from segments which don't have a parent (and are therefore the begin of a track).
+       * For all children they have a new own track is created. The children themselves have children again, so the 
+       * tracks split up again.
+       * If we have for example a segment with 3 children, which each have 5 children, which each have 7 children,
+       * we will get 1*3*5*7=105 tracks.
+       * 
+       * @return All tracks that are possible with the given segments and their connections. Tracks are returned
+       * as a vector of hits. So the output will be a vector of a vector of hits
+       * 
+       * @param minHits the minimum number of hits that a track needs to have. All possible tracks,
+       * that have less won't be considered as tracks and won't be returned.
+       * 
+       */
+      //std::vector < std::vector< IHit* > > getTracks( unsigned minHits = 3 );
+      std::vector < std::vector< IHit* > > getTracks( unsigned minHits = 2 ); // YV, 2 mini-vector hits can form a track     
+      
+      /**Returns all the tracks starting from this segment.
+       * It is a recursive method and gets invoked by getTracks.
+       */
+      //std::vector < std::vector< IHit* > > getTracksOfSegment ( Segment* segment, std::vector< IHit* > hits , unsigned minHits = 3 );
+      std::vector < std::vector< IHit* > > getTracksOfSegment ( Segment* segment, std::vector< IHit* > hits , unsigned minHits = 2 );    // YV, 2 mini-vector hits can form a track   
+      
+      /**
+       * @return All the segments currently saved in the automaton
+       */
+      std::vector <const Segment*> getSegments() const;
+      
+      unsigned getNumberOfConnections(){ return _nConnections; }
+      
+   private:
+      
+      /** Here the segments are stored.
+       * The vector corresponds to the layer.
+       * The list corresponds to the segments on the layer.
+       * _segments[2] is a list with all segments on layer 2.
+       * 
+       * The segments will be deleted by the Automaton in the destructor
+       * 
+       */
+      std::vector < std::list < Segment* > > _segments{};
+      
+      /** A vector containing all the criteria, that are used in the Automaton
+       */
+      std::vector < ICriterion* > _criteria{};
+      
+      unsigned _nConnections{};
+      
+      
+      
+   };  
+   
+   
+   
+   
+   
+}
+
+
+
+
+
+
+#endif
+
+
diff --git a/Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h b/Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h
new file mode 100644
index 00000000..f1b22e46
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h
@@ -0,0 +1,129 @@
+#ifndef HopfieldNeuralNet_h
+#define HopfieldNeuralNet_h
+ 
+ 
+#include <vector>
+
+#include "KiTrackExceptions.h"
+
+namespace KiTrack{
+
+   /**
+    * Represents a Hopfield Neural Network
+    * 
+    * See <a href="../SubsetHopfieldNN.pdf">this</a> for detailed info.
+    * 
+    * Author: Robin Glattauer, HEPHY
+    */
+   class HopfieldNeuralNet {
+
+
+      public:
+         
+         /**
+         * @param G A matrix of the correlations between the neurons. 
+         * True means two neurons are incompatible. False means, they are
+         * compatible. (the diagonal elements are 0 by definition and any entry there will be ignored and set to 0) 
+         * 
+         * @param QI A vector containing the qualtity indicators of the neurons (i.e. their power to amplify or
+         * weaken other neurons). Quality should be indicated by a value between 0 and 1. 1 being the highest quality.
+         * 
+         * @param states The states of the neurons. Should be between 0 and 1.
+         * 
+         * @param omega Controls the influence of the quality indicator on the  activation of the neuron. Needs to be
+         * between 0 and 1. 0 means, no influence from the quality of the neurons -> system tends to biggest compatible 
+         * set. 1 means highest influence from the quality of the neurons -> the highest quality neurons tend to win.
+         */
+         HopfieldNeuralNet( std::vector < std::vector <bool> > G , std::vector < double > QI , std::vector < double > states , double omega) ;
+               
+               
+         /** Does one iteration of the neuronal network.
+         * 
+         * \f$ \vec{y} = W \times \vec{state} + \vec{w_0} \f$
+         * 
+         * \f$ \vec{state}_{new} = activationFunction(\vec{y}) \f$
+         * 
+         * @return Whether the Neural Network is considered as stable
+         */
+         bool doIteration();      
+            
+         /**
+         * Sets the temperature of the Neural Network (The HNN is cooled down in every iteration)
+         */
+         void setT    (double T)    { _T = T;};
+         
+         /**
+         * Sets the temperature at infinity. The temperature will converge to this
+         * value after infinite iterations.
+         */
+         void setTInf (double TInf) {_TInf = TInf;};
+         
+         /**
+         * Set the threshhold value below which the HNN is seen as "stable". As long as any Neuron changes its state 
+         * by a value bigger than this, the HNN is not considered stable. When all Neurons change their states so little,
+         * that none of the changes exceeds this threshold, then the HNN is stable.
+         */
+         void setLimitForStable (double limit) { _limitForStable = limit; };
+         
+         
+         /** @return the vector of the states
+         */
+         std::vector <double> getStates(){ return _States; };
+         
+
+         
+      protected:
+         
+         
+            
+         /** the matrix of the weights*/
+         std::vector < std::vector <double> > _W{};
+         
+         /** states describing how active a neuron is*/
+         std::vector < double > _States{};
+         
+         
+         std::vector < double > _w0{};
+         
+         /** temperature */
+         double _T{};
+         
+         /** temperature after infinite iterations */
+         double _TInf{};
+
+         /** indicates if the neuronal network is stable.
+         * this is true when the change after one iteration 
+         * of any neuron is not bigger than the value _limitForStable.
+         */
+         bool _isStable{};   
+
+         /** The upper limit for change of a neuron, if it should be considered stabel.*/
+         double _limitForStable{};
+         
+         /** Omega controls the influence of the quality indicator on the activation of the neuron.
+         */
+         double _omega{};
+
+         /** the order of the neurons to be updated. So it should of course reach from 0 to the number of neurons -1.
+         * (4 , 2, 0  1, 3) will for example mean: update first the neuron 4, then the neuron 2, then 0 and so on
+         */
+         std::vector <unsigned> _order{};
+         
+         
+         /** Calculates the activation function
+         * 
+         * @param state the state
+         * @param T the temperature
+         * @return the activation function corresponding to the input values: g(x) = 1/2* (1 + tanh( x/T ))
+         */
+         double activationFunction ( double state , double T );
+
+
+   };
+
+
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/KiTrack/IHit.h b/Utilities/KiTrack/KiTrack/IHit.h
new file mode 100644
index 00000000..736c6d21
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/IHit.h
@@ -0,0 +1,89 @@
+#ifndef IHit_h
+#define IHit_h
+
+#include "KiTrack/ISectorSystem.h"
+
+namespace KiTrack{
+   
+   
+   /** An Interface for hits.
+    * 
+    * They have of course a position, accessible with getX(), getY() and getZ().
+    * 
+    * Also a hit has a sector. A sector is just an integer, telling where the hit lies. For example
+    * a sector 141 could mean 1st layer, 4th module, 1st sensor. But how information is encoded is dealt
+    * with in the SectorSystem classes (see ISectorSystem for the Abstract Base Class ).
+    */   
+   class IHit{
+      
+      
+   public:
+
+       /** @return the x position */
+      float getX() const { return _x; }
+      
+      /** @return the y position */
+      float getY() const { return _y; }
+      
+      /** @return the z position */
+      float getZ() const { return _z; }
+      
+      /** @return the sector, where the hit lies n */
+      int getSector() const { return _sector; }
+      
+      /** @return the used SectorSystem that encodes the sector of the hit*/
+      virtual const ISectorSystem* getSectorSystem() const =0;
+      
+      /** @return the layer of the hit */
+      unsigned getLayer() const {return getSectorSystem()->getLayer( _sector ); }
+      
+      /** @return whether the hit is virtual (not a real hit). */ 
+      bool isVirtual() const { return _isVirtual; };
+      void setIsVirtual( bool isVirtual ){ _isVirtual = isVirtual; };
+      
+      /** @return the distance to an other hit */
+      float distTo( IHit* otherHit );
+      
+      /** @return a string containing the position of the hit */
+      std::string getPositionInfo();
+
+      /** to be used with mini-vectors: @return 3D angle */  //YV
+      double get3DAngle( IHit* /*otherHit*/) const { return _3DAngle ; }
+
+      /** to be used with mini-vectors: @return azimuth angle */  //YV
+      double getPhi() const { return _phiMV ; } 
+
+      /** to be used with mini-vectors: @return polar angle */  //YV
+      double getTheta() const { return _thetaMV ; } 
+
+      virtual ~IHit(){}
+      
+   protected:
+      
+      
+      float _x{};
+      float _y{};
+      float _z{};
+
+      double _3DAngle{};  //YV
+      double _phiMV{};     //YV
+      double _thetaMV{};     //YV
+      
+      int _sector{};
+      
+      
+      bool _isVirtual{};
+      
+      
+   };
+   
+   
+   
+}
+
+
+#endif
+
+
+
+
diff --git a/Utilities/KiTrack/KiTrack/ISectorConnector.h b/Utilities/KiTrack/KiTrack/ISectorConnector.h
new file mode 100644
index 00000000..558ea888
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/ISectorConnector.h
@@ -0,0 +1,40 @@
+#ifndef ISectorConnector_h
+#define ISectorConnector_h
+
+#include <set>
+
+
+namespace KiTrack{
+   
+   
+   /** Abstract Base Class for SectorConnectors.
+    * 
+    * A SectorConnector is pretty simple: you put in a sector (int) and get back a bunch of other sectors in a set.
+    * What it can be used for: Suppose you want to search for the path of a particle through a detector
+    * and you know what possible ways it can go, than you can create a SectorConnector to emulate that.
+    * So if you have a hit in sector 43 (whatever 43 means) and you think, that from there the particle will
+    * only go to either sector 46, 47 or 48, then you would write a SectorConnector that will return
+    * a set of 46,47,48 when the method getTargetSectors( 43 ) is called.
+    */
+   class ISectorConnector{
+      
+      
+   public:
+      
+      /** @return a set of sectors somehow linked to the passed one */
+      virtual std::set <int> getTargetSectors ( int ) = 0;
+      
+      virtual ~ISectorConnector(){};
+      
+   };
+   
+   
+   
+}
+
+
+
+#endif
+
+
+
diff --git a/Utilities/KiTrack/KiTrack/ISectorSystem.h b/Utilities/KiTrack/KiTrack/ISectorSystem.h
new file mode 100644
index 00000000..a9b3d992
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/ISectorSystem.h
@@ -0,0 +1,56 @@
+#ifndef ISectorSystem_h
+#define ISectorSystem_h
+
+#include <string>
+
+#include "KiTrack/KiTrackExceptions.h"
+
+namespace KiTrack{
+   
+   
+   /** An interface for Sector Systems. 
+    * 
+    * A sector is a code for a place. So it can for example equal a sensor somewhere in a detector or be something
+    * abstract like the IP.
+    * 
+    * A sector system is able to take a sector (integer number) and give back information
+    * about it. This can be things like the number of the sensor or the rough distance from the IP or such
+    * things. Or even neighbouring sectors. 
+    * But this is all dependent on the circumstances of the detectors and their representation. 
+    * 
+    * What all SectorSystems have in common is the layer: SectorSystems must be able to
+    * return the layer of a sector and how many layers there are all in all. 
+    */  
+   class ISectorSystem{
+      
+      
+   public:
+      
+      /** @return the layer of the corresponding sector. */
+      virtual unsigned getLayer( int sector ) const  =0;
+      
+      /** @return the number of layers in the sector system. */
+      unsigned getNumberOfLayers() const { return _nLayers; };
+      
+      /** @return some information on the sector as string */
+      virtual std::string getInfoOnSector( int sector ) const = 0;
+      
+      virtual ~ISectorSystem(){}
+      
+      
+      
+   protected:
+      
+      
+      unsigned _nLayers{};
+      
+      
+      
+   };
+   
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/KiTrack/ITrack.h b/Utilities/KiTrack/KiTrack/ITrack.h
new file mode 100644
index 00000000..50d7e895
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/ITrack.h
@@ -0,0 +1,47 @@
+#ifndef ITrack_h
+#define ITrack_h
+
+#include <vector>
+#include "KiTrack/IHit.h"
+
+namespace KiTrack{
+
+   
+   /** Abstract Base Class for tracks.
+    */
+   class ITrack{
+      
+      
+   public:
+      
+      /** @return a vector of the hits of the track
+       */
+      virtual std::vector< IHit*> getHits() const = 0;
+      
+      /** @return an indicator for the quality of the track. Usually between 0 and 1 */
+      virtual double getQI() const = 0; 
+      
+      /** Fits the track. */
+      virtual void fit() = 0;
+      
+      /** @return the degrees of freedom of the fit. This must only be called after fit() has been used */
+      virtual double getNdf() const = 0;
+      
+      /** @return the chi squared value of the fit. This must only be called after fit() has been used */
+      virtual double getChi2() const = 0;
+      
+      /** @return the chi squared probability of the fit. This must only be called after fit() has been used */
+      virtual double getChi2Prob() const = 0;
+      
+      virtual ~ITrack(){}
+      
+   };
+
+
+
+
+}
+
+#endif
+
+
diff --git a/Utilities/KiTrack/KiTrack/KiTrackExceptions.h b/Utilities/KiTrack/KiTrack/KiTrackExceptions.h
new file mode 100644
index 00000000..6e2a4a39
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/KiTrackExceptions.h
@@ -0,0 +1,105 @@
+#ifndef KiTrackExceptions_h
+#define KiTrackExceptions_h
+
+#include <string>
+#include <exception> 
+
+//Exceptions for the KiTrack namespace
+
+namespace KiTrack {
+
+  /**Base exception class for KiTrack - all other exceptions extend this.
+   * @author R. Glattauer, HEPHY
+   * 
+   */
+
+  class KiTrackException : public std::exception {
+
+    
+  protected:
+    std::string message{} ;
+    
+    KiTrackException(){  /*no_op*/ ; } 
+    
+  public: 
+     virtual ~KiTrackException()  { /*no_op*/; } 
+    
+    KiTrackException( const std::string& text ){
+      message = "KiTrack::Exception: " + text ;
+    }
+
+    virtual const char* what() const  noexcept { return  message.c_str() ; } 
+
+  };
+
+  
+  
+  /**Out of range exception, used when the user tries to access layers oder sensors, that are not implemented
+   * @author R. Glattauer, HEPHY
+   */
+  class OutOfRange : public KiTrackException{
+    
+  protected:
+    OutOfRange() {  /*no_op*/ ; } 
+  public: 
+    virtual ~OutOfRange()  { /*no_op*/; } 
+
+    OutOfRange( std::string text ){
+      message = "KiTrack::OutOfRange: " + text ;
+    }
+  }; 
+  
+  
+  /**Invalid Parameter exception.
+   * @author R. Glattauer, HEPHY
+   */
+  class InvalidParameter : public KiTrackException{
+     
+  protected:
+     InvalidParameter() {  /*no_op*/ ; } 
+  public: 
+     virtual ~InvalidParameter()  { /*no_op*/; } 
+     
+     InvalidParameter( std::string text ){
+        message = "KiTrack::InvalidParameter: " + text ;
+     }
+  }; 
+  
+  
+  /**Wrong segment length exception.
+   * @author R. Glattauer, HEPHY
+   */
+  class BadSegmentLength : public KiTrackException{
+     
+  protected:
+     BadSegmentLength() {  /*no_op*/ ; } 
+  public: 
+     virtual ~BadSegmentLength()  { /*no_op*/; } 
+     
+     BadSegmentLength( std::string text ){
+        message = "KiTrack::BadSegmentLength: " + text ;
+     }
+  }; 
+
+  
+  
+  /**Unknown criterion exception.
+   * @author R. Glattauer, HEPHY
+   */
+  class UnknownCriterion : public KiTrackException{
+     
+  protected:
+     UnknownCriterion() {  /*no_op*/ ; } 
+  public: 
+     virtual ~UnknownCriterion()  { /*no_op*/; } 
+     
+     UnknownCriterion( std::string text ){
+        message = "KiTrack::UnknownCriterion: " + text ;
+     }
+  }; 
+
+} 
+
+#endif
+
+
diff --git a/Utilities/KiTrack/KiTrack/Segment.h b/Utilities/KiTrack/KiTrack/Segment.h
new file mode 100644
index 00000000..6a31c2f3
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/Segment.h
@@ -0,0 +1,99 @@
+#ifndef Segment_h
+#define Segment_h
+
+#include <vector>
+#include <list>
+#include <string>
+
+#include "KiTrack/IHit.h"
+
+namespace KiTrack{
+
+   
+   /** A Segment is something like a track or a part of a track: it consists of hits linked together.
+    * 
+    * The simplest Segment consists of only one single hit (the truly smallest part of a track),
+    * a 1-hit-segment.
+    * A segment of two hits (a 2-hit-segment) is the next bigger version and so on.
+    * 
+    * Segments are used by the Cellular Automaton (see class Automaton), which uses them to find tracks.
+    * 
+    * The main difference to a hit (in case of 1-hit-segments) or a track (in case of segments with more hits) is, that
+    * the segments can have connection to other Segments. They can have children and parents.
+    * Children are connected Segments on the inside, Parents are connected Segments on the outside.
+    * 
+    * Inside and outside are w.r.t. the layer a segment is on. Every Segment has a layer (getLayer(), setLayer() ). The 
+    * layer indicates the place of the segment (whereever that place is. e.g. a detector ). Layer 0 usually means inside 
+    * and higher layers are further outside.
+    * 
+    * Also every Segment has a state. It is another feature requested by the Cellular Automaton. It gives the CA the possibility
+    * to check the quality of a Segment and manipulate it (the higher the state, usually the better; but for details on
+    * the states in the Cellular Autoamton see the <a href="../CellularAutomaton.pdf">Introduction to the Cellular Automaton</a> )
+    * 
+    * Segments can skip layers (a 1-hit-segment can't, since it is just a hit and can only be on one layer, but a 
+    * 2-hit-segment could already be the connection between layer 2 and layer 4, thus skipping a layer).
+    * For this the state is not only an integer, but a vector of integers representing states for every layer.
+    * (the 2-hit-segment skipping layer number 3 can therefore be imagined as two 2-hit-segments, each of them having
+    * a seperate state )
+    * 
+    */   
+   class Segment {
+   
+   
+   public:
+      
+      Segment( std::vector <IHit*> hits);
+      Segment( IHit* hit);
+      
+      
+      void deleteParent ( Segment* delParent ){ _parents.remove( delParent );};
+      void deleteChild ( Segment* delChild ){ _children.remove( delChild );};
+      
+      
+      std::list <Segment*> getChildren() { return _children;};
+      std::list <Segment*> getParents()  { return _parents;};
+      
+      std::vector <IHit*> getHits()const {return _hits;};
+      
+      void addChild( Segment* child ){ _children.push_back(child); };
+      void addParent( Segment* parent ){ _parents.push_back(parent); };
+      
+      unsigned getLayer()const { return _layer; };
+      void setLayer( unsigned layer ) { _layer = layer; }; 
+      
+      std::vector<int>& getState() { return _state; }; 
+      
+      void raiseState() { if (_state.size() > 0) _state[0]++; };
+      int getInnerState()const { return _state[0];}; 
+      int getOuterState()const { return _state.back();}; 
+      void resetState();
+      
+      void setSkippedLayers( unsigned skippedLayers ){ _state.resize( skippedLayers + 1 );}
+      
+      bool isActive() const { return _active;}
+      void setActive( bool active ){ _active = active; }
+      
+      /** @return infos about the segment */
+      std::string getInfo();
+     
+   private:
+      
+      std::list <Segment*> _children{}; 
+      std::list <Segment*> _parents{};
+      
+      
+      
+      std::vector <IHit*> _hits{};
+      
+      std::vector<int> _state{};
+      
+      unsigned _layer{};
+      bool _active{};
+      
+   };
+
+
+} //end of KiTrack Namespace
+
+#endif
+
diff --git a/Utilities/KiTrack/KiTrack/SegmentBuilder.h b/Utilities/KiTrack/KiTrack/SegmentBuilder.h
new file mode 100644
index 00000000..a33a4f77
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/SegmentBuilder.h
@@ -0,0 +1,94 @@
+#ifndef SegmentBuilder_h
+#define SegmentBuilder_h
+
+#include "Criteria/ICriterion.h"
+#include "KiTrack/ISectorConnector.h"
+#include "KiTrack/Automaton.h"
+
+namespace KiTrack{
+
+
+   /** This classe builds the Cellular Automaton from the hits
+    * 
+    * It can be used to take all the autHits stored in a map< int , vector < IHits > > and makes
+    * 1-hit-segments out of them ( see the class Segment for more info on them ).
+    * 
+    * The created 1-segments then are connected.
+    * 
+    * For the rules of connecting criteria and hitConnectors can be added to the object:
+    * 
+    * - a hitConnector takes the sector of the segment ( for example a cellID0 or a layer number or an own code ) and returns
+    * all the sectors we might connect to. So there we get the information like: "this segment can be connected
+    * to layer 3 and 4, module 7,8,9 in forward direction".
+    * 
+    * - the criteria take two segments and return whether they are compatible or not. 
+    * A criterion could check for anything, that is stored in the segments. 
+    * For example: if the line formed from two 1-hit segments passes close by the IP might
+    * be a criterion for very stiff tracks.
+    * 
+    * So the hitConnectors tell us were to look and the criteria whether to connect. If two 1-hit segments are found,
+    * that are compatible, they will be connected. Connected means: The inner 1-segment will save the outer one as a parent
+    * and the outer one will save the inner one as a child.
+    * 
+    * All this (except adding hitConnectors and Criteria) is done in the method get1SegAutomaton.
+    * 
+    * This method finally then returns an automaton (segments sorted by their layers), ready to be used.
+    * 
+    */   
+   class SegmentBuilder{
+      
+     
+   public: 
+      
+      /**
+       * @param ftdRep the FTDRepresentation to take the autHits from
+       */
+      SegmentBuilder(  std::map< int , std::vector< IHit* > > map_sector_hits );
+      
+      /** Adds a criterion. 
+       */
+      void addCriterion ( ICriterion* criterion ){ _criteria.push_back( criterion );};
+      
+      /** Adds criteria
+       */
+      void addCriteria ( std::vector< ICriterion* > criteria){ _criteria.insert( _criteria.end(), criteria.begin() , criteria.end() ); }
+      
+      /** Adds a hitConnector
+       */
+      void addSectorConnector ( ISectorConnector* connector ){ _sectorConnectors.push_back( connector ); };
+      
+      /**
+       * @return An automaton containing all the hits from the FTDRepresentation sorted now by layers. 
+       * (attention: those are not necessarily the same layers as the FTD layers).
+       * Also they are connected.
+       */
+      Automaton get1SegAutomaton();
+      
+      
+   private:
+      
+      
+      std::vector <ICriterion* > _criteria{};
+      std::vector <ISectorConnector* > _sectorConnectors{};
+      
+      std::map< int , std::vector< IHit* > > _map_sector_hits{};
+      
+      
+      
+      
+      
+   };
+
+
+
+
+
+}
+
+
+#endif
+
+
+
+
+
diff --git a/Utilities/KiTrack/KiTrack/Subset.h b/Utilities/KiTrack/KiTrack/Subset.h
new file mode 100644
index 00000000..6b3e9fd5
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/Subset.h
@@ -0,0 +1,58 @@
+#ifndef Subset_h
+#define Subset_h
+
+
+#include "KiTrack/ITrack.h"
+
+
+namespace KiTrack {
+ 
+   /** A base class for subsets.
+    * 
+    * The idea behind the subset classes is, that one has a collection of elements, but not all elements are compatible
+    * with each other. One wants to find a subset of these elements, where all are compatible. Also the subset should have
+    * a high quality. 
+    * Details about this can be found in the derived classes. For technical reasons (templates and virtual methods) 
+    * this class only covers the basics.
+    */
+   template <class T>
+   class Subset{
+      
+   public:
+      
+      /** Adds an element
+       */
+      void add( T newElement ){ _elements.push_back( newElement ); };
+      
+      /** Adds a vector of elements
+       */
+      void add( std::vector<T> newElements ){ _elements.insert( _elements.end() , newElements.begin() , newElements.end() ); };
+      
+      
+      /** @return the subset of the best tracks, i.e. all the tracks that were accepted
+       */
+      std::vector< T > getAccepted(){ return _acceptedElements;} ;
+      
+      /** @return the tracks that got rejected (and are therefore not in the best subset)
+       */
+      std::vector< T > getRejected(){ return _rejectedElements;} ;
+      
+      
+   
+   protected:
+      
+      std::vector< T > _elements{};
+      std::vector< T > _acceptedElements{};
+      std::vector< T > _rejectedElements{};
+      
+      
+   };
+   
+   
+   
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h b/Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h
new file mode 100644
index 00000000..5d92a2f0
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h
@@ -0,0 +1,399 @@
+#ifndef SubsetHopfieldNN_h
+#define SubsetHopfieldNN_h
+
+#include <CLHEP/Random/RandFlat.h>
+
+#include "KiTrack/Subset.h"
+#include "KiTrack/HopfieldNeuralNet.h"
+
+
+
+namespace KiTrack {
+ 
+   /** A class to get the best subset with help of a Hopfield Neural Network
+    * 
+    */
+   template< class T >
+   class SubsetHopfieldNN : public Subset<T>{
+      
+   public:
+      
+      /** Calculates the best set using a Hopfield Neural Network 
+       * (see <a href="../SubsetHopfieldNN.pdf">this</a> for more info) . 
+       * 
+       * After this the results can be accessed with 
+       * the getAccepted() and getRejected() methods (provided by the baseclass Subset).
+       *
+       * 
+       * This is a templated class to allow the reuse with objects from different.
+       * The goal is this: if you have a set of things that are somehow compatible or incompatible 
+       * with each other and you want a subset that only contains compatible ones and has a high quality, to find
+       * this subset.
+       * 
+       * For example: you plan a concert where a lot of different artists shall perform together. You have 20 that
+       * you are interested in asking. BUT: not all of them get along together very well. So artist 1 might be incompatible
+       * with artist 2 and 7 for some arbitrary reasons. And artist 2 is incompatible with artist 1,3 and 13 and so on.
+       * In order not to completely mess up the concert you can only invite artists who are entirely compatible with each other.
+       * AND: not all artists are equal: some are really famous and some are pretty mediocre.
+       * So you want to find a set of artists with the highest possible quality which is completely compatible.
+       * 
+       * This is done by this class. The algorithm used for it is a Hopfield Neural Network (HNN).
+       * 
+       * In order to work it needs to know two things: how to calculate the quality of an element and how to determine
+       * if two elements are compatible. These are of course things the user has to provide.
+       * For both a functor object is needed.
+       * 
+       * Here is how it could look like in the artist example:
+       * 
+\verbatim
+ 
+class AristQI{
+  
+   public:
+ 
+   // returns the quality of an artist (a value between 0 and 1, 0 being bad and 1 being fantastic)  
+   inline double operator()( Artist artist ){
+   
+      return artist.numberOfFans()/nPeopleOnEarth;    // a number between 0 and 1
+      
+  }
+
+};
+
+class ArtistCompatibility{
+
+public:
+
+   // returns whether two artists are compatible
+   inline bool operator()( Artist artistA, Artist artistB ){
+   
+      if( artistA.hates( artistB ) ) return false;
+      else return true; 
+     
+   }
+
+};
+
+
+//Somewhere within the program:
+
+ArtistCompatibility comp;
+ArtistQI qi;
+
+SubsetHopfieldNN< Artist > subset;
+subset.add( vecOfArtists );                                 
+subset.calculateBestSet( comp, qi );
+
+std::vector< Artist > artistsToInvite = subset.getAccepted();
+std::vector< Artist > artistsToStayAtHome = subset.getRejected();
+
+
+\endverbatim
+       * 
+       * 
+       * @param areCompatible a functor of type bool( T, T ) that should tell whether two elements are compatible
+       * or not.
+       * 
+       * @param getQI a functor of type double( T ) that returns the quality of an element and should range between 0 and 1.
+       */
+      template< class GetQI, class AreCompatible >
+      void calculateBestSet( AreCompatible areCompatible, GetQI getQI );
+      
+      
+      SubsetHopfieldNN(){ 
+       
+         _TStart = 2.1;
+         _TInf = 0.1;
+         _omega = 0.75;
+         _limitForStable = 0.01;
+         _initStateMin = 0.;
+         _initStateMax = 0.1;
+         _activationThreshold = 0.5;
+         
+      }
+      
+      void setTStart( double tStart ){ _TStart = tStart; }
+      void setTInf( double tInf ){ _TInf = tInf; }
+      void setOmega( double omega ){ _omega = omega; }
+      void setLimitForStable( double limitForStable ){ _limitForStable = limitForStable; }
+      void setInitStateMin( double initStateMin ){ _initStateMin = initStateMin; }
+      void setInitStateMax( double initStateMax ){ _initStateMax = initStateMax; }
+      void setActivationThreshold( double activationThreshold ){ _activationThreshold = activationThreshold; }
+      
+      double getTStart(){ return _TStart; }
+      double getTInf(){ return _TInf; }
+      double getOmega(){ return _omega; }
+      double getLimitForStable(){ return _limitForStable; }
+      double getInitStateMin(){ return _initStateMin; }
+      double getInitStateMax(){ return _initStateMax; }
+      double getActivationThreshold(){ return _activationThreshold; }
+      
+   protected:
+      
+      
+      double _TStart{};
+      double _TInf{};
+      double _omega{};
+      double _limitForStable{};
+      double _initStateMin{};
+      double _initStateMax{};
+      double _activationThreshold{};
+      
+   };
+   
+   
+   template< class T > template< class GetQI, class AreCompatible >
+   void SubsetHopfieldNN<T>::calculateBestSet( AreCompatible areCompatible, GetQI getQI ){
+      
+      
+      unsigned nAccepted=0;
+      unsigned nRejected=0;
+      unsigned nCompWithAll=0;
+      unsigned nIncompatible=0;
+      
+      
+      std::vector< T > elements = this->_elements; //this pointer is needed here, because of the template!
+      
+      unsigned nElements = elements.size();
+      
+      // the information for the Hopfield Neural Network:
+      
+      std::vector < std::vector <bool> > G; // a matrix telling, if two neurons (elements) are compatible
+      G.resize( nElements );
+      for (unsigned i=0; i<nElements; i++) G[i].resize( elements.size() );
+      
+      std::vector < double > QI ; // the quality indicators of the neurons (elements)
+      QI.resize( nElements );
+      
+      std::vector < double > states; // the initial state to start from.
+      states.resize( nElements );
+      
+      
+      
+      
+      /**********************************************************************************************/
+      /*                1. Find out which elements are compatible and get the QIs                     */
+      /**********************************************************************************************/
+      
+      
+      for ( unsigned i=0; i < nElements ; i++){ //over all elements
+         
+         
+         T elementA = elements[i]; //the track we want to look at.
+         
+         // Get the quality
+         QI[i] = getQI( elementA );
+         
+         //streamlog_out(DEBUG3) << "QI of element " << i << " = " << QI[i] << "\n";
+         
+         
+         // Set an initial state
+         states[i] = CLHEP::RandFlat::shoot ( _initStateMin , _initStateMax ); //random ( uniformly ) values from initStateMin to initStateMax
+         
+         
+         // Fill the states in the G matrix. (whether two elements are compatible or not
+         for ( unsigned j=i+1; j < nElements ; j++ ){ // over all elements that come after the current one (the elements before get filled automatically because of symmetry)
+            
+            T elementB = elements[j]; // the track we check if it is in conflict with trackA
+            
+            if ( areCompatible( elementA , elementB ) ){ 
+               
+               G[i][j] = 0;
+               G[j][i] = 0;
+               
+            }
+            else{
+               
+               G[i][j] = 1;
+               G[j][i] = 1;            
+               
+            }
+            
+         }
+         
+      }
+      
+      // output of the G matrix:
+      if( !G.empty() ){
+         
+	//streamlog_out(DEBUG2) << "G:\n";
+         
+         
+         for ( unsigned i=0; i < G.size(); i++ ){
+            
+            
+            for ( unsigned j=0; j < G[i].size(); j++ ){
+               
+	      //streamlog_out(DEBUG2) << G[i][j] << "  ";
+               
+            }
+            
+            //streamlog_out(DEBUG2) << "\n";
+            
+         }
+        
+      }
+      // output, where one sees, what elements are  incompatible with what others:
+      if( !G.empty() ){
+         
+	//streamlog_out(DEBUG2) << "Incompatible ones:\n";
+         
+         
+         for ( unsigned i=0; i < G.size(); i++ ){
+            
+	   //streamlog_out(DEBUG2) << "Element " << i << ":\t";
+            
+            for ( unsigned j=0; j < G[i].size(); j++ ){
+               
+	      //if( G[i][j] ) streamlog_out(DEBUG2) << j << ", ";
+               
+            }
+            
+            //streamlog_out(DEBUG2) << "\n";
+            
+         }
+         
+      }
+      
+      
+      /**********************************************************************************************/
+      /*                2. Save elements, that are compatible with all others                         */
+      /**********************************************************************************************/
+      
+      for( unsigned i=0; i < elements.size(); i++ ){
+         
+         
+         bool isCompatibleWithAll = true;
+         
+         //check if this track is compatible with all others
+         for( unsigned j=0; j < elements.size(); j++){
+            
+            //G[i][j] == 0 i and j are compatible, if G[i][j] == 1 i and j are incompatible
+            if( (i != j) && G[i][j] ){
+               
+               isCompatibleWithAll = false;
+               break;
+               
+            }
+            
+         }
+         
+         
+         if ( isCompatibleWithAll ){ //if it is compatible with all others, we don't need the Hopfield Neural Net, we can just save it
+            
+            
+            //add the track to the good ones
+            this->_acceptedElements.push_back( elements[i] );
+            nCompWithAll++;
+            
+            
+            //And now erase it from the ones we will still check:
+            elements.erase( elements.begin() + i );
+            states.erase( states.begin() + i );
+            QI.erase( QI.begin() + i );
+            
+            for( unsigned j=0; j<G.size(); j++ ) G[j].erase( G[j].begin() + i );
+                     G.erase( G.begin() + i );
+            
+            i--;
+            
+         }
+         else{
+            
+            nIncompatible++;
+            
+         }
+         
+      }
+      
+      
+      //streamlog_out( DEBUG3 ) << nCompWithAll << " elements are compatible with all others, " << nIncompatible
+      //<< " elements are interfering and will be checked for the best subset\n";
+      
+      
+      
+      /**********************************************************************************************/
+      /*                3. Let the Neural Network perform to find the best subset                   */
+      /**********************************************************************************************/  
+      
+      if( !elements.empty() ){
+         
+         HopfieldNeuralNet net( G , QI , states , _omega);
+         
+         net.setT ( _TStart );
+         net.setTInf( _TInf );
+         net.setLimitForStable( _limitForStable );
+         
+         unsigned nIterations=1;
+         
+         //streamlog_out(DEBUG1) << "states: ( ";
+         //for ( unsigned int i=0; i< states.size(); i++) streamlog_out(DEBUG1) << states[i] << " "; 
+         //streamlog_out(DEBUG1) << ")\n";
+         
+         while ( !net.doIteration() ){ // while the Neural Net is not (yet) stable
+            
+            nIterations++;
+            
+            std::vector <double> newStates = net.getStates();
+            
+            //streamlog_out(DEBUG1) << "states: ( ";      
+            
+            //for ( unsigned int i=0; i< newStates.size(); i++) streamlog_out(DEBUG1) << newStates[i] << " "; 
+            
+            //streamlog_out(DEBUG1) << ")\n";
+            
+         }
+         
+         
+         
+         //streamlog_out( DEBUG3 ) << "Hopfield Neural Network is stable after " << nIterations << " iterations.\n";
+         
+         
+         
+         
+         /**********************************************************************************************/
+         /*                4. Now just sort the elements into accepted and rejected ones                 */
+         /**********************************************************************************************/  
+         
+         
+         states = net.getStates();
+         
+         
+         
+         for ( unsigned i=0; i < states.size(); i++ ){
+            
+            
+            if ( states[i] >= _activationThreshold ){
+               
+               this->_acceptedElements.push_back( elements[i] );
+               nAccepted++;
+               
+            }
+            else{
+               
+               this->_rejectedElements.push_back( elements[i] );
+               nRejected++;
+               
+            }
+            
+         }
+         
+      }
+      
+      
+      //streamlog_out( DEBUG3 ) << "Hopfield Neural Network accepted " << nAccepted 
+      //<< " elements and rejected " << nRejected << " elements of all in all " 
+      //<< nAccepted + nRejected << "incomaptible elements.\n";
+      
+      //streamlog_out( DEBUG3 )   << "So in sum " << nAccepted + nCompWithAll
+      //<< " elements survived and " << nRejected << " elements got rejected.\n";
+      
+      
+   }
+   
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/KiTrack/SubsetSimple.h b/Utilities/KiTrack/KiTrack/SubsetSimple.h
new file mode 100644
index 00000000..a5521621
--- /dev/null
+++ b/Utilities/KiTrack/KiTrack/SubsetSimple.h
@@ -0,0 +1,186 @@
+#ifndef SubsetSimple_h
+#define SubsetSimple_h
+
+#include <algorithm>
+
+//#include "marlin/VerbosityLevels.h"
+
+#include "KiTrack/Subset.h"
+
+namespace KiTrack {
+   
+   
+   template <class T, class QI >
+   struct SorterQI
+   {
+      SorterQI( QI getQI ): _getQI( getQI ){}
+      
+      bool operator()( T a, T b ){ return ( _getQI( a ) > _getQI( b ) ); }
+      
+      QI _getQI;
+   };
+   
+ 
+   /** A class to get the best subset by taking the element with the highest quality
+    * indicator and throwing away all incompatible ones. 
+    * On the remaining elements repeat the procedure. 
+    * 
+    */
+   template <class T >
+   class SubsetSimple : public Subset<T> {
+      
+   public:
+      
+      /** Calculates the best set using a very simple method. After this the results can be accessed with 
+       * the getAccepted() and getRejected() methods (provided by the baseclass Subset).
+       * 
+       * This is a templated class to allow the reuse with objects from different.
+       * The goal is this: if you have a set of things that are somehow compatible or incompatible 
+       * with each other and you want a subset that only contains compatible ones and has a high quality, to find
+       * this subset.
+       * 
+       * For example: you plan a concert where a lot of different artists shall perform together. You have 20 that
+       * you are interested in asking. BUT: not all of them get along together very well. So artist 1 might be incompatible
+       * with artist 2 and 7 for some arbitrary reasons. And artist 2 is incompatible with artist 1,3 and 13 and so on.
+       * In order not to completely mess up the concert you can only invite artists who are entirely compatible with each other.
+       * AND: not all artists are equal: some are really famous and some are pretty mediocre.
+       * So you want to find a set of artists with the highest possible quality which is completely compatible.
+       * 
+       * This is done by this class. 
+       * 
+       * The algorithm used for it is this: take the element with the highest quality and accept it. Reject all
+       * other elements that are incompatible with it. From the remaining elements redo the same with the next best
+       * element.
+       * In our artist example: take the biggest star and throw out all he doesn't get allong with. From the remaining
+       * artists (those who do get along with the biggest star) pick next famous one. Once again kick out all that
+       * don't get along with him and so on.
+       * 
+       * In order to work it needs to know two things: how to calculate the quality of an element and how to determine
+       * if two elements are compatible. These are of course things the user has to provide.
+       * For both a functor object is needed.
+       * 
+       * Here is how it could look like in the artist example:
+       * 
+\verbatim
+
+class AristQI{
+   
+public:
+   
+   // returns the quality of an artist (a value between 0 and 1, 0 being bad and 1 being fantastic)  
+   inline double operator()( Artist artist ){
+      
+      return artist.numberOfFans()/nPeopleOnEarth;    // a number between 0 and 1
+      
+   }
+   
+};
+
+class ArtistCompatibility{
+   
+public:
+   
+   // returns whether two artists are compatible
+   inline bool operator()( Artist artistA, Artist artistB ){
+      
+      if( artistA.hates( artistB ) ) return false;
+      else return true; 
+      
+   }
+   
+};
+
+
+//Somewhere within the program:
+
+ArtistCompatibility comp;
+ArtistQI qi;
+
+SubsetHopfieldNN< Artist > subset;
+subset.add( vecOfArtists );                                 
+subset.calculateBestSet( comp, qi );
+
+std::vector< Artist > artistsToInvite = subset.getAccepted();
+std::vector< Artist > artistsToStayAtHome = subset.getRejected();
+
+
+\endverbatim
+       * 
+       * 
+       * 
+       * @param areCompatible a functor of type bool( T, T ) that should tell whether two elements are compatible
+       * or not.
+       * 
+       * @param getQI a functor of type double( T ) that returns the quality of an element and should range between 0 and 1.
+       */
+      template< class GetQI, class AreCompatible >
+      void calculateBestSet( AreCompatible areCompatible, GetQI getQI );
+   };
+   
+   template<class T> template<class GetQI, class AreCompatible> 
+   void SubsetSimple<T>::calculateBestSet( AreCompatible areCompatible, GetQI getQI ){
+      
+      
+      unsigned nAccepted=0;
+      unsigned nRejected=0;
+      
+      
+      
+      std::vector< T > elements = this->_elements;
+      
+      // sort the vector from big QI to small QI
+      SorterQI< T, GetQI > sorterQI( getQI );
+      sort( elements.begin(), elements.end() , sorterQI );
+      
+      //std::cout << "DEBUG: SubsetSimple::calculateBestSet The elements and their QIs sorted:" << std::endl;
+      for( unsigned i=0; i < elements.size(); i++ ){
+	double qi = getQI( elements[i] );
+	//std::cout << "DEBUG: SubsetSimple::calculateBestSet " << elements[i] << "\t" << qi << std::endl;
+      }
+      
+      /*The idea here is: the first track is (now that we sorted) the one with the highest
+       * QI. Check all other tracks if they are complatible with it.
+       * If one of them is incompatible throw it away. Once done with that, store the
+       * first track as accepted (and delete it from the vector) and do it once more for
+       * the new highest QI track.
+       * Repeat until all tracks are stored.
+       */   
+      while( elements.size() > 0 ){
+         
+         
+         // check all elements with smaller QI if they are compatible
+         for( unsigned i=1; i < elements.size(); i++){
+            
+            
+            if( areCompatible( elements[0] , elements[i] ) == false ){ // the track is incompatible
+               
+               // reject it
+               nRejected++;
+               this->_rejectedElements.push_back( elements[i] );
+               
+	       //std::cout << "DEBUG: SubsetSimple::calculateBestSet " << "reject " << elements[i] << std::endl;
+               // and delete it from the elements we are looking at
+               elements.erase( elements.begin() + i );
+               i--;
+               
+            }
+            
+         }
+         
+         // store the first element
+	 //std::cout << "DEBUG: SubsetSimple::calculateBestSet " << "accept " << elements[0] << std::endl;
+         nAccepted++;
+         this->_acceptedElements.push_back( elements[0] );
+         
+         // delete it from the current tracks
+         elements.erase( elements.begin() );
+         
+      }
+            
+      //std::cout << "DEBUG: SubsetSimple::calculateBestSet " << "SubsetSimple accepted " << nAccepted 
+      //		<< " elements and rejected " << nRejected << " elements of all in all " 
+      //		<< nAccepted + nRejected << " elements." << std::endl;
+      
+   }
+} // end namespace
+#endif
diff --git a/Utilities/KiTrack/Tools/FTDHelixFitter.h b/Utilities/KiTrack/Tools/FTDHelixFitter.h
new file mode 100644
index 00000000..6050ae01
--- /dev/null
+++ b/Utilities/KiTrack/Tools/FTDHelixFitter.h
@@ -0,0 +1,65 @@
+#ifndef FTDHelixFitter_h
+#define FTDHelixFitter_h
+
+#include "edm4hep/Track.h"
+#include "edm4hep/TrackerHitConst.h"
+
+class FTDHelixFitterException : public std::exception {
+ protected:
+   std::string message ;
+   
+   FTDHelixFitterException(){  /*no_op*/ ; } 
+   
+ public: 
+   virtual ~FTDHelixFitterException() { /*no_op*/; } 
+   
+   FTDHelixFitterException( const std::string& text ){
+      message = "FTDHelixFitterException: " + text ;
+   }
+   
+   virtual const char* what() const noexcept { return  message.c_str() ; } 
+   
+};
+
+/** A class to make it quick to fit a track or hits and get back the chi2 and Ndf values and
+ * also bundle the code used for that, so it doesn't have to be copied all over the places.
+ * Uses a helix fit from the MarlinTrk class HelixFit.cc
+ * It is named FTDHelixFitter, because it makes some assumptions about the hits, that come from them
+ * being on the FTD. Specifically the errors passed to the helix fit are calculated on the assumption,
+ * that du and dv are errors in the xy plane.
+ * If this class is intended to be used for hits on different detectors, a careful redesign is necessary!
+ */
+class FTDHelixFitter{
+ public:
+   
+  FTDHelixFitter( edm4hep::Track* track ) ;
+  FTDHelixFitter( std::vector<edm4hep::ConstTrackerHit> trackerHits ) ;
+   
+   
+   double getChi2(){ return _chi2; }
+   int getNdf(){ return _Ndf; }
+   
+   float getOmega(){ return _omega; }
+   float getTanLambda(){ return _tanLambda; }
+   float getPhi0(){ return _phi0; }
+   float getD0(){ return _d0; }
+   float getZ0(){ return _z0; }
+   
+ private:
+   
+   void fit();
+   
+   double _chi2;
+   int _Ndf;
+   
+   float _omega;
+   float _tanLambda;
+   float _phi0;
+   float _d0;
+   float _z0;
+   
+   std::vector< edm4hep::ConstTrackerHit > _trackerHits;
+     
+};
+
+#endif
diff --git a/Utilities/KiTrack/Tools/Fitter.h b/Utilities/KiTrack/Tools/Fitter.h
new file mode 100644
index 00000000..461d735d
--- /dev/null
+++ b/Utilities/KiTrack/Tools/Fitter.h
@@ -0,0 +1,129 @@
+#ifndef Fitter_h
+#define Fitter_h
+
+#include "TrackSystemSvc/IMarlinTrkSystem.h"
+#include "TrackSystemSvc/IMarlinTrack.h"
+#include "edm4hep/Track.h"
+//#include "lcio.h"
+
+#include "Math/ProbFunc.h"
+
+
+//using namespace lcio;
+
+
+
+class FitterException : public std::exception {
+   
+   
+protected:
+   std::string message ;
+   
+   FitterException(){  /*no_op*/ ; } 
+   
+public: 
+   virtual ~FitterException() { /*no_op*/; } 
+   
+   FitterException( const std::string& text ){
+      message = "FitterException: " + text ;
+   }
+   
+   virtual const char* what() const noexcept { return  message.c_str() ; } 
+   
+};
+
+
+
+/** A class to store additional information together with a TrackState, namely the chi2 value and Ndf
+ */
+class TrackStatePlus{
+   
+   
+   
+public: 
+   
+  const edm4hep::TrackState* getTrackState() const {return _trackState; }
+  double getChi2() const {return _chi2;}
+  int getNdf() const {return _Ndf;}
+  
+ TrackStatePlus( const edm4hep::TrackState* trackState, double chi2, int Ndf ):
+  _trackState( trackState ), _chi2( chi2 ), _Ndf( Ndf ){}
+   
+   
+   
+private: 
+   
+  const edm4hep::TrackState* _trackState;
+   double _chi2;
+   int _Ndf;
+   
+   
+};
+
+
+/** A class to make it quick to fit a track or hits and get back the chi2, Ndf and chi2prob values and
+ * also bundle the code used for that, so it doesn't have to be copied all over the places.
+ */
+class Fitter{
+   
+   
+public:
+   
+  Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem );
+  Fitter( std::vector < edm4hep::ConstTrackerHit > trackerHits, MarlinTrk::IMarlinTrkSystem* trkSystem );
+  Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem, int VXDFlag );  
+
+   
+   double getChi2Prob( int trackStateLocation ) ;
+   double getChi2( int trackStateLocation ) ;
+   int getNdf( int trackStateLocation ) ;
+   
+   //TODO: maybe add methods for custom points (location: TrackState::AtOther) In that case, the point would have to
+   // be passed as well. (or only the point is passed)
+   
+   const edm4hep::TrackState* getTrackState( int trackStateLocation ) ;
+   
+   ~Fitter(){ 
+      
+      for( unsigned i=0; i<_trackStatesPlus.size(); i++ ){
+         
+         delete _trackStatesPlus[i]->getTrackState();
+         delete _trackStatesPlus[i];
+         
+      }
+      _trackStatesPlus.clear();
+      
+      delete _marlinTrk;
+      
+   }
+   
+private:
+   
+   void init_BField();
+
+   const TrackStatePlus* getTrackStatePlus( int trackStateLocation ) ;
+
+   void fit();
+
+   void fitVXD();
+   
+   static float _bField;
+   
+   
+   std::vector< edm4hep::ConstTrackerHit > _trackerHits;
+   
+   /** here the created TrackStates (plus) are stored */
+   std::vector< const TrackStatePlus* > _trackStatesPlus;
+   
+   MarlinTrk::IMarlinTrkSystem* _trkSystem;
+   
+   MarlinTrk::IMarlinTrack* _marlinTrk;
+   
+   // No copy constructor or assignment needed so far. so private for safety
+   // If they are needed, they need to be implemented in a clean way first!
+   Fitter( const Fitter& f ){};
+   Fitter& operator= ( Fitter const& f ){return *this;}
+   
+};
+
+#endif
diff --git a/Utilities/KiTrack/Tools/KiTrackMarlinTools.h b/Utilities/KiTrack/Tools/KiTrackMarlinTools.h
new file mode 100644
index 00000000..f4b58292
--- /dev/null
+++ b/Utilities/KiTrack/Tools/KiTrackMarlinTools.h
@@ -0,0 +1,97 @@
+#ifndef KiTrackMarlinTools_h
+#define KiTrackMarlinTools_h
+
+#include <string>
+#include <set>
+#include <vector>
+#include <map>
+//#include <sstream>
+
+#include "edm4hep/TrackerHit.h"
+#include "edm4hep/Track.h"
+
+#include "ILDImpl/FTDHitSimple.h"
+#include "ILDImpl/VXDHitSimple.h"
+#include "KiTrack/ITrack.h"
+
+using namespace KiTrack;
+
+namespace KiTrackMarlin{
+
+/** @return information about the contents of the passed CellID0 */ 
+std::string getCellID0Info( int cellID0 );
+
+/** @return the layer given by the cellID0 */
+int getCellID0Layer( int cellID0 );
+
+/** Generates a root file with a specified name and with a single tree .
+ * If a rootfile with the same name already exists, a number will be appended
+ * to it, so the old one doesn't get lost.
+ * So if I create myRoot.root and it already exists, the old one will be renamed to
+ * "myRoot1.root".
+ * If "myRoot1.root" already exists, "myRoot2.root" will be created.
+ * 
+ * So after we did this for some time, we end up with a lot of root files with numbers.
+ * The one without a number appended is the newest one.
+ * The one with the number 1 appended is the oldest, 2 is newer than 1, 3 is newer than 2 and so on.
+ * 
+ * @param branchNames A set of all the branchnames that should be created in the tree
+ * 
+ * @param createNew Whether to create a new root file or create the tree and branches in an existing one
+ */
+void setUpRootFile( std::string fileNamePath, std::string treeName , std::set<std::string> branchNames = std::set<std::string>() , bool createNew=true );
+
+
+/** Saves values to a tree in a rootfile.
+ * 
+ * @param fileNamePath the name (path) of the rootfile
+ * 
+ * @param treeName the name of the tree
+ * 
+ * @param map_name_data a map of key = name of what we save , mapped value = value we want to save
+ * 
+ */
+void saveToRoot( std::string fileNamePath, std::string treeName , std::map < std::string , float > map_name_data );
+
+void saveToRoot( std::string rootFileName, std::string treeName , std::vector < std::map < std::string , float > > rootDataVec );
+
+
+
+
+/** method that compares two TrackerHits.
+ * 
+ * @return true if |a.z| < |b.z| , i.e. true if a is nearer to z=0 than b is
+ */
+//bool compare_TrackerHit_z( edm4hep::ConstTrackerHit* a, edm4hep::ConstTrackerHit* b );
+bool compare_TrackerHit_z( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b );
+
+/** method that compares two TrackerHits.
+ * 
+ * @return true if |a.R| < |b.R| , i.e. true if a has smaller radius than b 
+ *
+ * to be used at the VXD-SIT system
+ */
+bool compare_TrackerHit_R( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b );
+
+
+FTDHitSimple* createVirtualIPHit( int side , const SectorSystemFTD* sectorSystemFTD );
+
+VXDHitSimple* createVirtualIPHit( const SectorSystemVXD* sectorSystemVXD );
+
+
+std::string getPositionInfo( edm4hep::ConstTrackerHit* hit );
+
+std::string getPositionInfo( IHit* hit );   
+
+std::string getTrackHitInfo( ITrack* track );
+
+std::string getTrackHitInfo( edm4hep::Track* track );
+
+} // end of namespace KiTrackMarlin
+
+
+
+
+#endif
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.cc
new file mode 100644
index 00000000..9bf3a11f
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.cc
@@ -0,0 +1,84 @@
+#include "Criteria/Crit2_DeltaPhi.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+Crit2_DeltaPhi::Crit2_DeltaPhi ( float deltaPhiMin , float deltaPhiMax ){
+   
+   
+   _deltaPhiMax = deltaPhiMax;  
+   _deltaPhiMin = deltaPhiMin;  
+   _name = "Crit2_DeltaPhi";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit2_DeltaPhi::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+      
+      
+      IHit* a = parent->getHits()[0];
+      IHit* b = child-> getHits()[0];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+
+
+      float bx = b->getX();
+      float by = b->getY();
+
+      
+
+      float phia = atan2( ay, ax );
+      float phib = atan2( by, bx );
+      float deltaPhi = phia-phib;
+      if (deltaPhi > M_PI) deltaPhi -= 2*M_PI;           //to the range from -pi to pi
+      if (deltaPhi < -M_PI) deltaPhi += 2*M_PI;           //to the range from -pi to pi
+      
+      if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaPhi = 0.; // In case one of the hits is too close to the origin
+
+      deltaPhi = 180.*fabs( deltaPhi ) / M_PI;
+      if (_saveValues) _map_name_value["Crit2_DeltaPhi"]= deltaPhi;
+
+      
+      
+              
+         
+      if ( deltaPhi > _deltaPhiMax ) return false;
+
+      if ( deltaPhi < _deltaPhiMin ) return false;
+      
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_DeltaPhi::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.h
new file mode 100644
index 00000000..342e7750
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.h
@@ -0,0 +1,38 @@
+#ifndef Crit2_DeltaPhi_h
+#define Crit2_DeltaPhi_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the difference between the \f$ \phi \f$ angles of two hits in degrees. 
+    * The \f$ \phi \f$ is the angle in the xy plane w.r.t. the positive x axis.
+    * \f[ \phi = atan2(y,x) \f]
+    */
+   class Crit2_DeltaPhi : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_DeltaPhi ( float deltaPhiMin , float deltaPhiMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit2_DeltaPhi(){};
+
+    
+   private:
+      
+      float _deltaPhiMax{};
+      float _deltaPhiMin{};
+      
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc
new file mode 100644
index 00000000..a94b0ea9
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc
@@ -0,0 +1,78 @@
+#include "Criteria/Crit2_DeltaPhi_MV.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+Crit2_DeltaPhi_MV::Crit2_DeltaPhi_MV ( float deltaPhiMin , float deltaPhiMax ){
+   
+   
+   _deltaPhiMax = deltaPhiMax;  
+   _deltaPhiMin = deltaPhiMin;  
+   _name = "Crit2_DeltaPhi_MV";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit2_DeltaPhi_MV::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+      IHit* a = parent->getHits()[0];
+      IHit* b = child->getHits()[0];
+
+      double phia = a->getPhi();
+      double phib = b->getPhi();
+      
+      double deltaPhi = phia-phib;
+      
+      if (deltaPhi > M_PI) deltaPhi -= 2*M_PI;           //to the range from -pi to pi
+      if (deltaPhi < -M_PI) deltaPhi += 2*M_PI;           //to the range from -pi to pi
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float bx = b->getX();
+      float by = b->getY();
+      
+      if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaPhi = 0.; // In case one of the hits is too close to the origin
+      
+      deltaPhi = 180.*fabs( deltaPhi ) / M_PI;
+      if (_saveValues) _map_name_value["Crit2_DeltaPhi_MV"]= deltaPhi;
+      
+        
+      if ( deltaPhi > _deltaPhiMax ) return false;
+      
+      if ( deltaPhi < _deltaPhiMin ) return false;
+      
+      
+   }
+
+
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_DeltaPhi_MV::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h
new file mode 100644
index 00000000..3dee9bad
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h
@@ -0,0 +1,38 @@
+#ifndef Crit2_DeltaPhi_MV_h
+#define Crit2_DeltaPhi_MV_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the difference between the \f$ \phi \f$ angles of two hits in degrees. 
+    * The \f$ \phi \f$ is the angle in the xy plane w.r.t. the positive x axis.
+    * \f[ \phi = atan2(y,x) \f]
+    */
+   class Crit2_DeltaPhi_MV : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_DeltaPhi_MV ( float deltaPhiMin , float deltaPhiMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit2_DeltaPhi_MV(){};
+
+    
+   private:
+      
+      float _deltaPhiMax{};
+      float _deltaPhiMin{};
+      
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.cc
new file mode 100644
index 00000000..64190dc6
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.cc
@@ -0,0 +1,81 @@
+#include "Criteria/Crit2_DeltaRho.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+Crit2_DeltaRho::Crit2_DeltaRho ( float deltaRhoMin , float deltaRhoMax ){
+   
+   
+   _deltaRhoMax = deltaRhoMax;  
+   _deltaRhoMin = deltaRhoMin;
+   
+   _name = "Crit2_DeltaRho";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+      
+bool Crit2_DeltaRho::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+      
+      
+      IHit* a = parent->getHits()[0];
+      IHit* b = child-> getHits()[0];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+
+      float bx = b->getX();
+      float by = b->getY();
+      
+      //the distance to (0,0) in the xy plane
+      float rhoA =  sqrt( ax*ax + ay*ay );
+      float rhoB =  sqrt( bx*bx + by*by );
+      
+      float deltaRho = rhoA - rhoB;
+      
+      //first check, if the distance to (0,0) rises --> such a combo could not reach the IP
+      if (_saveValues){
+         _map_name_value["Crit2_DeltaRho_rhoParent"] = rhoA;
+         _map_name_value["Crit2_DeltaRho_rhoChild"] = rhoB;
+         _map_name_value["Crit2_DeltaRho"] = deltaRho;
+      }
+      
+      
+     
+      if ( deltaRho > _deltaRhoMax ) return false;
+      if ( deltaRho < _deltaRhoMin ) return false;
+      
+      
+            
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_DeltaRho::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.h
new file mode 100644
index 00000000..3b65daec
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.h
@@ -0,0 +1,36 @@
+#ifndef Crit2_DeltaRho_h
+#define Crit2_DeltaRho_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the difference of the sqrt(x^2 + y^2) of two hits.
+    */
+   class Crit2_DeltaRho : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_DeltaRho ( float deltaRhoMin , float deltaRhoMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit2_DeltaRho(){};
+      
+    
+   private:
+      
+      float _deltaRhoMax{};
+      float _deltaRhoMin{};
+      
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.cc
new file mode 100644
index 00000000..5d0f0463
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.cc
@@ -0,0 +1,84 @@
+#include "Criteria/Crit2_DeltaTheta_MV.h"
+
+#include <cmath>
+#include <sstream>
+//#include <iostream>   // for debugging
+
+using namespace KiTrack;
+
+Crit2_DeltaTheta_MV::Crit2_DeltaTheta_MV ( float deltaThetaMin , float deltaThetaMax ){
+   
+   
+   _deltaThetaMax = deltaThetaMax;  
+   _deltaThetaMin = deltaThetaMin;  
+   _name = "Crit2_DeltaTheta_MV";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit2_DeltaTheta_MV::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+
+     IHit* a = parent->getHits()[0];
+     IHit* b = child->getHits()[0];
+     
+       
+     double thetaa = a->getTheta();
+     double thetab = b->getTheta();
+
+     //streamlog_out(DEBUG4) << " theta a = " << (180*thetaa)/M_PI << " theta b = " << (180*thetab)/M_PI << std::endl ;
+     
+     double deltaTheta = thetaa-thetab;
+     
+     if (deltaTheta > M_PI) deltaTheta -= 2*M_PI;           //to the range from -pi to pi
+     if (deltaTheta < -M_PI) deltaTheta += 2*M_PI;           //to the range from -pi to pi
+
+     float ax = a->getX();
+     float ay = a->getY();
+     float bx = b->getX();
+     float by = b->getY();
+     
+     if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaTheta = 0.; // In case one of the hits is too close to the origin
+      
+     deltaTheta = 180.*fabs( deltaTheta ) / M_PI;
+     if (_saveValues) _map_name_value["Crit2_DeltaTheta_MV"]= deltaTheta;
+     
+     
+     if ( deltaTheta > _deltaThetaMax ) return false;
+     
+     if ( deltaTheta < _deltaThetaMin ) return false;
+       
+     //streamlog_out(DEBUG4) << " delta theta " << deltaTheta << " max " <<  _deltaThetaMax << " min " <<  _deltaThetaMin << std::endl ;    
+     
+     
+   }
+
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_DeltaTheta_MV::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.h
new file mode 100644
index 00000000..3f9a0494
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.h
@@ -0,0 +1,38 @@
+#ifndef Crit2_DeltaTheta_MV_h
+#define Crit2_DeltaTheta_MV_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the difference between the \f$ \theta \f$ angles of two hits in degrees. 
+    * The \f$ \theta \f$ is the angle in the xy plane w.r.t. the positive x axis.
+    * \f[ \theta = atan2(y,x) \f]
+    */
+   class Crit2_DeltaTheta_MV : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_DeltaTheta_MV ( float deltaThetaMin , float deltaThetaMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit2_DeltaTheta_MV(){};
+
+    
+   private:
+      
+      float _deltaThetaMax{};
+      float _deltaThetaMin{};
+      
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.cc b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.cc
new file mode 100644
index 00000000..95f5e7d2
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.cc
@@ -0,0 +1,74 @@
+#include "Criteria/Crit2_Distance_MV.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+Crit2_Distance_MV::Crit2_Distance_MV ( float deltaPos2Min , float deltaPos2Max ){
+   
+   
+   _deltaPos2Max = deltaPos2Max;  
+   _deltaPos2Min = deltaPos2Min;  
+   _name = "Crit2_Distance_MV";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit2_Distance_MV::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+      IHit* a = parent->getHits()[0];
+      IHit* b = child->getHits()[0];
+
+      float ax = a->getX();
+      float ay = a->getY();
+      float bx = b->getX();
+      float by = b->getY();
+
+      double posa = sqrt(ax*ax + ay*ay);
+      double posb = sqrt(bx*bx + by*by);
+      
+      double deltaPos2 = (posa-posb) * (posa-posb) ;
+      
+      if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaPos2 = 0.; // In case one of the hits is too close to the origin
+      
+      if (_saveValues) _map_name_value["Crit2_Distance_MV"]= deltaPos2;
+      
+        
+      if ( deltaPos2 > _deltaPos2Max ) return false;
+      
+      if ( deltaPos2 < _deltaPos2Min ) return false;
+      
+      
+   }
+
+
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_Distance_MV::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.h b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.h
new file mode 100644
index 00000000..6463acb2
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.h
@@ -0,0 +1,38 @@
+#ifndef Crit2_Distance_MV_h
+#define Crit2_Distance_MV_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the difference between the \f$ \phi \f$ angles of two hits in degrees. 
+    * The \f$ \phi \f$ is the angle in the xy plane w.r.t. the positive x axis.
+    * \f[ \phi = atan2(y,x) \f]
+    */
+   class Crit2_Distance_MV : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_Distance_MV ( float deltaPos2Min , float deltaPos2Max );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit2_Distance_MV(){};
+
+    
+   private:
+      
+      float _deltaPos2Max{};
+      float _deltaPos2Min{};
+      
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.cc b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.cc
new file mode 100644
index 00000000..0c8baf1c
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.cc
@@ -0,0 +1,125 @@
+#include "Criteria/Crit2_HelixWithIP.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+using namespace KiTrack;
+
+Crit2_HelixWithIP::Crit2_HelixWithIP ( float ratioMin , float ratioMax ){
+   
+   
+   _ratioMax = ratioMax;  
+   _ratioMin = ratioMin;  
+   
+   _name = "Crit2_HelixWithIP";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+      
+bool Crit2_HelixWithIP::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+      
+      
+      IHit* a = parent->getHits()[0];
+      IHit* b = child-> getHits()[0];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      
+      
+      float ratio = 1.;
+      
+      try{
+         
+         SimpleCircle circle ( 0. , 0. , ax , ay , bx , by );
+         
+         float x = circle.getCenterX();
+         float y = circle.getCenterY();
+         
+         
+         //calculate the angle in the circle from the IP to the child hit:
+         
+         //vector from the center of circle to the IP
+         float ux = 0. - x;
+         float uy = 0. - y;
+         
+         //vector from the center of circle to the child
+         float vx = bx - x;
+         float vy = by - y;
+
+         //vector from the center of circle to the parent
+         float wx = ax - x;
+         float wy = ay - y;
+         
+         //the angle between u and v (angle between two vectors: cos(alpha) = u*v/|u||v| )
+         float alpha1 = acos ( (ux*vx + uy*vy ) / sqrt(( ux*ux + uy*uy ) * ( vx*vx + vy*vy )) );
+         
+         //the angle between v and w
+         float alpha2 = acos ( (vx*wx + vy*wy ) / sqrt(( vx*vx + vy*vy ) * ( wx*wx + wy*wy )) );
+         
+         float deltaz1 = bz - 0.;
+         float deltaz2 = az - bz;
+         
+
+         
+         if ( ( alpha2 != 0) && (deltaz1 != 0) ) ratio = ( alpha1 * deltaz2 ) / ( alpha2 * deltaz1 );
+         
+
+
+         
+      }
+      catch ( InvalidParameter ){
+         
+        
+      }
+      
+
+
+      
+      if (_saveValues) _map_name_value["Crit2_HelixWithIP"]= ratio;
+       
+         
+      if ( ratio > _ratioMax ) return false;
+
+      if ( ratio < _ratioMin ) return false;
+      
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_HelixWithIP::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.h b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.h
new file mode 100644
index 00000000..2f888e15
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.h
@@ -0,0 +1,43 @@
+#ifndef Crit2_HelixWithIP_h
+#define Crit2_HelixWithIP_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: Check if two hits are compatible with a helix crossing the IP.
+    * The procedure is this: a circle is calculated from the two hits and the IP.
+    * The angle between the center of the circle and two hits is calles alpha here.
+    * alpha between IP and the first hit is proportional to the z-distance of the IP
+    * and the first hit in the same way alpha between the first and second hit should 
+    * be proportional to the z-distance of those hits. The value calculated is
+    * \f[ \frac{ \frac{\alpha_1}{\Delta z_1} }{ \frac{\alpha_2}{\Delta z_2} } \simeq 1 \f]
+    * and is 1 for a perfect helix around the z - axis.
+    */
+   class Crit2_HelixWithIP : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_HelixWithIP ( float ratioMin , float ratioMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit2_HelixWithIP(){};
+
+    
+   private:
+      
+      float _ratioMax{};
+      float _ratioMin{};
+      
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.cc b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.cc
new file mode 100644
index 00000000..781e95b8
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.cc
@@ -0,0 +1,82 @@
+#include "Criteria/Crit2_RZRatio.h"
+
+#include <cmath>
+#include <sstream>
+
+
+using namespace KiTrack;
+
+Crit2_RZRatio::Crit2_RZRatio ( float ratioMin, float ratioMax ){
+   
+   
+   _ratioMax = ratioMax;
+   _ratioMin = ratioMin;
+   
+   _name = "Crit2_RZRatio";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+   
+   
+}
+
+  
+bool Crit2_RZRatio::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+      
+      IHit* a = parent->getHits()[0];
+      IHit* b = child-> getHits()[0];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      // the square is used, because it is faster to calculate with the squares than with sqrt, which takes some time!
+      double ratioSquared = 0.; 
+      if ( az-bz  != 0. ) ratioSquared = ( (ax-bx)*(ax-bx) + (ay-by)*(ay-by) + (az-bz)*(az-bz) ) / ( (az-bz) * ( az-bz ) );
+      
+      
+      if (_saveValues) _map_name_value[ "Crit2_RZRatio"] = sqrt( ratioSquared );
+      
+
+      
+      if ( ratioSquared > _ratioMax * _ratioMax ) return false;
+      if ( ratioSquared < _ratioMin * _ratioMin ) return false;
+  
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_RZRatio::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
+
+
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.h b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.h
new file mode 100644
index 00000000..1d1ea36f
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.h
@@ -0,0 +1,35 @@
+#ifndef Crit2_RZRatio_h
+#define Crit2_RZRatio_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: distance of two hits divided by their z-distance.
+    * \f[ \frac{\sqrt{ \Delta x^2 + \Delta y^2 + \Delta z^2 }}{\left| \Delta z \right|}\f]
+    */
+   class Crit2_RZRatio : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_RZRatio ( float ratioMin, float ratioMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit2_RZRatio(){};
+    
+   private:
+      
+      float _ratioMax{};
+      float _ratioMin{};
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.cc b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.cc
new file mode 100644
index 00000000..f52351ef
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.cc
@@ -0,0 +1,90 @@
+#include "Criteria/Crit2_StraightTrackRatio.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+Crit2_StraightTrackRatio::Crit2_StraightTrackRatio ( float ratioMin, float ratioMax ){
+   
+   
+   _ratioMax = ratioMax; 
+   _ratioMin = ratioMin;
+   
+   _name = "Crit2_StraightTrackRatio";
+   _type = "2Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+      
+bool Crit2_StraightTrackRatio::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments
+      
+      
+      
+      IHit* a = parent->getHits()[0];
+      IHit* b = child-> getHits()[0];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      //the distance to (0,0) in the xy plane
+      double rhoASquared = ax*ax + ay*ay;
+      double rhoBSquared = bx*bx + by*by;
+      
+      
+
+      
+      if (_saveValues){
+         _map_name_value["Crit2_StraightTrackRatio"]= 1.;
+         
+      }
+     
+      
+      if( (rhoBSquared >0.) && ( az != 0. ) ){ //prevent division by 0
+         
+         // the square is used, because it is faster to calculate with the squares than with sqrt, which takes some time!
+         double ratioSquared = ( ( rhoASquared * ( bz*bz )  ) / ( rhoBSquared * ( az*az )  ) );
+               
+         if (_saveValues) _map_name_value["Crit2_StraightTrackRatio"] = sqrt(ratioSquared);
+         
+         
+         if ( ratioSquared > _ratioMax * _ratioMax ) return false;
+   
+         if ( ratioSquared < _ratioMin * _ratioMin ) return false;
+      
+      }
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit2_StraightTrackRatio::This criterion needs 2 segments with 1 hit each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.h b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.h
new file mode 100644
index 00000000..3d46c215
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.h
@@ -0,0 +1,41 @@
+#ifndef Crit2_StraightTrackRatio_h
+#define Crit2_StraightTrackRatio_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: for straight tracks: if the line between the two hits points towards IP.
+    * Calculated is
+    * 
+    * \f[ \frac{ \frac{\rho_1}{z_1} }{ \frac{\rho_2}{z_2} } \simeq 1 \f]
+    * 
+    * , where \f$ \rho = \sqrt{ x^2 + y^2 }\f$
+    */
+   class Crit2_StraightTrackRatio : public ICriterion{
+
+
+
+   public:
+      
+      Crit2_StraightTrackRatio ( float ratioMin, float ratioMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit2_StraightTrackRatio(){};
+
+    
+   private:
+      
+      float _ratioMax{};
+      float _ratioMin{};
+      
+      
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.cc b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.cc
new file mode 100644
index 00000000..2f3c4203
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.cc
@@ -0,0 +1,121 @@
+#include "Criteria/Crit3_2DAngle.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+Crit3_2DAngle::Crit3_2DAngle ( float angleMin, float angleMax ){
+   
+   
+   _cosAngleMin = cos ( angleMax * M_PI / 180. );
+   _cosAngleMax = cos ( angleMin * M_PI / 180. );
+   
+   _name = "Crit3_2DAngle";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+      
+bool Crit3_2DAngle::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   //this is not written very beautiful, because this code gets called often and needs to be fast.
+   //But it's just a simple angle calculation of two vectors cos(alpha) = u*v/|u||v|
+   //
+   //Because of speed, I avoided using stuff like sqrt or cos or something in here.
+   //That's why it may look a bit odd.
+   
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      
+      
+      float ux = bx - ax;
+      float uy = by - ay;
+
+      
+      float vx = cx - bx;
+      float vy = cy - by;
+
+   
+      //In the numerator there is the vector product of u and v   
+      double numerator= ux*vx + uy*vy;
+      
+      //In the denominator there are the lengths of u and v (here squared)
+      double uSquared= ux*ux + uy*uy;
+      double vSquared= vx*vx + vy*vy;
+      
+
+      
+      double denomSquared = uSquared * vSquared;
+      
+      if (_saveValues){
+         
+         _map_name_value["Crit3_2DAngle_cos2DAngleSquared"] =  1.;
+         _map_name_value["Crit3_2DAngle"] = 0.;
+         
+      }
+      
+      if ( denomSquared > 0.){ //don't divide by 0
+      
+         double cosThetaSquared = numerator * numerator / ( uSquared * vSquared );
+         if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!!
+         
+         if (_saveValues){
+            
+            _map_name_value["Crit3_2DAngle_cos2DAngleSquared"] =  cosThetaSquared;
+            _map_name_value["Crit3_2DAngle"] = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI;
+            
+         }
+         
+         if (cosThetaSquared < _cosAngleMin*_cosAngleMin) return false;
+         if (cosThetaSquared > _cosAngleMax*_cosAngleMax) return false;
+      
+      }
+      
+      
+      
+
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_2DAngle::This criterion needs 2 segments with 2 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.h b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.h
new file mode 100644
index 00000000..666f5fed
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.h
@@ -0,0 +1,36 @@
+#ifndef Crit3_2DAngle_h
+#define Crit3_2DAngle_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the angle between two 2-segments in the xy - plane
+    */
+   class Crit3_2DAngle : public ICriterion{
+
+
+
+   public:
+      
+      /**
+       * @param angleMax the maximum angle between 2 2-segments in grad
+       */
+      Crit3_2DAngle ( float angleMin, float angleMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit3_2DAngle(){};
+    
+   private:
+      
+      float _cosAngleMin{};
+      float _cosAngleMax{};
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.cc b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.cc
new file mode 100644
index 00000000..a70c962d
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.cc
@@ -0,0 +1,134 @@
+#include "Criteria/Crit3_2DAngleTimesR.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+
+using namespace KiTrack;
+
+Crit3_2DAngleTimesR::Crit3_2DAngleTimesR ( float angleMin, float angleMax ){
+   
+   
+   _angleMin = angleMin;
+   _angleMax = angleMax;
+   
+   _name = "Crit3_2DAngleTimesR";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+      
+bool Crit3_2DAngleTimesR::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   //this is not written very beautiful, because this code gets called often and needs to be fast.
+   //But it's just a simple angle calculation of two vectors cos(alpha) = u*v/|u||v|
+   //
+   //Because of speed, I avoided using stuff like sqrt or cos or something in here.
+   //That's why it may look a bit odd.
+   
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      
+      
+      float ux = bx - ax;
+      float uy = by - ay;
+
+      
+      float vx = cx - bx;
+      float vy = cy - by;
+
+   
+      //In the numerator there is the vector product of u and v   
+      double numerator= ux*vx + uy*vy;
+      
+      //In the denominator there are the lengths of u and v (here squared)
+      double uSquared= ux*ux + uy*uy;
+      double vSquared= vx*vx + vy*vy;
+      
+
+      
+      double denomSquared = uSquared * vSquared;
+      
+      if (_saveValues){
+         
+         _map_name_value["Crit3_2DAngleTimesR"] = 0.;
+         
+      }
+      
+      if ( denomSquared > 0.){ //don't divide by 0
+         
+         double cosThetaSquared = numerator * numerator / ( uSquared * vSquared );
+         if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!!
+         double angle = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI;
+         
+         try{
+            
+            SimpleCircle circle ( ax , ay , bx , by , cx , cy );
+            
+            double R = circle.getRadius();
+            
+            double angleTimesR = R * angle;
+            
+            if (_saveValues){
+               
+               _map_name_value["Crit3_2DAngleTimesR"] = angleTimesR;
+               
+            }
+            
+            if ( angleTimesR < _angleMin ) return false;
+            if ( angleTimesR > _angleMax ) return false;
+            
+         }
+         catch( InvalidParameter ){
+            
+            
+         }
+         
+         
+      }
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_2DAngleTimesR::This criterion needs 2 segments with 2 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.h b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.h
new file mode 100644
index 00000000..8025583f
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.h
@@ -0,0 +1,36 @@
+#ifndef Crit3_2DAngleTimesR_h
+#define Crit3_2DAngleTimesR_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the angle in the xy plane between two 2-segments multiplied by the radius of the circle they form
+    */
+   class Crit3_2DAngleTimesR : public ICriterion{
+
+
+
+   public:
+      
+      /**
+       * @param angleMax the maximum angle between 2 2-segments in grad times radius
+       */
+      Crit3_2DAngleTimesR ( float angleMin, float angleMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit3_2DAngleTimesR(){};
+    
+   private:
+      
+      float _angleMin{};
+      float _angleMax{};
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.cc b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.cc
new file mode 100644
index 00000000..bbe254fd
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.cc
@@ -0,0 +1,124 @@
+#include "Criteria/Crit3_3DAngle.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+Crit3_3DAngle::Crit3_3DAngle ( float angleMin, float angleMax ){
+   
+   
+   _cosAngleMin = cos ( angleMax * M_PI / 180. );
+   _cosAngleMax = cos ( angleMin * M_PI / 180. );
+   
+   _name = "Crit3_3DAngle";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+      
+bool Crit3_3DAngle::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   //this is not written very beautiful, because this code gets called often and needs to be fast.
+   //But it's just a simple angle calculation of two vectors cos(alpha) = u*v/|u||v|
+   //
+   //Because of speed, I avoided using stuff like sqrt or cos or something in here.
+   //That's why it may look a bit odd.
+   
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      
+      float ux = bx - ax;
+      float uy = by - ay;
+      float uz = bz - az;
+      
+      float vx = cx - bx;
+      float vy = cy - by;
+      float vz = cz - bz;
+   
+      //In the numerator there is the vector product of u and v   
+      double numerator= ux*vx + uy*vy + uz*vz;
+      
+      //In the denominator there are the lengths of u and v (here squared)
+      double uSquared= ux*ux + uy*uy + uz*uz;
+      double vSquared= vx*vx + vy*vy + vz*vz;
+      
+
+      
+      double denomSquared = uSquared * vSquared;
+      
+      if (_saveValues){
+         
+         _map_name_value["Crit3_3DAngle_cos3DAngleSquared"] =  1.;
+         _map_name_value["Crit3_3DAngle"] = 0.;
+         
+      }
+      
+      if ( denomSquared > 0.){ //don't divide by 0
+      
+         double cosThetaSquared = numerator * numerator / ( uSquared * vSquared );
+         if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!!
+         
+         if (_saveValues){
+            
+            _map_name_value["Crit3_3DAngle_cos3DAngleSquared"] =  cosThetaSquared;
+            _map_name_value["Crit3_3DAngle"] = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI;
+            
+         }
+         
+         if (cosThetaSquared < _cosAngleMin*_cosAngleMin) return false;
+         if (cosThetaSquared > _cosAngleMax*_cosAngleMax) return false;
+      
+      }
+      
+      
+      
+
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_3DAngle::This criterion needs 2 segments with 2 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.h b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.h
new file mode 100644
index 00000000..1c24922d
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.h
@@ -0,0 +1,36 @@
+#ifndef Crit3_3DAngle_h
+#define Crit3_3DAngle_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the angle between two 2-segments
+    */
+   class Crit3_3DAngle : public ICriterion{
+
+
+
+   public:
+      
+      /**
+       * @param angleMax the maximum angle between 2 2-segments in grad
+       */
+      Crit3_3DAngle ( float angleMin, float angleMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit3_3DAngle(){};
+    
+   private:
+      
+      float _cosAngleMin{};
+      float _cosAngleMax{};
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.cc b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.cc
new file mode 100644
index 00000000..ff52c6f5
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.cc
@@ -0,0 +1,136 @@
+#include "Criteria/Crit3_3DAngleTimesR.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+
+using namespace KiTrack;
+
+Crit3_3DAngleTimesR::Crit3_3DAngleTimesR ( float angleMin, float angleMax ){
+   
+   
+   _angleMin = angleMin;
+   _angleMax = angleMax;
+   
+   _name = "Crit3_3DAngleTimesR";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+      
+bool Crit3_3DAngleTimesR::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments
+      
+      
+      
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      
+      float ux = bx - ax;
+      float uy = by - ay;
+      float uz = bz - az;
+      
+      float vx = cx - bx;
+      float vy = cy - by;
+      float vz = cz - bz;
+   
+      //In the numerator there is the vector product of u and v   
+      double numerator= ux*vx + uy*vy + uz*vz;
+      
+      //In the denominator there are the lengths of u and v (here squared)
+      double uSquared= ux*ux + uy*uy + uz*uz;
+      double vSquared= vx*vx + vy*vy + vz*vz;
+      
+
+      
+      double denomSquared = uSquared * vSquared;
+      
+      if (_saveValues){
+         
+         _map_name_value["Crit3_3DAngleTimesR"] = 0.;
+         
+      }
+      
+      if ( denomSquared > 0.){ //don't divide by 0
+         
+         double cosThetaSquared = numerator * numerator / ( uSquared * vSquared );
+         if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!!
+         double angle = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI;
+         
+         
+         try{
+            
+            SimpleCircle circle ( ax , ay , bx , by , cx , cy );
+            
+            double R = circle.getRadius();
+            
+            double angleTimesR = R * angle;
+            
+            if (_saveValues){
+               
+               _map_name_value["Crit3_3DAngleTimesR"] = angleTimesR;
+               
+            }
+            
+            if ( angleTimesR < _angleMin ) return false;
+            if ( angleTimesR > _angleMax ) return false;
+            
+         }
+         catch( InvalidParameter ){
+            
+            
+         }
+         
+         
+      }
+      
+      
+      
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_3DAngleTimesR::This criterion needs 2 segments with 2 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.h b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.h
new file mode 100644
index 00000000..3a366a0d
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.h
@@ -0,0 +1,36 @@
+#ifndef Crit3_3DAngleTimesR_h
+#define Crit3_3DAngleTimesR_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+
+   /** Criterion: the angle between two 2-segments multiplied by the radius of the circle the segments form
+    */
+   class Crit3_3DAngleTimesR : public ICriterion{
+
+
+
+   public:
+      
+      /**
+       * @param angleMax the maximum angle between 2 2-segments in grad times the radius of the circle the segments form
+       */
+      Crit3_3DAngleTimesR ( float angleMin, float angleMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+
+      virtual ~Crit3_3DAngleTimesR(){};
+    
+   private:
+      
+      float _angleMin{};
+      float _angleMax{};
+      
+   };
+
+}
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.cc b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.cc
new file mode 100644
index 00000000..aec9768f
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.cc
@@ -0,0 +1,91 @@
+#include "Criteria/Crit3_ChangeRZRatio.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+
+Crit3_ChangeRZRatio::Crit3_ChangeRZRatio( float minChange , float maxChange ){
+   
+   
+   _ratioChangeMaxSquared = maxChange*maxChange;
+   _ratioChangeMinSquared = minChange*minChange;
+   
+   _name = "Crit3_ChangeRZRatio";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit3_ChangeRZRatio::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+
+
+
+      // The rz ratios squared
+      
+      double ratioSquaredParent = 0.; 
+      if ( az-bz  != 0. ) ratioSquaredParent = ( (ax-bx)*(ax-bx) + (ay-by)*(ay-by) + (az-bz)*(az-bz) ) / ( (az-bz) * ( az-bz ) );
+      
+      double ratioSquaredChild = 0.; 
+      if ( cz-bz  != 0. ) ratioSquaredChild = ( (cx-bx)*(cx-bx) + (cy-by)*(cy-by) + (cz-bz)*(cz-bz) ) / ( (cz-bz) * ( cz-bz ) );
+
+      double ratioOfRZRatioSquared = 0.;
+      
+      if (ratioSquaredChild != 0.) ratioOfRZRatioSquared = ratioSquaredParent / ratioSquaredChild;
+      
+      if (_saveValues) {
+         
+         _map_name_value["Crit3_ChangeRZRatio_ratioOfRZRatioSquared"] =  ratioOfRZRatioSquared;
+         _map_name_value["Crit3_ChangeRZRatio"] = sqrt( ratioOfRZRatioSquared );
+         
+      }
+
+      if ( ratioOfRZRatioSquared > _ratioChangeMaxSquared ) return false;
+      if ( ratioOfRZRatioSquared < _ratioChangeMinSquared ) return false;
+
+
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_ChangeRZRatio::This criterion needs 2 segments with 2 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   
+   return true;
+   
+   
+}
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.h b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.h
new file mode 100644
index 00000000..a218523b
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.h
@@ -0,0 +1,48 @@
+#ifndef Crit2_ChangeRZRatio_h
+#define Crit2_ChangeRZRatio_h
+
+#include "Criteria/ICriterion.h"
+
+
+namespace KiTrack{
+   
+   /** Criterion: the change of the ratio of the distance of two hits over the z distance
+    */
+   class Crit3_ChangeRZRatio : public ICriterion{
+      
+      
+      
+   public:
+      
+      Crit3_ChangeRZRatio ( float minChange , float maxChange );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit3_ChangeRZRatio(){};
+      
+      
+   private:
+      
+      float _ratioChangeMaxSquared{};
+      float _ratioChangeMinSquared{};
+
+      
+      
+   };
+   
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.cc b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.cc
new file mode 100644
index 00000000..2e2486d3
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.cc
@@ -0,0 +1,90 @@
+#include "Criteria/Crit3_IPCircleDist.h"
+
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+using namespace KiTrack;
+
+
+Crit3_IPCircleDist::Crit3_IPCircleDist( float distToCircleMin , float distToCircleMax ){
+   
+   _distToCircleMax  = distToCircleMax;
+   _distToCircleMin  = distToCircleMin;
+   
+   _name = "Crit3_IPCircleDist";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit3_IPCircleDist::areCompatible( Segment* parent , Segment* child ) {
+   
+
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+     
+      float bx = b->getX();
+      float by = b->getY();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+
+
+      try{
+
+         SimpleCircle circle ( ax , ay , bx , by , cx , cy );
+         
+         double x = circle.getCenterX();
+         double y = circle.getCenterY();
+         double R = circle.getRadius();
+         
+         double circleDistToIP = fabs( R - sqrt (x*x+y*y) );
+         
+         if (_saveValues) _map_name_value["Crit3_IPCircleDist"] =  circleDistToIP;
+               
+         if ( circleDistToIP  > _distToCircleMax ) return false;
+         if ( circleDistToIP  < _distToCircleMin ) return false;
+
+      }
+      catch ( InvalidParameter ){
+         
+         
+         if (_saveValues) _map_name_value["Crit3_IPCircleDist"] =  0.;
+         
+      }
+
+
+
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_IPCircleDist::This criterion needs 2 segments with 2 hits each, passed was a "
+       <<  parent->getHits().size() << " hit segment (parent) and a "
+       <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+   }
+   
+   
+   return true;
+   
+   
+}
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.h b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.h
new file mode 100644
index 00000000..08969069
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.h
@@ -0,0 +1,47 @@
+#ifndef Crit2_IPCircleDist_h
+#define Crit2_IPCircleDist_h
+
+#include "Criteria/ICriterion.h"
+
+
+namespace KiTrack{
+   
+   /** Criterion: the distance of the IP from the circle the 3 hits form (in the xy plane)
+    */
+   class Crit3_IPCircleDist : public ICriterion{
+      
+      
+      
+   public:
+      
+      Crit3_IPCircleDist ( float distToCircleMin , float distToCircleMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit3_IPCircleDist(){};
+      
+      
+   private:
+      
+      float _distToCircleMax{};
+      float _distToCircleMin{};
+      
+      
+   };
+   
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.cc b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.cc
new file mode 100644
index 00000000..cbda61ec
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.cc
@@ -0,0 +1,90 @@
+#include "Criteria/Crit3_IPCircleDistTimesR.h"
+
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+using namespace KiTrack;
+
+
+Crit3_IPCircleDistTimesR::Crit3_IPCircleDistTimesR( float distToCircleMin , float distToCircleMax ){
+   
+   _distToCircleMax  = distToCircleMax;
+   _distToCircleMin  = distToCircleMin;
+   
+   _name = "Crit3_IPCircleDistTimesR";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit3_IPCircleDistTimesR::areCompatible( Segment* parent , Segment* child ) {
+   
+
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+     
+      float bx = b->getX();
+      float by = b->getY();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      
+      
+      try{
+         
+         SimpleCircle circle ( ax , ay , bx , by , cx , cy );
+         
+         double x = circle.getCenterX();
+         double y = circle.getCenterY();
+         double R = circle.getRadius();
+         
+         double circleDistToIPTimesR = fabs( R - sqrt (x*x+y*y) ) * R;
+         
+         if (_saveValues) _map_name_value["Crit3_IPCircleDistTimesR"] =  circleDistToIPTimesR;
+               
+         if ( circleDistToIPTimesR  > _distToCircleMax ) return false;
+         if ( circleDistToIPTimesR  < _distToCircleMin ) return false;
+         
+      }
+      catch ( InvalidParameter ){
+         
+         
+         if (_saveValues) _map_name_value["Crit3_IPCircleDistTimesR"] =  0.;
+         
+      }
+      
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_IPCircleDistTimesR::This criterion needs 2 segments with 2 hits each, passed was a "
+       <<  parent->getHits().size() << " hit segment (parent) and a "
+       <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+   }
+   
+   
+   return true;
+   
+   
+}
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.h b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.h
new file mode 100644
index 00000000..3800ed9c
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.h
@@ -0,0 +1,40 @@
+#ifndef Crit3_IPCircleDistTimesR_h
+#define Crit3_IPCircleDistTimesR_h
+
+#include "Criteria/ICriterion.h"
+
+
+namespace KiTrack{
+   
+   /** Criterion: the distance of the circle formed by the two segments from the IP multiplied by R
+    */
+   class Crit3_IPCircleDistTimesR : public ICriterion{
+      
+      
+      
+   public:
+      
+      Crit3_IPCircleDistTimesR ( float distToCircleMin , float distToCircleMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit3_IPCircleDistTimesR(){};
+      
+      
+   private:
+      
+      float _distToCircleMax{};
+      float _distToCircleMin{};
+      
+      
+   };
+   
+}
+
+
+
+
+
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc
new file mode 100644
index 00000000..d2523735
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc
@@ -0,0 +1,93 @@
+#include "Criteria/Crit3_NoZigZag_MV.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "TVector3.h"
+
+
+using namespace KiTrack;
+
+Crit3_NoZigZag_MV::Crit3_NoZigZag_MV ( float prodMin , float prodMax ){
+   
+   
+   _prodMin = prodMin;
+   _prodMax = prodMax;
+   
+   _name = "Crit3_NoZigZag_MV";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit3_NoZigZag_MV::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments
+      
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+
+      double thetaa = a->getTheta();
+      double thetab = b->getTheta();      
+      double thetac = c->getTheta();    
+
+      
+      double angleXY1 = thetac - thetab; //the angle between 2-segments in the xy plane
+      double angleXY2 = thetab - thetaa;
+
+
+      if ( a->isVirtual() ) { angleXY2 = 0 ; }
+      
+      angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY1 > M_PI) angleXY1 -= 2*M_PI;           //to the range from -pi to pi
+
+      angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY2 > M_PI) angleXY2 -= 2*M_PI;           //to the range from -pi to pi
+  
+      
+      // to grad
+      angleXY1 *= 180./M_PI;
+      angleXY2 *= 180./M_PI;
+
+      float prod = angleXY1 * angleXY2; // if the direction of curvature stays the same, both anlges have the same sign-> and therefore the product is positive
+
+
+      //streamlog_out(DEBUG4) << " parent layer " << Layerc << "  theta " << (180*thetac)/M_PI << " child first hit layer " << Layera  << " theta = " << (180*thetaa)/M_PI << " child second hit layer " << Layerb  << " theta = " << (180*thetab)/M_PI << " angleXY1 " << angleXY1 <<  " angleXY2 " << angleXY2 <<  " prod " << prod << std::endl ;
+      
+      
+
+      if (_saveValues) _map_name_value["Crit3_NoZigZag_MV_angle1"] = angleXY1;
+      if (_saveValues) _map_name_value["Crit3_NoZigZag_MV_angle2"] = angleXY2;
+      if (_saveValues) _map_name_value["Crit3_NoZigZag_MV"] = prod;
+      
+      if ( prod < _prodMin ) return false;
+      if ( prod > _prodMax ) return false;
+      
+         
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_NoZigZag_MV::This criterion needs 2 segments with 2 mini-vectors each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   return true;
+   
+   
+   
+}
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.h b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.h
new file mode 100644
index 00000000..3dcf6f89
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.h
@@ -0,0 +1,39 @@
+#ifndef Crit3_NoZigZag_MV_h
+#define Crit3_NoZigZag_MV_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: forbids zig zagging: measure the angles in the xy plane, transpose them to the range from -pi to pi
+    * and multiply: if there is a zigzag, the sign of the angle switches and the product of both angles becomes
+    * negative.
+    */
+   class Crit3_NoZigZag_MV : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param prodMin the minimum product of the two angles in degrees
+       * 
+       * @param prodMax the maxinum product of the two angles in degrees
+       */
+      Crit3_NoZigZag_MV ( float prodMin , float prodMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit3_NoZigZag_MV(){};
+      
+   private:
+      
+      float _prodMin{};
+      float _prodMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT.cc b/Utilities/KiTrack/src/Criteria/Crit3_PT.cc
new file mode 100644
index 00000000..7b22dade
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_PT.cc
@@ -0,0 +1,99 @@
+#include "Criteria/Crit3_PT.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+using namespace KiTrack;
+
+
+Crit3_PT::Crit3_PT( float ptMin , float ptMax , float Bz ){
+   
+   _ptMin = ptMin;
+   _ptMax = ptMax;
+   _Bz = Bz;
+   
+   _name = "Crit3_PT";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit3_PT::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+     
+      float bx = b->getX();
+      float by = b->getY();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+
+
+      try{
+      
+         SimpleCircle circle ( ax , ay , bx , by , cx , cy );
+      
+
+         double R = circle.getRadius();
+         
+         
+         // check if pt is bigger than _ptMin
+         //
+         // |omega| = K*Bz/pt
+         // R = pt / (K*Bz)
+         // pt = R * K *Bz
+         //
+               
+         const double K= 0.00029979; //K depends on the used units
+         
+         double pt = R * K * _Bz;
+            
+         if (_saveValues) _map_name_value["Crit3_PT"] =  pt;
+               
+         if ( pt < _ptMin ) return false;
+         if ( pt > _ptMax ) return false;
+
+         
+      }
+      catch ( InvalidParameter ){
+         
+         if (_saveValues) _map_name_value["Crit3_PT"] =  0.;
+         
+      }
+
+
+
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_PT::This criterion needs 2 segments with 2 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+}
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT.h b/Utilities/KiTrack/src/Criteria/Crit3_PT.h
new file mode 100644
index 00000000..46e4f0f2
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_PT.h
@@ -0,0 +1,48 @@
+#ifndef Crit2_PT_h
+#define Crit2_PT_h
+
+#include "Criteria/ICriterion.h"
+
+
+namespace KiTrack{
+   
+   /** Criterion: the transversal momentum 
+    */
+   class Crit3_PT : public ICriterion{
+      
+      
+      
+   public:
+      
+      Crit3_PT ( float ptMin , float ptMax , float Bz = 3.5 );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit3_PT(){};
+      
+      
+   private:
+      
+      float _ptMin{};
+      float _ptMax{};
+      float _Bz{};
+      
+      
+   };
+   
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc
new file mode 100644
index 00000000..da921091
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc
@@ -0,0 +1,99 @@
+#include "Criteria/Crit3_PT_MV.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+using namespace KiTrack;
+
+
+Crit3_PT_MV::Crit3_PT_MV( float ptMin , float ptMax , float Bz ){
+   
+   _ptMin = ptMin;
+   _ptMax = ptMax;
+   _Bz = Bz;
+   
+   _name = "Crit3_PT_MV";
+   _type = "3Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit3_PT_MV::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = parent-> getHits()[1];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+     
+      float bx = b->getX();
+      float by = b->getY();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+
+
+      try{
+      
+         SimpleCircle circle ( ax , ay , bx , by , cx , cy );
+      
+
+         double R = circle.getRadius();
+         
+         
+         // check if pt is bigger than _ptMin
+         //
+         // |omega| = K*Bz/pt
+         // R = pt / (K*Bz)
+         // pt = R * K *Bz
+         //
+               
+         const double K= 0.00029979; //K depends on the used units
+         
+         double pt = R * K * _Bz;
+            
+         if (_saveValues) _map_name_value["Crit3_PT_MV"] =  pt;
+               
+         if ( pt < _ptMin ) return false;
+         if ( pt > _ptMax ) return false;
+
+         
+      }
+      catch ( InvalidParameter ){
+         
+         if (_saveValues) _map_name_value["Crit3_PT_MV"] =  0.;
+         
+      }
+
+
+
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit3_PT_MV::This criterion needs 2 segments with 2 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+}
diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h
new file mode 100644
index 00000000..86ef0369
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h
@@ -0,0 +1,48 @@
+#ifndef Crit2_PT_MV_h
+#define Crit2_PT_MV_h
+
+#include "Criteria/ICriterion.h"
+
+
+namespace KiTrack{
+   
+   /** Criterion: the transversal momentum 
+    */
+   class Crit3_PT_MV : public ICriterion{
+      
+      
+      
+   public:
+      
+      Crit3_PT_MV ( float ptMin , float ptMax , float Bz = 3.5 );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit3_PT_MV(){};
+      
+      
+   private:
+      
+      float _ptMin{};
+      float _ptMax{};
+      float _Bz{};
+      
+      
+   };
+   
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.cc
new file mode 100644
index 00000000..b406bf88
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.cc
@@ -0,0 +1,101 @@
+#include "Criteria/Crit4_2DAngleChange.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "TVector3.h"
+
+
+using namespace KiTrack;
+
+Crit4_2DAngleChange::Crit4_2DAngleChange ( float changeMin , float changeMax ){
+   
+   
+   _changeMax = changeMax;
+   _changeMin = changeMin;
+   
+   _name = "Crit4_2DAngleChange";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit4_2DAngleChange::areCompatible( Segment* parent , Segment* child ) {
+    
+      
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+      
+      
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+      float dz = d->getZ();
+      
+
+      
+      TVector3 outerVec  (bx-ax , by-ay , bz-az );
+      TVector3 middleVec (cx-bx , cy-by , cz-bz );
+      TVector3 innerVec  (dx-cx , dy-cy , dz-cz );
+      
+  
+      
+      
+      double angleXY1 = outerVec.Phi()-middleVec.Phi(); //the angle between 2-segments in the xy plane
+      double angleXY2 = middleVec.Phi()-innerVec.Phi();
+      
+      angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY1 > M_PI) angleXY1 -= 2*M_PI;           //to the range from -pi to pi
+
+      angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY2 > M_PI) angleXY2 -= 2*M_PI;           //to the range from -pi to pi
+  
+      
+      float ratioOf2DAngles = angleXY1 / angleXY2 ;
+
+      if (_saveValues) _map_name_value["Crit4_2DAngleChange"] = ratioOf2DAngles;
+      
+      if ( ratioOf2DAngles > _changeMax ) return false;    
+      if ( ratioOf2DAngles < _changeMin ) return false;
+      
+         
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_2DAngleChange::This criterion needs 2 segments with 3 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.h b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.h
new file mode 100644
index 00000000..c3bcb65d
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.h
@@ -0,0 +1,35 @@
+#ifndef Crit4_2DAngleChange_h
+#define Crit4_2DAngleChange_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: change of the angle (in the xy plane) between segments in the xy plane
+    */
+   class Crit4_2DAngleChange : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param changeMax 
+       */
+      Crit4_2DAngleChange ( float changeMin , float changeMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_2DAngleChange(){};
+      
+   private:
+      
+      float _changeMin{};
+      float _changeMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.cc
new file mode 100644
index 00000000..d6a8c5da
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.cc
@@ -0,0 +1,101 @@
+#include "Criteria/Crit4_3DAngleChange.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "TVector3.h"
+
+
+using namespace KiTrack;
+
+Crit4_3DAngleChange::Crit4_3DAngleChange ( float changeMin , float changeMax ){
+   
+   
+   _changeMax = changeMax;
+   _changeMin = changeMin;
+   
+   _name = "Crit4_3DAngleChange";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit4_3DAngleChange::areCompatible( Segment* parent , Segment* child ) {
+    
+      
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+      float dz = d->getZ();
+      
+
+      
+      TVector3 outerVec  (bx-ax , by-ay , bz-az );
+      TVector3 middleVec (cx-bx , cy-by , cz-bz );
+      TVector3 innerVec  (dx-cx , dy-cy , dz-cz );
+      
+  
+      
+      
+      double angleXY1 = outerVec.Angle( middleVec ); 
+      double angleXY2 = middleVec.Angle( innerVec );
+      
+      angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY1 > M_PI) angleXY1 -= 2*M_PI;           //to the range from -pi to pi
+
+      angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY2 > M_PI) angleXY2 -= 2*M_PI;           //to the range from -pi to pi
+  
+      
+      float ratioOf3DAngles = angleXY1 / angleXY2 ;
+
+      if (_saveValues) _map_name_value["Crit4_3DAngleChange"] = ratioOf3DAngles;
+      
+      if ( ratioOf3DAngles > _changeMax ) return false;    
+      if ( ratioOf3DAngles < _changeMin ) return false;
+      
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_3DAngleChange::This criterion needs 2 segments with 3 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.h b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.h
new file mode 100644
index 00000000..84351869
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.h
@@ -0,0 +1,35 @@
+#ifndef Crit4_3DAngleChange_h
+#define Crit4_3DAngleChange_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: change of the angle between segments
+    */
+   class Crit4_3DAngleChange : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param changeMax 
+       */
+      Crit4_3DAngleChange ( float changeMin , float changeMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_3DAngleChange(){};
+      
+   private:
+      
+      float _changeMin{};
+      float _changeMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.cc b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.cc
new file mode 100644
index 00000000..ade7136d
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.cc
@@ -0,0 +1,124 @@
+#include "Criteria/Crit4_3DAngleChangeNormed.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "TVector3.h"
+#include "Criteria/SimpleCircle.h"
+
+
+using namespace KiTrack;
+
+Crit4_3DAngleChangeNormed::Crit4_3DAngleChangeNormed ( float changeMin , float changeMax ){
+   
+   
+   _changeMax = changeMax;
+   _changeMin = changeMin;
+   
+   _name = "Crit4_3DAngleChangeNormed";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit4_3DAngleChangeNormed::areCompatible( Segment* parent , Segment* child ) {
+   
+
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+      
+      
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+      float dz = d->getZ();
+      
+
+      
+      TVector3 outerVec  (bx-ax , by-ay , bz-az );
+      TVector3 middleVec (cx-bx , cy-by , cz-bz );
+      TVector3 innerVec  (dx-cx , dy-cy , dz-cz );
+      
+      
+      
+      
+      double angleXY1 = outerVec.Angle( middleVec ); 
+      double angleXY2 = middleVec.Angle( innerVec );
+      
+      angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY1 > M_PI) angleXY1 -= 2*M_PI;           //to the range from -pi to pi
+      
+      angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY2 > M_PI) angleXY2 -= 2*M_PI;           //to the range from -pi to pi
+      
+      
+      try{
+         
+         SimpleCircle circle1 ( ax , ay , bx , by , cx , cy );
+         SimpleCircle circle2 ( bx , by , cx , cy , dx , dy );
+         
+         
+         float R = ( circle1.getRadius() + circle2.getRadius() ) / 2.;
+         
+         
+         float ratioOf3DAngles = angleXY1 / angleXY2 ;
+         
+         float ratioNormed = ( (ratioOf3DAngles -1. ) * R )  + 1;
+         
+         if (_saveValues) _map_name_value["Crit4_3DAngleChangeNormed"] = ratioNormed;
+         
+         if ( ratioNormed > _changeMax ) return false;    
+         if ( ratioNormed < _changeMin ) return false;
+         
+      }
+      catch ( InvalidParameter ){
+         
+         if (_saveValues) _map_name_value["Crit4_3DAngleChangeNormed"] = 0.;
+         
+         
+      }
+      
+      
+      
+      
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_3DAngleChangeNormed::This criterion needs 2 segments with 3 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.h b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.h
new file mode 100644
index 00000000..691d0060
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.h
@@ -0,0 +1,35 @@
+#ifndef Crit4_3DAngleChangeNormed_h
+#define Crit4_3DAngleChangeNormed_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: check for the change of the 3D angle and normalise it with R
+    */
+   class Crit4_3DAngleChangeNormed : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param changeMax 
+       */
+      Crit4_3DAngleChangeNormed ( float changeMin , float changeMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_3DAngleChangeNormed(){};
+      
+   private:
+      
+      float _changeMin{};
+      float _changeMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.cc b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.cc
new file mode 100644
index 00000000..2f0ecbac
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.cc
@@ -0,0 +1,110 @@
+#include "Criteria/Crit4_DistOfCircleCenters.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+
+using namespace KiTrack;
+
+Crit4_DistOfCircleCenters::Crit4_DistOfCircleCenters ( float distMin , float distMax ){
+   
+   
+   _distMax = distMax;
+   _distMin = distMin;
+   
+   _name = "Crit4_DistOfCircleCenters";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+   
+}
+
+
+
+bool Crit4_DistOfCircleCenters::areCompatible( Segment* parent , Segment* child ) {
+    
+   
+   
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+
+      
+      
+      float ax = a->getX();
+      float ay = a->getY();
+//       float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+//       float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+//       float cz = c->getZ();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+//       float dz = d->getZ();
+      
+      
+      
+      try{
+      
+         SimpleCircle circle1 ( ax , ay , bx , by , cx , cy );
+         SimpleCircle circle2 ( bx , by , cx , cy , dx , dy );
+
+         
+         float X1 = circle1.getCenterX();
+         float Y1 = circle1.getCenterY();
+
+         float X2 = circle2.getCenterX();
+         float Y2 = circle2.getCenterY();
+         
+         
+         float distOfCircleCenters = sqrt( (X2-X1)*(X2-X1) + (Y2-Y1)*(Y2-Y1) );
+         
+         if (_saveValues) _map_name_value["Crit4_DistOfCircleCenters"] = distOfCircleCenters;
+         
+         
+         if ( distOfCircleCenters > _distMax ) return false;
+         if ( distOfCircleCenters < _distMin ) return false;
+      
+      }
+      catch ( InvalidParameter ){
+         
+         if (_saveValues) _map_name_value["Crit4_DistOfCircleCenters"] = 0.;
+         
+         
+      }
+      
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_DistOfCircleCenters::This criterion needs 2 segments with 3 hits each, passed was a "
+        <<  parent->getHits().size() << " hit segment (parent) and a "
+        <<  child->getHits().size() <<" hit segment (child).";
+      
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.h b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.h
new file mode 100644
index 00000000..c7d4a943
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.h
@@ -0,0 +1,35 @@
+#ifndef Crit4_DistOfCircleCenters_h
+#define Crit4_DistOfCircleCenters_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: make circles from the semgments and measure the distances of their centers
+    */
+   class Crit4_DistOfCircleCenters : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param distMax 
+       */
+      Crit4_DistOfCircleCenters ( float distMin , float distMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_DistOfCircleCenters(){};
+      
+   private:
+      
+      float _distMax{};
+      float _distMin{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.cc b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.cc
new file mode 100644
index 00000000..b993f45e
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.cc
@@ -0,0 +1,119 @@
+#include "Criteria/Crit4_DistToExtrapolation.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+#include "TVector3.h"
+
+
+
+using namespace KiTrack;
+
+Crit4_DistToExtrapolation::Crit4_DistToExtrapolation ( float distMin , float distMax ){
+   
+   
+   _distMin = distMin;
+   _distMax = distMax;
+   
+   _name = "Crit4_DistToExtrapolation";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit4_DistToExtrapolation::areCompatible( Segment* parent , Segment* child ) {
+    
+   
+   
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+//       float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+      float dz = d->getZ();
+      
+      try{
+      
+         SimpleCircle circle ( ax , ay , bx , by , cx , cy );
+
+         
+         double centerX = circle.getCenterX();
+         double centerY = circle.getCenterY();
+         double R = circle.getRadius();
+         
+         TVector3 u ( bx - centerX , by - centerY , bz );
+         TVector3 v ( cx - centerX , cy - centerY , cz );
+         
+         
+         double deltaPhiParent = v.Phi() - u.Phi(); //angle in xy plane from center of circle, between point 2 and 3
+         
+         // use this angle and the distance to the next layer to extrapolate
+         double zDistParent = fabs( cz - bz );
+         double zDistChild  = fabs( dz - cz );
+         
+         double deltaPhiChild = deltaPhiParent * zDistChild / zDistParent ;
+         
+         double phiChild = v.Phi() + deltaPhiChild;
+         
+         double xChildPred = centerX + R* cos(phiChild);
+         double yChildPred = centerY + R* sin(phiChild);
+         
+         
+         double DistToPrediction = sqrt ( ( xChildPred- dx )*( xChildPred- dx ) + ( yChildPred- dy )*( yChildPred- dy ) );
+         double distNormed = DistToPrediction / zDistChild;   
+         
+         if (_saveValues) _map_name_value["Crit4_DistToExtrapolation"] = distNormed;
+         
+         if ( distNormed > _distMax ) return false;
+         if ( distNormed < _distMin ) return false;
+         
+      }
+      catch ( InvalidParameter ){
+         
+         if (_saveValues) _map_name_value["Crit4_DistToExtrapolation"] = -1.;
+      
+      }
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_DistToExtrapolation::This criterion needs 2 segments with 3 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.h b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.h
new file mode 100644
index 00000000..726e4434
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.h
@@ -0,0 +1,37 @@
+#ifndef Crit4_DistToExtrapolation_h
+#define Crit4_DistToExtrapolation_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: use the first 3 hits to extrapolate the location in xy for a given z of the last hit.
+    * Then measure the distance from the extrapolation to the hit. (Also divide by the z distance to the last hit,
+    * in order to take into account that with farther distances the accuracy drops)
+    */
+   class Crit4_DistToExtrapolation : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param distMax 
+       */
+      Crit4_DistToExtrapolation ( float distMin , float distMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_DistToExtrapolation(){};
+      
+   private:
+      
+      float _distMin{};
+      float _distMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.cc b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.cc
new file mode 100644
index 00000000..3f00d4be
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.cc
@@ -0,0 +1,108 @@
+#include "Criteria/Crit4_NoZigZag.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "TVector3.h"
+
+
+using namespace KiTrack;
+
+Crit4_NoZigZag::Crit4_NoZigZag ( float prodMin , float prodMax ){
+   
+   
+   _prodMin = prodMin;
+   _prodMax = prodMax;
+   
+   _name = "Crit4_NoZigZag";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit4_NoZigZag::areCompatible( Segment* parent , Segment* child ) {
+   
+   
+   
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+      float dz = d->getZ();
+      
+
+      
+      TVector3 outerVec  (bx-ax , by-ay , bz-az );
+      TVector3 middleVec (cx-bx , cy-by , cz-bz );
+      TVector3 innerVec  (dx-cx , dy-cy , dz-cz );
+      
+  
+      
+      
+      double angleXY1 = outerVec.Phi()-middleVec.Phi(); //the angle between 2-segments in the xy plane
+      double angleXY2 = middleVec.Phi()-innerVec.Phi();
+      
+      angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY1 > M_PI) angleXY1 -= 2*M_PI;           //to the range from -pi to pi
+
+      angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI );    //to the range from 0 to 2pi 
+      if (angleXY2 > M_PI) angleXY2 -= 2*M_PI;           //to the range from -pi to pi
+  
+      
+      // to grad
+      angleXY1 *= 180./M_PI;
+      angleXY2 *= 180./M_PI;
+
+      float prod = angleXY1 * angleXY2; // if the direction of curvature stays the same, both anlges have the same sign-> and therefore the product is positive
+      
+      if (_saveValues) _map_name_value["Crit4_NoZigZag_angle1"] = angleXY1;
+      if (_saveValues) _map_name_value["Crit4_NoZigZag_angle2"] = angleXY2;
+      if (_saveValues) _map_name_value["Crit4_NoZigZag"] = prod;
+      
+      if ( prod < _prodMin ) return false;
+      if ( prod > _prodMax ) return false;
+      
+         
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_NoZigZag::This criterion needs 2 segments with 3 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.h b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.h
new file mode 100644
index 00000000..5ca64cee
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.h
@@ -0,0 +1,39 @@
+#ifndef Crit4_NoZigZag_h
+#define Crit4_NoZigZag_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: forbids zig zagging: measure the angles in the xy plane, transpose them to the range from -pi to pi
+    * and multiply: if there is a zigzag, the sign of the angle switches and the product of both angles becomes
+    * negative.
+    */
+   class Crit4_NoZigZag : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param prodMin the minimum product of the two angles in degrees
+       * 
+       * @param prodMax the maxinum product of the two angles in degrees
+       */
+      Crit4_NoZigZag ( float prodMin , float prodMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_NoZigZag(){};
+      
+   private:
+      
+      float _prodMin{};
+      float _prodMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.cc
new file mode 100644
index 00000000..e6c4db21
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.cc
@@ -0,0 +1,120 @@
+#include "Criteria/Crit4_PhiZRatioChange.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+#include "TVector3.h"
+
+
+
+using namespace KiTrack;
+
+Crit4_PhiZRatioChange::Crit4_PhiZRatioChange ( float changeMin , float changeMax ){
+   
+   
+   _changeMin = changeMin;
+   _changeMax = changeMax;
+   
+   _name = "Crit4_PhiZRatioChange";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit4_PhiZRatioChange::areCompatible( Segment* parent , Segment* child ) {
+    
+   
+   
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+//       float az = a->getZ();
+      
+      float bx = b->getX();
+      float by = b->getY();
+      float bz = b->getZ();
+      
+      float cx = c->getX();
+      float cy = c->getY();
+      float cz = c->getZ();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+      float dz = d->getZ();
+      
+      try{
+      
+         SimpleCircle circle1 ( ax , ay , bx , by , cx , cy );
+         SimpleCircle circle2 ( bx , by , cx , cy , dx , dy );
+         
+         
+         float X1 = circle1.getCenterX();
+         float Y1 = circle1.getCenterY();
+         float X2 = circle2.getCenterX();
+         float Y2 = circle2.getCenterY();
+         
+         
+         
+         TVector3 u ( bx - X1, by - Y1 , 0.); //vector from center of circle to point
+         TVector3 v ( cx - X1, cy - Y1 , 0.);
+         float zDist1 = fabs( cz - bz );
+         float phi1 = u.Angle( v );
+         float phiZRatio1 = phi1 / zDist1;
+         
+         TVector3 s ( cx - X2, cy - Y2 , 0.); //vector from center of circle to point
+         TVector3 t ( dx - X2, dy - Y2 , 0.);
+         float zDist2 = fabs( dz - cz );
+         float phi2 = s.Angle( t );
+         float phiZRatio2 = phi2 / zDist2;
+         
+         
+         float ratioOfPhiZRatio = phiZRatio1 / phiZRatio2;
+         
+         if (_saveValues) _map_name_value["Crit4_PhiZRatioChange"] = ratioOfPhiZRatio;
+         
+         
+            
+         if ( ratioOfPhiZRatio > _changeMax ) return false;    
+         if ( ratioOfPhiZRatio < _changeMin ) return false;
+         
+      }
+      catch ( InvalidParameter ){
+       
+         if (_saveValues) _map_name_value["Crit4_PhiZRatioChange"] = 1.;
+         
+      }
+      
+         
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_PhiZRatioChange::This criterion needs 2 segments with 3 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.h b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.h
new file mode 100644
index 00000000..d8f41b1c
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.h
@@ -0,0 +1,35 @@
+#ifndef Crit4_PhiZRatioChange_h
+#define Crit4_PhiZRatioChange_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: check for the change of \f$ \frac{\phi}{Z} \f$. (\f$ \phi \f$ = angle in the circle formed by the hits)
+    */
+   class Crit4_PhiZRatioChange : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param changeMax 
+       */
+      Crit4_PhiZRatioChange ( float changeMin , float changeMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_PhiZRatioChange(){};
+      
+   private:
+      
+      float _changeMin{};
+      float _changeMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_RChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_RChange.cc
new file mode 100644
index 00000000..ea7e4257
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_RChange.cc
@@ -0,0 +1,97 @@
+#include "Criteria/Crit4_RChange.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "Criteria/SimpleCircle.h"
+
+
+
+using namespace KiTrack;
+
+Crit4_RChange::Crit4_RChange ( float changeMin , float changeMax ){
+   
+   
+   _changeMin = changeMin;
+   _changeMax = changeMax;
+   
+   _name = "Crit4_RChange";
+   _type = "4Hit";
+   
+   _saveValues = false;
+   
+}
+
+
+
+bool Crit4_RChange::areCompatible( Segment* parent , Segment* child ) {
+    
+   
+   
+   if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments
+      
+
+
+      IHit* a = child->getHits()[0];
+      IHit* b = child->getHits()[1];
+      IHit* c = child->getHits()[2];
+      IHit* d = parent-> getHits()[2];
+      
+      float ax = a->getX();
+      float ay = a->getY();
+      
+      float bx = b->getX();
+      float by = b->getY();
+       
+      float cx = c->getX();
+      float cy = c->getY();
+      
+      float dx = d->getX();
+      float dy = d->getY();
+      
+      try{
+      
+         SimpleCircle circle1 ( ax , ay , bx , by , cx , cy );
+         SimpleCircle circle2 ( bx , by , cx , cy , dx , dy );
+         
+         float R1 = circle1.getRadius();
+         float R2 = circle2.getRadius();
+         
+         float ratioOfR = 1.;
+         if (R2 > 0) ratioOfR = R1/R2;
+         
+         if (_saveValues) _map_name_value["Crit4_RChange"] = ratioOfR;
+         
+         
+            
+         if ( ratioOfR > _changeMax ) return false;    
+         if ( ratioOfR < _changeMin ) return false;
+         
+      }
+      catch ( InvalidParameter ){
+         
+         if (_saveValues) _map_name_value["Crit4_RChange"] = 1.;
+         
+      }
+      
+   }
+   else{
+      
+      std::stringstream s;
+      s << "Crit4_RChange::This criterion needs 2 segments with 3 hits each, passed was a "
+      <<  parent->getHits().size() << " hit segment (parent) and a "
+      <<  child->getHits().size() << " hit segment (child).";
+      
+      
+      throw BadSegmentLength( s.str() );
+      
+      
+   }
+   
+   
+   return true;
+   
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/Crit4_RChange.h b/Utilities/KiTrack/src/Criteria/Crit4_RChange.h
new file mode 100644
index 00000000..3b4c1d8b
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Crit4_RChange.h
@@ -0,0 +1,35 @@
+#ifndef Crit4_RChange_h
+#define Crit4_RChange_h
+
+
+#include "Criteria/ICriterion.h"
+
+namespace KiTrack{
+   
+   /** Criterion: check for the change of the radii of the circles that can be made from the 3-hit segments
+    */
+   class Crit4_RChange : public ICriterion{
+      
+      
+      
+   public:
+      
+      /**
+       * @param changeMax 
+       */
+      Crit4_RChange ( float changeMin , float changeMax );
+      
+      virtual bool areCompatible( Segment* parent , Segment* child );
+      
+      virtual ~Crit4_RChange(){};
+      
+   private:
+      
+      float _changeMin{};
+      float _changeMax{};
+      
+   };
+   
+}
+
+#endif
diff --git a/Utilities/KiTrack/src/Criteria/Criteria.cc b/Utilities/KiTrack/src/Criteria/Criteria.cc
new file mode 100644
index 00000000..f8ea29a2
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/Criteria.cc
@@ -0,0 +1,278 @@
+#include "Criteria/Criteria.h"
+#include "Criteria/ICriterion.h"
+
+#include "Criteria/Crit2_RZRatio.h"
+#include "Criteria/Crit2_StraightTrackRatio.h"
+#include "Criteria/Crit2_DeltaPhi.h"
+#include "Criteria/Crit2_HelixWithIP.h"
+#include "Criteria/Crit2_DeltaRho.h"                                                                                                                                                                        
+#include "Criteria/Crit3_ChangeRZRatio.h"
+#include "Criteria/Crit3_PT.h"
+#include "Criteria/Crit3_2DAngle.h"
+#include "Criteria/Crit3_2DAngleTimesR.h"
+#include "Criteria/Crit3_3DAngle.h"
+#include "Criteria/Crit3_3DAngleTimesR.h"
+#include "Criteria/Crit3_IPCircleDist.h"
+#include "Criteria/Crit3_IPCircleDistTimesR.h"
+                                                                                                                                                                       
+#include "Criteria/Crit4_2DAngleChange.h"
+#include "Criteria/Crit4_3DAngleChange.h"
+#include "Criteria/Crit4_3DAngleChangeNormed.h"
+#include "Criteria/Crit4_DistToExtrapolation.h"
+#include "Criteria/Crit4_PhiZRatioChange.h"
+#include "Criteria/Crit4_DistOfCircleCenters.h"
+#include "Criteria/Crit4_NoZigZag.h"
+#include "Criteria/Crit4_RChange.h"                                                                                                                                                                        
+// Criteria for Mini - Vector based Cellular Automaton for VXD
+#include "Criteria/Crit2_DeltaPhi_MV.h"
+#include "Criteria/Crit2_Distance_MV.h"
+#include "Criteria/Crit2_DeltaTheta_MV.h"
+#include "Criteria/Crit3_NoZigZag_MV.h"
+#include "Criteria/Crit3_PT_MV.h"
+
+using namespace KiTrack;
+
+std::set< std::string > Criteria::getAllCriteriaNames(){
+
+   
+   std::set< std::string > critNames;
+   
+   critNames.insert( "Crit2_RZRatio" );
+   critNames.insert( "Crit2_StraightTrackRatio" );
+   critNames.insert( "Crit2_DeltaPhi" );
+   critNames.insert( "Crit2_HelixWithIP" );
+   critNames.insert( "Crit2_DeltaRho" );
+
+   critNames.insert( "Crit3_ChangeRZRatio" );
+   critNames.insert( "Crit3_PT" );
+   critNames.insert( "Crit3_2DAngle" );
+   critNames.insert( "Crit3_2DAngleTimesR" );
+   critNames.insert( "Crit3_3DAngle" );
+   critNames.insert( "Crit3_3DAngleTimesR" );
+   critNames.insert( "Crit3_IPCircleDist" );
+   critNames.insert( "Crit3_IPCircleDistTimesR" );
+   
+
+   critNames.insert( "Crit4_2DAngleChange" );
+   critNames.insert( "Crit4_3DAngleChange" );
+   critNames.insert( "Crit4_3DAngleChangeNormed" );
+   critNames.insert( "Crit4_DistToExtrapolation" );
+   critNames.insert( "Crit4_PhiZRatioChange" );
+   critNames.insert( "Crit4_DistOfCircleCenters" );
+   critNames.insert( "Crit4_NoZigZag" );
+   critNames.insert( "Crit4_RChange" );
+
+   // MiniVector based Cellular Automaton for VXD
+
+   critNames.insert( "Crit2_DeltaPhi_MV" );
+   critNames.insert( "Crit2_Distance_MV" );
+   critNames.insert( "Crit2_DeltaTheta_MV" ); 
+   critNames.insert( "Crit3_NoZigZag_MV" );
+   critNames.insert( "Crit3_PT_MV" );
+
+   return critNames;
+
+}
+
+
+std::set < std::string > Criteria::getTypes(){
+ 
+   std::set< std::string > critNames = getAllCriteriaNames();
+   std::set< std::string > types;
+   
+   std::set< std::string >::iterator it;
+   
+   
+   for( it = critNames.begin(); it != critNames.end(); it++ ){
+      
+      
+      ICriterion* crit = Criteria::createCriterion( *it );
+      
+      types.insert( crit->getType() );
+      
+      delete crit;
+      
+      
+   }
+   
+   return types;
+   
+   
+}
+
+
+std::set< std::string > Criteria::getCriteriaNames( std::string type ){
+   
+   
+   std::set< std::string > criteria;
+   std::set< std::string > critNames = getAllCriteriaNames();
+   
+   
+   std::set< std::string >::iterator it;
+   
+   for( it = critNames.begin(); it != critNames.end(); it++ ){
+      
+      
+      ICriterion* crit = Criteria::createCriterion( *it );
+      
+      if ( crit->getType() == type ) criteria.insert( *it );
+      
+      delete crit;
+      
+   }
+
+   return criteria;
+      
+    
+   
+   
+}
+
+
+ICriterion* Criteria::createCriterion( std::string critName, float min , float max ) {
+   
+   
+   
+   if ( critName == "Crit2_RZRatio" ) return ( new Crit2_RZRatio( min , max ) );
+   
+   else if ( critName == "Crit2_StraightTrackRatio" ) return ( new Crit2_StraightTrackRatio( min , max ) );
+   
+   else if ( critName == "Crit2_DeltaPhi" ) return ( new Crit2_DeltaPhi( min , max ) );
+   
+   else if ( critName == "Crit2_HelixWithIP" ) return ( new Crit2_HelixWithIP( min , max ) );
+   
+   else if ( critName == "Crit2_DeltaRho" ) return ( new Crit2_DeltaRho( min , max ) );
+   
+   else if ( critName == "Crit3_ChangeRZRatio" ) return ( new Crit3_ChangeRZRatio( min , max ) );
+   
+   else if ( critName == "Crit3_PT" ) return ( new Crit3_PT( min , max ) );
+   
+   else if ( critName == "Crit3_2DAngle" ) return ( new Crit3_2DAngle( min , max ) );
+   
+   else if ( critName == "Crit3_2DAngleTimesR" ) return ( new Crit3_2DAngleTimesR( min , max ) );
+   
+   else if ( critName == "Crit3_3DAngle" ) return ( new Crit3_3DAngle( min , max ) );
+   
+   else if ( critName == "Crit3_3DAngleTimesR" ) return ( new Crit3_3DAngleTimesR( min , max ) );
+   
+   else if ( critName == "Crit3_IPCircleDist" ) return ( new Crit3_IPCircleDist( min , max ) );
+   
+   else if ( critName == "Crit3_IPCircleDistTimesR" ) return ( new Crit3_IPCircleDistTimesR( min , max ) );
+   
+   else if ( critName == "Crit4_2DAngleChange" ) return ( new Crit4_2DAngleChange( min , max ) );
+   
+   else if ( critName == "Crit4_3DAngleChange" ) return ( new Crit4_3DAngleChange( min , max ) );
+   
+   else if ( critName == "Crit4_3DAngleChangeNormed" ) return ( new Crit4_3DAngleChangeNormed( min , max ) );
+   
+   else if ( critName == "Crit4_DistToExtrapolation" ) return ( new Crit4_DistToExtrapolation( min , max ) );
+   
+   else if ( critName == "Crit4_PhiZRatioChange" ) return ( new Crit4_PhiZRatioChange( min , max ) );
+   
+   else if ( critName == "Crit4_DistOfCircleCenters" ) return ( new Crit4_DistOfCircleCenters( min , max ) );
+   
+   else if ( critName == "Crit4_NoZigZag" ) return ( new Crit4_NoZigZag( min , max ) );
+   
+   else if ( critName == "Crit4_RChange" ) return ( new Crit4_RChange( min , max ) );
+
+   // Mini-Vector based
+
+   else if ( critName == "Crit2_DeltaPhi_MV" ) return ( new Crit2_DeltaPhi_MV( min , max ) );
+
+   else if ( critName == "Crit2_Distance_MV" ) return ( new Crit2_Distance_MV( min , max ) );
+
+   else if ( critName == "Crit2_DeltaTheta_MV" ) return ( new Crit2_DeltaTheta_MV( min , max ) );
+
+   else if ( critName == "Crit3_NoZigZag_MV" ) return ( new Crit3_NoZigZag_MV( min , max ) );
+
+   else if ( critName == "Crit3_PT_MV" ) return ( new Crit3_PT_MV( min , max ) );
+   
+   else {
+      
+      std::string s = "Criteria::The criterion \"" + critName + 
+                      "\" is not known. Make sure the class Criteria has this criterion listed in the createCriterion method";
+      
+      throw UnknownCriterion( s );
+      
+   }
+
+      
+      
+    
+}
+
+
+
+std::vector< std::string > Criteria::getAllCriteriaNamesVec(){
+   
+   std::vector < std::string > allCriteriaNamesVec;
+   std::set< std::string > critNames = getAllCriteriaNames();
+   
+   
+   std::set< std::string >::iterator it;
+   
+   for( it = critNames.begin(); it != critNames.end(); it++ ){
+   
+      
+      allCriteriaNamesVec.push_back( *it );
+      
+   }
+   
+   return allCriteriaNamesVec;
+   
+}
+
+
+void Criteria::getLeftRight( std::string critName, float & left, float & right ){
+   
+   
+   if ( critName == "Crit2_RZRatio" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit2_RZRatio" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit2_StraightTrackRatio" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit2_DeltaPhi" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit2_HelixWithIP" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit2_DeltaRho" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit3_ChangeRZRatio" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit3_PT" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit3_2DAngle" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit3_2DAngleTimesR" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit3_3DAngle" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit3_3DAngleTimesR" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit3_IPCircleDist" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit3_IPCircleDistTimesR" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit4_2DAngleChange" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit4_3DAngleChange" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit4_3DAngleChangeNormed" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit4_DistToExtrapolation" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit4_PhiZRatioChange" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit4_DistOfCircleCenters" ) { left = 0.; right = 1.; }
+   
+   else if ( critName == "Crit4_NoZigZag" ) { left = 0.5; right = 0.5; }
+   
+   else if ( critName == "Crit4_RChange" ) { left = 0.5; right = 0.5; }
+   
+   else { left = 0.5; right = 0.5; }
+   
+ 
+}
+   
+
diff --git a/Utilities/KiTrack/src/Criteria/SimpleCircle.cc b/Utilities/KiTrack/src/Criteria/SimpleCircle.cc
new file mode 100644
index 00000000..77d1a8bd
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/SimpleCircle.cc
@@ -0,0 +1,90 @@
+#include "Criteria/SimpleCircle.h"
+
+#include <cmath>
+#include <sstream>
+
+
+
+using namespace KiTrack;
+
+SimpleCircle::SimpleCircle( double x1 , double y1 , double x2 , double y2 , double x3, double y3 ) {
+  
+  
+   
+  // 1. check if they are not in a line, i.e. the slopes are parallel (or two or more points are identical)
+  
+  if ( (x2 -x1)*(y3 - y2) == (x3 - x2)*(y2 - y1) ){
+     
+     
+     std::stringstream s;
+     
+     s << "SimpleCircle::The 3 points are on one line in xy-space: x1 = "
+       <<  x1
+       << ", y1 = " << y1
+       << ", x2 = " << x2
+       << ", y2 = " << y2
+       << ", x3 = " << x3
+       << ", y3 = " << y3;
+                     
+     throw InvalidParameter( s.str() );
+     
+     
+  }
+  
+
+   _R = 0;
+   _centerX = 0.;
+   _centerY = 0.;
+
+
+   _x1 = x1;
+   _y1 = y1;
+   _x2 = x2;
+   _y2 = y2;
+   _x3 = x3;
+   _y3 = y3;
+               
+               
+   //check if x1 and x2 or x2 and x3 are equal. If they are, swap them around, so that those are not 0. (or else the slopes get infinite)
+   // note that x1==x2==x3 is not possible as they would need to be on a line for that (and parallel, which we checked)
+   
+   if ( x1 == x2 ) {  // x1 and x2 have the same x --> we swap the points around (still it stays the same circle) so the 
+                        // that they are now x1 and x3. because the line x1->x3 (i.e. its slope) isn't used in the calculations --> we don't care if it's zero.
+      
+
+      _x2 = x3;
+      _y2 = y3;
+      _x3 = x2;
+      _y3 = y2;
+      
+   }
+   else if ( x2 == x3 ) {  // x1 and x2 have the same x --> we swap the points around (still it stays the same circle) so the 
+                        // that they are now x1 and x3. because the line x1->x3 (i.e. its slope) isn't used in the calculations --> we don't care if it's zero.
+      
+
+      _x2 = x1;
+      _y2 = y1;
+      _x1 = x2;
+      _y1 = y2;
+      
+   }
+   
+   
+   
+   double ma = (_y2-_y1)/(_x2-_x1); //slope
+   double mb = (_y3-_y2)/(_x3-_x2);
+               
+               
+   _centerX = ( ma*mb*(_y1-_y3) + mb*(_x1+_x2) - ma*(_x2+_x3) )/( 2.*(mb-ma));
+   _centerY = (-1./ma) * ( _centerX - (_x1+_x2)/2. ) + (_y1+_y2)/2;
+            
+   _R = sqrt (( _x1 - _centerX )*( _x1 - _centerX ) + ( _y1 - _centerY )*( _y1 - _centerY ));
+
+
+
+  
+  
+  
+  
+}
+
diff --git a/Utilities/KiTrack/src/Criteria/SimpleCircle.h b/Utilities/KiTrack/src/Criteria/SimpleCircle.h
new file mode 100644
index 00000000..2c7d2da2
--- /dev/null
+++ b/Utilities/KiTrack/src/Criteria/SimpleCircle.h
@@ -0,0 +1,55 @@
+#ifndef SimpleCircle_h
+#define SimpleCircle_h
+
+#include "KiTrack/KiTrackExceptions.h"
+
+namespace KiTrack{
+
+/** A simple class representing a circle.
+ * 
+ * In the constructor it builds a cricle from 3 2-dimensional points.
+ * After that, the parameters can be read out (radius and position of the center)
+ */
+class SimpleCircle {
+  
+  
+  
+  public:
+      
+    
+      SimpleCircle ( double x1 , double y1 , double x2 , double y2 , double x3, double y3 ) ;
+      
+      double getRadius() {return _R;};
+      double getCenterX() {return _centerX;};
+      double getCenterY() {return _centerY;};
+      
+  private:
+      
+      
+      double _R{};
+      double _centerX{};
+      double _centerY{};
+      
+      double _x1{};
+      double _x2{};
+      double _x3{};
+      
+      double _y1{};
+      double _y2{};
+      double _y3{};
+
+
+
+};
+
+
+
+
+} // end of namespace KiTrack
+
+
+
+
+#endif
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc# b/Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc#
new file mode 100644
index 00000000..6d928c37
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc#
@@ -0,0 +1,132 @@
+#include "ILDImpl/FTDTrack.h"
+
+
+#include <algorithm>
+#include <math.h>
+
+//#include "UTIL/LCTrackerConf.h"
+
+// Root, for calculating the chi2 probability. 
+#include "Math/ProbFunc.h"
+
+
+
+using namespace KiTrackMarlin;
+
+/** @return if the absolute z value of hit a is bigger than that of hit b */
+bool compare_IHit_z( IHit* a, IHit* b ){
+   
+   return ( fabs( a->getZ() ) < fabs( b->getZ() ) ); //compare their z values
+   
+}
+
+
+
+FTDTrack::FTDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem ){
+   
+   _trkSystem = trkSystem;
+   _chi2Prob = 0.;
+ 
+   _lcioTrack = new edm4hep::Track();
+   
+   
+}
+
+FTDTrack::FTDTrack( std::vector< IFTDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){
+   
+   
+   _trkSystem = trkSystem;
+   _chi2Prob = 0.;
+   
+   _lcioTrack = new edm4hep::Track();
+   
+   for( unsigned i=0; i < hits.size(); i++ ){
+      
+      addHit( hits[i] );
+      
+      
+   }
+   
+}
+
+
+FTDTrack::FTDTrack( const FTDTrack& f ){
+
+   //make a new copied lcio track
+  _lcioTrack = new edm4hep::Track( *f._lcioTrack );
+   
+   
+   _hits = f._hits;
+   _chi2Prob = f._chi2Prob;
+   _trkSystem = f._trkSystem;
+
+}
+
+FTDTrack & FTDTrack::operator= (const FTDTrack & f){
+   
+   if (this == &f) return *this;   //protect against self assignment
+   
+   //make a new copied lcio track
+   _lcioTrack = new edm4hep::Track( *f._lcioTrack );
+   
+   
+   _hits = f._hits;
+   _chi2Prob = f._chi2Prob;
+   _trkSystem = f._trkSystem;
+   
+   return *this;
+   
+}
+
+
+
+void FTDTrack::addHit( IFTDHit* hit ){
+  if ( hit != NULL ){
+    _hits.push_back( hit );
+    // and sort the track again
+    sort( _hits.begin(), _hits.end(), compare_IHit_z );
+    _lcioTrack->addToTrackerHits( *hit->getTrackerHit() );
+  }
+}
+
+
+
+
+
+void FTDTrack::fit() {
+   
+   
+   Fitter fitter( _lcioTrack , _trkSystem );
+   
+   
+   _lcioTrack->setChi2( fitter.getChi2( 1/*by fucd AtIP=1 in LCIO, changed to CepC rule in future: lcio::TrackState::AtIP*/ ) );
+   _lcioTrack->setNdf( fitter.getNdf( 1/*lcio::TrackState::AtIP*/ ) );
+   _chi2Prob = fitter.getChi2Prob( 1/*lcio::TrackState::AtIP*/ );
+   
+   edm4hep::TrackState trkState( *fitter.getTrackState( 1/*lcio::TrackState::AtIP*/ ) ) ;
+   trkState.location = 1/*lcio::TrackState::AtIP*/ ;
+   _lcioTrack->addToTrackStates( trkState );
+   
+   
+}
+
+
+double FTDTrack::getQI() const{
+  
+   
+   double QI = _chi2Prob;
+   
+   // make sure QI is between 0 and 1
+   if (QI > 1. ) QI = 1.;
+   if (QI < 0. ) QI = 0.;
+   
+   return QI;
+   
+}
+
+
+
+
+
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/FTDHit01.cc b/Utilities/KiTrack/src/ILDImpl/FTDHit01.cc
new file mode 100644
index 00000000..a5eaab1c
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/FTDHit01.cc
@@ -0,0 +1,44 @@
+#include "ILDImpl/FTDHit01.h"
+
+
+#include "UTIL/ILDConf.h"
+
+using namespace KiTrackMarlin;
+
+
+FTDHit01::FTDHit01( edm4hep::TrackerHit trackerHit , const SectorSystemFTD* const sectorSystemFTD ){
+   
+   
+   _sectorSystemFTD = sectorSystemFTD;
+   
+   _trackerHit = trackerHit;
+
+   //Set the position of the FTDHit01
+   const edm4hep::Vector3d& pos= trackerHit.getPosition();
+   _x = pos[0];
+   _y = pos[1]; 
+   _z = pos[2]; 
+
+
+   //find out layer, module, sensor
+
+   UTIL::BitField64  cellID( UTIL::ILDCellID0::encoder_string );
+
+   cellID.setValue( trackerHit.getCellID() );
+     
+   _side   = cellID[ UTIL::ILDCellID0::side ];
+   _module = cellID[ UTIL::ILDCellID0::module ];
+   _sensor = cellID[ UTIL::ILDCellID0::sensor ] - 1;
+   _layer = cellID[ UTIL::ILDCellID0::layer ] + 1;
+   
+   
+   calculateSector();
+   
+   
+   //We assume a real hit. If it is virtual, this has to be set.
+   _isVirtual = false;
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc b/Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc
new file mode 100644
index 00000000..57824a74
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc
@@ -0,0 +1,30 @@
+#include "ILDImpl/FTDHitSimple.h"
+
+
+using namespace KiTrackMarlin;
+
+FTDHitSimple::FTDHitSimple( float x , float y , float z , int side, unsigned layer , unsigned module, unsigned sensor, const SectorSystemFTD* const sectorSystemFTD ){
+   
+   
+   _sectorSystemFTD = sectorSystemFTD;
+   
+   _x = x;
+   _y = y; 
+   _z = z; 
+   
+  
+   _side   = side;
+   _layer  = layer;
+   _module = module;
+   _sensor = sensor;
+   
+   
+   calculateSector();
+   
+   
+   //We assume a real hit. If it is virtual, this has to be set.
+   _isVirtual = false;
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/ILDImpl/FTDNeighborPetalSecCon.cc b/Utilities/KiTrack/src/ILDImpl/FTDNeighborPetalSecCon.cc
new file mode 100644
index 00000000..30e80147
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/FTDNeighborPetalSecCon.cc
@@ -0,0 +1,56 @@
+#include "ILDImpl/FTDNeighborPetalSecCon.h"
+
+
+using namespace KiTrackMarlin;
+
+
+FTDNeighborPetalSecCon::FTDNeighborPetalSecCon( const SectorSystemFTD* sectorSystemFTD ){
+   
+   _sectorSystemFTD = sectorSystemFTD;
+     
+}
+
+
+
+std::set< int > FTDNeighborPetalSecCon::getTargetSectors ( int sector ){
+   
+   
+   
+   std::set <int> targetSectors;
+   
+   
+   int side = _sectorSystemFTD->getSide( sector );
+   unsigned layer = _sectorSystemFTD->getLayer( sector );
+   unsigned petal = _sectorSystemFTD->getModule( sector );
+//    unsigned sensor = _sectorSystemFTD->getSensor( sector );
+   
+//    unsigned nLayers = _sectorSystemFTD->getNumberOfLayers();
+   unsigned nPetals = _sectorSystemFTD->getNumberOfModules();
+   unsigned nSensors = _sectorSystemFTD->getNumberOfSensors();
+   
+   
+   unsigned petalToTheLeft = petal - 1; //the names left and right are arbitrary, as it of course depends on from where one looks.
+   unsigned petalToTheRight = petal + 1;
+   
+   //Now we have to make sure that we didn't leave the petal range 0 to nPetals-1
+   if (petal == 0) petalToTheLeft = nPetals - 1;
+   if (petal == nPetals - 1) petalToTheRight = 0;
+   
+   
+   
+   for ( unsigned iSensor=0; iSensor < nSensors ; iSensor++ ){ //over all sensors
+      
+      
+      targetSectors.insert( _sectorSystemFTD->getSector ( side , layer , petalToTheLeft , iSensor ) ); 
+      targetSectors.insert( _sectorSystemFTD->getSector ( side , layer , petalToTheRight , iSensor ) );
+      
+   }
+   
+   
+   
+   return targetSectors;
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/FTDSectorConnector.cc b/Utilities/KiTrack/src/ILDImpl/FTDSectorConnector.cc
new file mode 100644
index 00000000..4e887e00
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/FTDSectorConnector.cc
@@ -0,0 +1,92 @@
+#include "ILDImpl/FTDSectorConnector.h"
+
+
+using namespace KiTrackMarlin;
+
+
+
+FTDSectorConnector::FTDSectorConnector( const SectorSystemFTD* sectorSystemFTD , unsigned layerStepMax , unsigned petalStepMax, unsigned lastLayerToIP){
+   
+   _sectorSystemFTD = sectorSystemFTD;
+   _layerStepMax = layerStepMax;
+   _lastLayerToIP = lastLayerToIP;
+   _petalStepMax = petalStepMax;
+   
+}
+
+
+
+std::set< int > FTDSectorConnector::getTargetSectors ( int sector ){
+   
+   
+   
+   std::set <int> targetSectors;
+   
+   
+   int side = _sectorSystemFTD->getSide( sector );
+   unsigned layer = _sectorSystemFTD->getLayer( sector );
+   unsigned module = _sectorSystemFTD->getModule( sector );
+//    unsigned sensor = _sectorSystemFTD->getSensor( sector );
+   
+//    unsigned nLayers = _sectorSystemFTD->getNumberOfLayers();
+   unsigned nModules = _sectorSystemFTD->getNumberOfModules();
+   unsigned nSensors = _sectorSystemFTD->getNumberOfSensors();
+   
+   
+   for( unsigned layerStep = 1; layerStep <= _layerStepMax; layerStep++ ){
+      
+      
+      
+      if ( layer >= layerStep +1 ){ //other wise the we could jump past layer 1, ( layer 0 is covered below)
+         
+         
+         unsigned layerTarget = layer - layerStep;
+         
+         
+         for ( unsigned iSensor=0; iSensor < nSensors ; iSensor++){ //over all sensors
+            
+            
+            for ( int iPetal= int(module) - _petalStepMax; iPetal <= int(module) + int(_petalStepMax) ; iPetal++ ){ 
+               
+               //if iPetal is out of the range from 0 to nModules-1, move it back there. 
+               //And of course use a different variable for that. 
+               //(Or else we would create and endless loop: imagine we have iPetal = 16 and set it back to 0--> the loop will continue from there until it reaches 16 again and so on...)
+               int iModule = iPetal;
+               while( iModule < 0 ) iModule+= nModules;
+               while( iModule >= int(nModules) ) iModule -= nModules;
+               
+               targetSectors.insert( _sectorSystemFTD->getSector ( side , layerTarget , iModule , iSensor ) ); 
+               
+            }
+            
+         }
+      
+      }
+      
+   }
+   
+   //Allow jumping to layer 0 from layer _lastLayerToIP or less
+   if ( ( layer >= 1 )&& ( layer <= _lastLayerToIP ) ){
+      
+      
+      unsigned layerTarget = 0;
+      
+      for ( unsigned iModule=0; iModule < nModules ; iModule++){ //over all modules
+         
+         for ( unsigned iSensor=0; iSensor < nSensors ; iSensor++ ){ //over all sensors
+            
+            
+            targetSectors.insert( _sectorSystemFTD->getSector ( side , layerTarget , iModule , iSensor ) ); 
+            
+         }
+         
+      }
+      
+   }
+   
+   return targetSectors;
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/FTDTrack.cc b/Utilities/KiTrack/src/ILDImpl/FTDTrack.cc
new file mode 100644
index 00000000..6d928c37
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/FTDTrack.cc
@@ -0,0 +1,132 @@
+#include "ILDImpl/FTDTrack.h"
+
+
+#include <algorithm>
+#include <math.h>
+
+//#include "UTIL/LCTrackerConf.h"
+
+// Root, for calculating the chi2 probability. 
+#include "Math/ProbFunc.h"
+
+
+
+using namespace KiTrackMarlin;
+
+/** @return if the absolute z value of hit a is bigger than that of hit b */
+bool compare_IHit_z( IHit* a, IHit* b ){
+   
+   return ( fabs( a->getZ() ) < fabs( b->getZ() ) ); //compare their z values
+   
+}
+
+
+
+FTDTrack::FTDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem ){
+   
+   _trkSystem = trkSystem;
+   _chi2Prob = 0.;
+ 
+   _lcioTrack = new edm4hep::Track();
+   
+   
+}
+
+FTDTrack::FTDTrack( std::vector< IFTDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){
+   
+   
+   _trkSystem = trkSystem;
+   _chi2Prob = 0.;
+   
+   _lcioTrack = new edm4hep::Track();
+   
+   for( unsigned i=0; i < hits.size(); i++ ){
+      
+      addHit( hits[i] );
+      
+      
+   }
+   
+}
+
+
+FTDTrack::FTDTrack( const FTDTrack& f ){
+
+   //make a new copied lcio track
+  _lcioTrack = new edm4hep::Track( *f._lcioTrack );
+   
+   
+   _hits = f._hits;
+   _chi2Prob = f._chi2Prob;
+   _trkSystem = f._trkSystem;
+
+}
+
+FTDTrack & FTDTrack::operator= (const FTDTrack & f){
+   
+   if (this == &f) return *this;   //protect against self assignment
+   
+   //make a new copied lcio track
+   _lcioTrack = new edm4hep::Track( *f._lcioTrack );
+   
+   
+   _hits = f._hits;
+   _chi2Prob = f._chi2Prob;
+   _trkSystem = f._trkSystem;
+   
+   return *this;
+   
+}
+
+
+
+void FTDTrack::addHit( IFTDHit* hit ){
+  if ( hit != NULL ){
+    _hits.push_back( hit );
+    // and sort the track again
+    sort( _hits.begin(), _hits.end(), compare_IHit_z );
+    _lcioTrack->addToTrackerHits( *hit->getTrackerHit() );
+  }
+}
+
+
+
+
+
+void FTDTrack::fit() {
+   
+   
+   Fitter fitter( _lcioTrack , _trkSystem );
+   
+   
+   _lcioTrack->setChi2( fitter.getChi2( 1/*by fucd AtIP=1 in LCIO, changed to CepC rule in future: lcio::TrackState::AtIP*/ ) );
+   _lcioTrack->setNdf( fitter.getNdf( 1/*lcio::TrackState::AtIP*/ ) );
+   _chi2Prob = fitter.getChi2Prob( 1/*lcio::TrackState::AtIP*/ );
+   
+   edm4hep::TrackState trkState( *fitter.getTrackState( 1/*lcio::TrackState::AtIP*/ ) ) ;
+   trkState.location = 1/*lcio::TrackState::AtIP*/ ;
+   _lcioTrack->addToTrackStates( trkState );
+   
+   
+}
+
+
+double FTDTrack::getQI() const{
+  
+   
+   double QI = _chi2Prob;
+   
+   // make sure QI is between 0 and 1
+   if (QI > 1. ) QI = 1.;
+   if (QI < 0. ) QI = 0.;
+   
+   return QI;
+   
+}
+
+
+
+
+
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/IMiniVector.h b/Utilities/KiTrack/src/ILDImpl/IMiniVector.h
new file mode 100644
index 00000000..af8142ba
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/IMiniVector.h
@@ -0,0 +1,63 @@
+#ifndef IMiniVector_h
+#define IMiniVector_h
+
+#include <iostream>
+
+#include "edm4hep/TrackerHit.h"
+
+#include "KiTrack/IHit.h"
+#include "ILDImpl/MiniVector.h"
+
+#include "ILDImpl/SectorSystemVXD.h"
+
+namespace KiTrackMarlin{
+   
+   
+   /** An interface for a mini-vector for the ILD 
+    */   
+   class IMiniVector : public IHit{
+      
+      
+   public:
+      
+      
+      MiniVector* getMiniVector() { return _miniVector; };
+      
+      
+      int getTheta() { return _theta; }
+      unsigned getPhi() { return _phi; }
+      
+
+      //void setLayer( unsigned layer ){ _layer = layer; calculateSector();}
+      //void setPhi( unsigned phi ){ _phi = phi; calculateSector();}
+      //void setTheta( unsigned theta ){ _theta = theta; calculateSector();}
+      void setLayer( unsigned layer ){ _layer = layer; }
+      void setPhi( unsigned phi ){ _phi = phi; }
+      void setTheta( unsigned theta ){ _theta = theta; }         
+      
+      
+      virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; };
+      
+   protected:
+      
+      MiniVector* _miniVector;
+      
+      
+      int _layer;
+      int _phi;
+      int _theta;
+      
+      const SectorSystemVXD* _sectorSystemVXD;
+      
+      /** Calculates and sets the sector number
+       */
+
+      //void calculateSector(){ _sector = _sectorSystemMV->getSector( _layer, _phi, _theta ); }
+      
+   };
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/src/ILDImpl/IVXDHit.h b/Utilities/KiTrack/src/ILDImpl/IVXDHit.h
new file mode 100644
index 00000000..dcbecd9e
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/IVXDHit.h
@@ -0,0 +1,53 @@
+#ifndef IVXDHit_h
+#define IVXDHit_h
+
+#include <iostream>
+
+#include "edm4hep/TrackerHit.h"
+//#include "lcio.h"
+
+#include "KiTrack/IHit.h"
+
+#include "ILDImpl/SectorSystemVXD.h"
+
+namespace KiTrackMarlin{
+  /** An interface for a hit for the ILD using an lcio TrackerHit as basis.
+   * 
+   * It comes along with a layer, phi and theta.
+   */   
+  class IVXDHit : public IHit{
+  public:
+    
+    edm4hep::TrackerHit* getTrackerHit() { return _trackerHit; };
+            
+    int getTheta() { return _theta; }
+    unsigned getPhi() { return _phi; }
+    
+    //void setLayer( unsigned layer ){ _layer = layer; calculateSector();}
+    //void setPhi( unsigned phi ){ _phi = phi; calculateSector();}
+    //void setTheta( unsigned theta ){ _theta = theta; calculateSector();}
+    void setLayer( unsigned layer ){ _layer = layer; }
+    void setPhi( unsigned phi ){ _phi = phi; }
+    void setTheta( unsigned theta ){ _theta = theta; }    
+    
+    
+    virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; };
+    
+  protected:
+    
+    edm4hep::TrackerHit* _trackerHit;
+      
+    int _layer;
+    int _phi;
+    int _theta;
+    
+    const SectorSystemVXD* _sectorSystemVXD;
+    
+    /** Calculates and sets the sector number
+     */
+    
+    //void calculateSector(){ _sector = _sectorSystemVXD->getSector( _layer, _phi, _theta ); }
+  };
+}
+#endif
+
diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVector.cc b/Utilities/KiTrack/src/ILDImpl/MiniVector.cc
new file mode 100644
index 00000000..3d7840a2
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/MiniVector.cc
@@ -0,0 +1,139 @@
+#include <ILDImpl/MiniVector.h>
+
+#include "TrackSystemSvc/IMarlinTrack.h"
+#include "CLHEP/Vector/ThreeVector.h"
+
+using namespace KiTrack;
+using namespace KiTrackMarlin;
+
+MiniVector::MiniVector(edm4hep::TrackerHit * outer, edm4hep::TrackerHit * inner) { 
+  HitVec.push_back(outer);
+  HitVec.push_back(inner);
+}
+
+
+MiniVector::MiniVector( TrackerHitVec hitPair){
+
+  HitVec = hitPair ;
+
+}
+
+MiniVector::~MiniVector(){
+
+}
+
+
+double * MiniVector::getPosition(){
+
+  double x_outer = HitVec[0]->getPosition()[0];
+  double y_outer = HitVec[0]->getPosition()[1];
+  double z_outer = HitVec[0]->getPosition()[2];
+  
+  double x_inner = HitVec[1]->getPosition()[0];
+  double y_inner = HitVec[1]->getPosition()[1];
+  double z_inner = HitVec[1]->getPosition()[2];
+
+  double *_pos = new double[3] ;
+
+  //_pos[0] = (x_outer - x_inner)/2. ;
+  //_pos[1] = (y_outer - y_inner)/2. ;
+  //_pos[2] = (z_outer - z_inner)/2. ;
+
+  _pos[0] = x_inner ;
+  _pos[1] = y_inner ;
+  _pos[2] = z_inner ;
+
+  return _pos ;
+
+}
+
+
+TrackerHitVec MiniVector::getTrackerHitVec(){
+
+  return HitVec ;
+
+}
+
+
+
+double MiniVector::getPhi(){
+
+  double x_outer = HitVec[0]->getPosition()[0];
+  double y_outer = HitVec[0]->getPosition()[1];
+  
+  double x_inner = HitVec[1]->getPosition()[0];
+  double y_inner = HitVec[1]->getPosition()[1];
+
+  double phiMV =  atan2((y_outer-y_inner),(x_outer-x_inner))  ;
+
+  //std::cout << " outer x,y " << x_outer << " , " << y_outer << " inner x,y " << x_inner << " , " << y_inner << std::endl ;
+
+  //std::cout << " Calling MiniVector::getPhi, returning " << phiMV << std::endl ;
+
+  return phiMV ;
+
+}
+
+double MiniVector::getTheta(){
+
+  double x_outer = HitVec[0]->getPosition()[0];
+  double y_outer = HitVec[0]->getPosition()[1];
+  double z_outer = HitVec[0]->getPosition()[2];
+  
+  double x_inner = HitVec[1]->getPosition()[0];
+  double y_inner = HitVec[1]->getPosition()[1];
+  double z_inner = HitVec[1]->getPosition()[2];
+
+  double thetaMV = atan2(sqrt((x_outer-x_inner)*(x_outer-x_inner) + (y_outer-y_inner)*(y_outer-y_inner)),(z_outer-z_inner)) ;
+
+  return thetaMV ;
+
+}
+
+
+double * MiniVector::getXYZ(){
+
+  double x_outer = HitVec[0]->getPosition()[0];
+  double y_outer = HitVec[0]->getPosition()[1];
+  double z_outer = HitVec[0]->getPosition()[2];
+  
+  double x_inner = HitVec[1]->getPosition()[0];
+  double y_inner = HitVec[1]->getPosition()[1];
+  double z_inner = HitVec[1]->getPosition()[2];
+
+  double *xyz = new double[3] ;
+
+  xyz[0] = x_outer - x_inner ;
+  xyz[1] = y_outer - y_inner ;
+  xyz[2] = z_outer - z_inner ;
+
+
+  return xyz ;
+
+}
+
+
+double MiniVector::get3DAngleMV(MiniVector *MinVec2){
+
+  double *xyz1 = new double[3] ;
+  xyz1 = this->getXYZ() ;
+  CLHEP::Hep3Vector v1( xyz1[0], xyz1[1], xyz1[2] ) ;
+
+  double *xyz2 = new double[3] ;
+  xyz2 = MinVec2->getXYZ() ;
+
+  CLHEP::Hep3Vector v2( xyz2[0], xyz2[1], xyz2[2] ) ;
+
+  double ScalarProd = v1.dot(v2);
+  double magV1 = v1.r();
+  double magV2 = v2.r();
+
+  std::cout << "####### MINIVECTOR::get3DAngle, Scalar product " << ScalarProd << " mag. of the instantiate mv " << magV1 << " mag. of the second mv " << magV2 << std::endl ; 
+
+  double Angle3D =  acos(ScalarProd / (magV1*magV2)) ; 
+ 
+  return Angle3D ;
+
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVector.h b/Utilities/KiTrack/src/ILDImpl/MiniVector.h
new file mode 100644
index 00000000..40c2e369
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/MiniVector.h
@@ -0,0 +1,67 @@
+#ifndef MINIVECTOR_H
+#define MINIVECTOR_H 1
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <edm4hep/TrackerHit.h>
+//#include "UTIL/LCTrackerConf.h"
+#include "KiTrack/IHit.h"
+
+#include "ILDImpl/SectorSystemVXD.h"
+
+#include <vector>
+#include <math.h>
+
+typedef std::vector<edm4hep::TrackerHit*> TrackerHitVec;
+
+namespace KiTrackMarlin{
+  class MiniVector : public IHit{
+  public:
+    TrackerHitVec HitVec ;
+    
+    // Class constructor
+    MiniVector(edm4hep::TrackerHit * outer, edm4hep::TrackerHit * inner);
+    
+    MiniVector(TrackerHitVec hitPair);
+    
+    ~MiniVector();
+    
+    // returns the TrackerHitVec 
+    TrackerHitVec getTrackerHitVec() ;
+    
+    // Gives the layer of the inner hit
+    //int getLayer() ;
+    
+    // Gives the azimuth angle of the mini-vector
+    double getPhi() ;
+    
+    // Gives the polar angle of the mini-vector
+    double getTheta() ;
+    
+    // Gives the 2-D angle between two minivectors
+    //double get2DAngle(MiniVector MinVec1, MiniVector MinVec2) ;
+    
+    // Gives the 3-D angle between two minivectors
+    double get3DAngleMV(MiniVector *MinVec2) ;
+    
+    double * getXYZ() ;
+    
+    // Gives the position of the mini-vector
+    double * getPosition() ;
+
+    virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; };
+      
+
+  protected:
+
+    const SectorSystemVXD* _sectorSystemVXD;
+    
+  };
+
+}
+
+
+
+
+#endif
diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.cc b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.cc
new file mode 100644
index 00000000..10d7ea3c
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.cc
@@ -0,0 +1,59 @@
+#include "ILDImpl/MiniVectorHit01.h"
+#include "ILDImpl/SectorSystemVXD.h"
+
+//#include "UTIL/LCTrackerConf.h"
+#include <UTIL/ILDConf.h>
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+#include <climits>
+
+using namespace KiTrackMarlin;
+
+typedef std::vector<edm4hep::TrackerHit*> TrackerHitVec;
+
+MiniVectorHit01::MiniVectorHit01( MiniVector* miniVector , const SectorSystemVXD* const sectorSystemVXD ){
+   
+   
+   _sectorSystemVXD = sectorSystemVXD;
+   
+   _miniVector = miniVector;
+
+   _phiMV = miniVector->getPhi() ;
+
+   _thetaMV = miniVector->getTheta() ;
+
+   TrackerHitVec HitVec = miniVector->getTrackerHitVec();
+
+   UTIL::BitField64  cellID( UTIL::ILDCellID0::encoder_string );
+   cellID.setValue( HitVec[1]->getCellID() );
+   
+   int _layer = cellID[ UTIL::ILDCellID0::layer ] ; // +1 to take into account the IP (considered as layer 0 ) 
+   int det_id = 0 ;
+   det_id  = cellID[UTIL::ILDCellID0::subdet] ;
+   if ( det_id == UTIL::ILDDetID::SIT) { _layer = _layer + 6; } 
+   
+   //Set the position of the VXDHit01
+   const double* pos= miniVector->getPosition();
+   _x = pos[0];
+   _y = pos[1]; 
+   _z = pos[2]; 
+
+   double _cosTheta = cos(miniVector->getTheta());
+   double _phi = miniVector->getPhi();
+   double _theta = miniVector->getTheta() ;
+
+   if (_phi < 0.) _phi = _phi + 2*M_PI;   
+
+   // YV, for debugging. Calculate sector here and not through the IVXHit base class
+   //calculateSector();
+   _sector = _sectorSystemVXD->getSector( _layer, _phi, _cosTheta );
+   
+   //We assume a real hit. If it is virtual, this has to be set.
+   _isVirtual = false;
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.h b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.h
new file mode 100644
index 00000000..e3e50afd
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.h
@@ -0,0 +1,16 @@
+#ifndef MiniVectorHit01_h
+#define MiniVectorHit01_h
+
+#include "ILDImpl/IMiniVector.h"
+
+namespace KiTrackMarlin{
+  /** A class for mini-vectors in the VXD - SIT system (the 01 is just for historical reasons and may be renamed)
+   */   
+  class MiniVectorHit01 : public IMiniVector{
+  public:
+    
+    MiniVectorHit01( MiniVector* miniVector , const SectorSystemVXD* const sectorSystemVXD );
+  };
+}
+#endif
+
diff --git a/Utilities/KiTrack/src/ILDImpl/SectorSystemFTD.cc b/Utilities/KiTrack/src/ILDImpl/SectorSystemFTD.cc
new file mode 100644
index 00000000..ff064859
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/SectorSystemFTD.cc
@@ -0,0 +1,183 @@
+#include "ILDImpl/SectorSystemFTD.h"
+
+#include <sstream>
+
+using namespace KiTrackMarlin;
+
+
+SectorSystemFTD::SectorSystemFTD( unsigned nLayers , unsigned nModules , unsigned nSensors ):
+   
+
+_nModules( nModules ),
+_nSensors( nSensors ){
+   
+   _nLayers = nLayers;
+   _sectorMax = 2*nLayers*nModules*nSensors - 1;
+   
+}
+   
+
+
+int SectorSystemFTD::getSector( int side, unsigned layer , unsigned module , unsigned sensor )const {
+   
+   //check if the values passed are okay:
+   if ( ( side!= 1 )&&( side != -1 ) ){
+      
+      
+      std::stringstream s;
+      s << "Side has to be either +1 or -1 and not " << side;
+      throw OutOfRange( s.str() );
+      
+   }
+   
+   if ( layer >= _nLayers ){
+      
+      std::stringstream s; 
+      s << "Layer " << layer << " is too big, the outermost layer is layer " << _nLayers - 1;
+      throw OutOfRange( s.str() );
+      
+   }
+   
+   if ( module >= _nModules ){
+      
+      std::stringstream s; 
+      s << "Module " << module << " is too big, the highest module is module " << _nModules - 1;
+      throw OutOfRange( s.str() );
+      
+   }
+   
+   if ( sensor >= _nSensors ){
+      
+      std::stringstream s;
+      s << "Sensor " << sensor << " is too big, the highest sensor is sensor " << _nSensors - 1;
+      throw OutOfRange( s.str() );
+      
+   }   
+   
+   unsigned multiplicator=1;
+   
+   
+   int sector = sensor;
+   multiplicator *= _nSensors; //there are nSensors possible values for sensor
+   
+   sector += module * multiplicator;
+   multiplicator *= _nModules;
+   
+   sector += layer * multiplicator;
+   multiplicator *= _nLayers;
+   
+   
+   sector += ( (side + 1 )/2 ) * multiplicator;             // (side+1) /2 gives 0 for backward (-1) and 1 for forward (+1)
+   /*
+   streamlog_out( DEBUG0 ) << " Sector of side " << side
+   << ", layer " << layer
+   << ", module " << module
+   << ", sensor " << sensor
+   << " == " << sector << "\n";
+   */
+   
+   return sector;
+   
+}
+
+
+
+
+
+
+int SectorSystemFTD::getSide( int sector ) const {
+   
+   checkSectorIsInRange( sector );
+   
+   
+   
+   int side = ( sector / ( _nSensors * _nModules * _nLayers ) ) % 2; //this is an integerdivision --> we will get the floor authomatically
+   
+   side = side*2 - 1 ; //from 0 and 1 to  -1 and 1
+   
+//    streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Side " << side;
+   
+   return side;
+   
+}
+
+unsigned SectorSystemFTD::getLayer( int sector ) const {
+   
+   checkSectorIsInRange( sector );
+   
+   unsigned layer = ( sector / (  _nSensors * _nModules ) ) % _nLayers; //this is an integerdivision --> we will get the floor authomatically
+   
+//    streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Layer " << layer;
+   
+   return layer;
+   
+   
+}
+
+unsigned SectorSystemFTD::getModule( int sector ) const {
+   
+   
+   checkSectorIsInRange( sector );
+   
+   unsigned module = ( sector / ( _nSensors ) ) % _nModules; //this is an integerdivision --> we will get the floor authomatically
+   
+//    streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Module " << module;
+   
+   return module;
+   
+   
+   
+}
+unsigned SectorSystemFTD::getSensor( int sector ) const {
+   
+   
+   checkSectorIsInRange( sector );
+   
+   unsigned sensor = ( sector ) % _nSensors; 
+   
+//    streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Sensor " << sensor;
+   
+   return sensor;
+   
+}
+
+
+void SectorSystemFTD::checkSectorIsInRange( int sector ) const {
+
+
+   if ( sector > _sectorMax ){
+      
+      std::stringstream s;
+      s << "SectorSystemFTD:\n Sector " 
+        << sector << " is too big, the highest possible number for a sector in this configuration of FTDSegRepresentation is"
+        << _sectorMax 
+        << ".\nThe configuration is: nLayers = " << _nLayers
+        << ", nModules = " << _nModules
+        << ", nSensors = " << _nSensors 
+        << "\n With 2 sides (forward and backward) this gives sectors from 0 to 2*" 
+        << _nLayers << "*"  
+        << _nModules << "*"
+        << _nSensors << " -1 = " << 2*_nLayers*_nModules*_nSensors -1 ;
+      throw OutOfRange( s.str() );
+      
+   }  
+
+}
+
+std::string SectorSystemFTD::getInfoOnSector( int sector ) const{
+   
+   
+   std::stringstream s;
+   s << " (si" << getSide(sector)  
+     << ",la" << getLayer(sector)
+     << ",mo" << getModule(sector) 
+     << ",se" << getSensor(sector) 
+     << ")";
+   
+   
+   return s.str();   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/SectorSystemVXD.cc b/Utilities/KiTrack/src/ILDImpl/SectorSystemVXD.cc
new file mode 100644
index 00000000..305d37c3
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/SectorSystemVXD.cc
@@ -0,0 +1,201 @@
+#include "ILDImpl/SectorSystemVXD.h"
+
+#include <sstream>
+#include <cmath>
+
+using namespace KiTrackMarlin;
+
+
+SectorSystemVXD::SectorSystemVXD( unsigned nLayers, unsigned nDivisionsInPhi, unsigned nDivisionsInTheta ){   
+
+  _nLayers = nLayers;
+  _nDivisionsInPhi = nDivisionsInPhi ;
+  _nDivisionsInTheta = nDivisionsInTheta ;
+  _sectorMax = _nLayers + _nLayers*_nDivisionsInPhi + _nLayers*_nDivisionsInPhi*_nDivisionsInTheta ;
+   
+}
+
+unsigned SectorSystemVXD::getNLayers() const {
+
+  return _nLayers ;
+
+}
+
+unsigned SectorSystemVXD::getPhiSectors() const {
+
+  return _nDivisionsInPhi ;
+
+}
+
+
+unsigned SectorSystemVXD::getThetaSectors() const {
+
+  return _nDivisionsInTheta ;
+
+} 
+  
+
+unsigned SectorSystemVXD::getLayer( int sector ) const {
+  
+  //std::cout << " SectorSystemVXD::getLayer  total no of layers = " << _nLayers << " n divisions in phi = " << _nDivisionsInPhi << " sector = " << sector << std::endl ;
+  
+  int theta = sector/(_nLayers*_nDivisionsInPhi) ;
+  
+  int phi = ((sector - (theta*_nLayers*_nDivisionsInPhi)) / _nLayers) ;
+  
+  int Layer = sector - (theta*_nLayers*_nDivisionsInPhi) - (phi*_nLayers) ; 
+
+  //std::cout << " SectorSystemVXD::getLayer " << Layer << " total no of layers = " << _nLayers << " iPhi = " << phi << " iTheta = " << theta << " n divisions in phi = " << _nDivisionsInPhi << " sector = " << sector << std::endl ;
+  
+  return Layer ;
+  
+}
+
+
+unsigned SectorSystemVXD::getPhi( int sector) const {
+
+  int theta = sector/(_nLayers*_nDivisionsInPhi) ;
+
+  int Phi = ((sector - (theta*_nLayers*_nDivisionsInPhi)) / _nLayers) ;
+
+  //std::cout << " SectorSystemVXD::getPhi " << Phi << std::endl ;
+   
+  return Phi ;
+   
+}
+
+
+unsigned SectorSystemVXD::getTheta( int sector ) const {
+
+   int Theta = sector/(_nLayers*_nDivisionsInPhi) ;
+
+   //std::cout << " SectorSystemVXD::getTheta " << Theta << std::endl ;
+
+   return Theta ;
+      
+}
+
+
+int SectorSystemVXD::getSector( int layer , int phi , int theta ) const {
+  
+  //std::cout << "getting sector : layer " << layer << " phi " << phi << " theta " << theta << std::endl ;
+
+  if ( layer >= _nLayers ){
+    
+    std::stringstream s; 
+    s << "Layer " << layer << " is too big, the outermost layer is layer " << _nLayers - 1 ;
+    throw OutOfRange( s.str() );
+    
+  }
+
+  
+  if ( phi >= _nDivisionsInPhi ){
+    
+    std::stringstream s; 
+    s << "Phi " << phi << " is too big, the highest phi division is " << _nDivisionsInPhi ;
+    throw OutOfRange( s.str() );
+    
+  }
+
+
+  
+  if ( theta >= _nDivisionsInTheta ){
+    
+    std::stringstream s;
+    s << "Theta " << theta << " is too big, the highest theta division is " << _nDivisionsInTheta ;
+
+    throw OutOfRange( s.str() );
+    //std::cout << " ####3 calling getSector function $$$$$$$$$$" << std::endl ;    
+  }   
+
+  int sector = layer + _nLayers*phi + _nLayers*_nDivisionsInPhi*theta ;
+  //std::cout << " did you call me? I am the Theta version, give you the sector " << sector << std::endl ;
+    
+  return sector ;  
+
+}
+
+
+int SectorSystemVXD::getSector( int layer , double phi , double cosTheta ) const {
+  
+
+  double _dPhi = (2*M_PI)/_nDivisionsInPhi;
+  double _dTheta = 2.0/_nDivisionsInTheta;
+  int iPhi = int(phi / _dPhi);
+  int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+
+  //std::cout << "getting sector : layer " << layer << " phi " << iPhi << " theta " << iTheta << std::endl ;
+
+  if ( layer >= _nLayers ){
+    
+    std::stringstream s; 
+    s << "Layer " << layer << " is too big, the outermost layer is layer " << _nLayers - 1 ;
+    throw OutOfRange( s.str() );
+    
+  }
+
+  
+  if ( iPhi >= _nDivisionsInPhi ){
+    
+    std::stringstream s; 
+    s << "Phi " << iPhi << " is too big, the highest phi division is " << _nDivisionsInPhi ;
+    throw OutOfRange( s.str() );
+    
+  }
+
+
+  
+  if ( iTheta >= _nDivisionsInTheta ){
+    
+    std::stringstream s;
+    s << "Theta " << iTheta << " is too big, the highest theta division is " << _nDivisionsInTheta ;
+
+    throw OutOfRange( s.str() );
+    //std::cout << " ####3 calling getSector function $$$$$$$$$$" << std::endl ;    
+  }   
+
+  int sector = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta ;
+  //std::cout << " did you call me? I am the cosTheta version, give you the sector " << sector << std::endl ;
+  
+  return sector ;  
+
+}
+
+
+
+void SectorSystemVXD::checkSectorIsInRange( int sector ) const {
+
+
+   if ( sector > _sectorMax ){
+      
+      std::stringstream s;
+      s << "SectorSystemVXS:\n Sector " 
+        << sector << " is too big, the highest possible number for a sector in this configuration of VXD - SIT is"
+        << _sectorMax 
+        << ".\nThe configuration is: nLayers = " << _nLayers
+        << ", n divisions in phi = " << _nDivisionsInPhi
+        << ", n divisions in theta = " << _nDivisionsInTheta
+	<< _nLayers + _nLayers*_nDivisionsInPhi + _nLayers*_nDivisionsInPhi*_nDivisionsInTheta ;
+      throw OutOfRange( s.str() );
+      
+   }  
+
+}
+
+
+std::string SectorSystemVXD::getInfoOnSector( int sector ) const{
+   
+   
+   std::stringstream s;
+   s << " (layer" << getLayer(sector )  
+     << ",theta" << getTheta(sector )
+     << ",phi" << getPhi(sector ) 
+     << ")";
+   
+   
+   return s.str();   
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/VXDHit01.cc b/Utilities/KiTrack/src/ILDImpl/VXDHit01.cc
new file mode 100644
index 00000000..f6e67e95
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/VXDHit01.cc
@@ -0,0 +1,67 @@
+#include "ILDImpl/VXDHit01.h"
+#include "ILDImpl/SectorSystemVXD.h"
+
+//#include "UTIL/LCTrackerConf.h"
+#include <UTIL/ILDConf.h>
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+#include <climits>
+
+using namespace KiTrackMarlin;
+
+
+VXDHit01::VXDHit01( edm4hep::TrackerHit* trackerHit , const SectorSystemVXD* const sectorSystemVXD ){
+   
+   
+   _sectorSystemVXD = sectorSystemVXD;
+   
+   _trackerHit = trackerHit;
+
+   //Set the position of the VXDHit01
+   const edm4hep::Vector3d& pos= trackerHit->getPosition();
+   _x = pos[0];
+   _y = pos[1]; 
+   _z = pos[2]; 
+
+
+   //find out layer, module, sensor
+
+   UTIL::BitField64  cellID( UTIL::ILDCellID0::encoder_string );
+
+   //cellID.setValue( trackerHit->getCellID0() );
+   _layer = cellID[ UTIL::ILDCellID0::layer ] + 1 ;   // + 1 to take into account the IP (considered as layer 0 ) 
+   //_layer = cellID[ LCTrackerCellID::layer() ];
+   int det_id = 0 ;
+   det_id  = cellID[UTIL::ILDCellID0::subdet] ;
+   if ( det_id == UTIL::ILDDetID::SIT) { _layer = _layer + 6; }   // need to find a more elegant way...
+
+
+   double radius = 0;
+      
+   for (int i=0; i<3; ++i) {
+     radius += pos[i]*pos[i];
+   }
+
+   radius = sqrt(radius);
+      
+   double _cosTheta = (pos[2]/radius);
+   double _phi = atan2(pos[1],pos[0]);
+   double _theta = acos( _cosTheta ) ;
+      
+   if (_phi < 0.) _phi = _phi + 2*M_PI;   
+
+   // YV, for debugging. Calculate sector here and not through the IVXHit base class
+   //calculateSector();
+
+   _sector = _sectorSystemVXD->getSector( _layer, _phi, _cosTheta );
+
+   
+   //We assume a real hit. If it is virtual, this has to be set.
+   _isVirtual = false;
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/VXDHit01.h b/Utilities/KiTrack/src/ILDImpl/VXDHit01.h
new file mode 100644
index 00000000..dbcc828f
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/VXDHit01.h
@@ -0,0 +1,23 @@
+#ifndef VXDHit01_h
+#define VXDHit01_h
+
+#include "ILDImpl/IVXDHit.h"
+
+namespace KiTrackMarlin{
+  /** A class for hits in the VXD (the 01 is just for historical reasons and may be renamed)
+   * 
+   * - The side is according to CellID0.
+   * - Layer is set according to CellID0 +1 (so we can use layer 0 for the IP)
+   * - Module is set according to CellID0.
+   * - Sensor is set according to CellID0 -1. (because currently sensors of the VXD start with 1 in the CellID0, if this changes, this has to be modified)
+   */   
+  class VXDHit01 : public IVXDHit{
+  public:
+    
+    VXDHit01( edm4hep::TrackerHit* trackerHit , const SectorSystemVXD* const sectorSystemVXD );
+  };
+  //void setSectorisationInPhi(int PhiSectors);
+  //void setSectorisationInTheta(int ThetaSectors);
+}
+#endif
+
diff --git a/Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc b/Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc
new file mode 100644
index 00000000..857e6784
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc
@@ -0,0 +1,29 @@
+#include "ILDImpl/VXDHitSimple.h"
+
+
+using namespace KiTrackMarlin;
+
+VXDHitSimple::VXDHitSimple( float x , float y , float z , int layer , int phi, int theta, const SectorSystemVXD* const sectorSystemVXD ){
+   
+   
+   _sectorSystemVXD = sectorSystemVXD;
+   
+   _x = x;
+   _y = y; 
+   _z = z; 
+   
+  
+   _layer  = layer;
+   _phi = phi;
+   _theta = theta;
+   
+   _sector = _sectorSystemVXD->getSector( layer, phi, theta );  // maybe a good idea to calculate a sector for the IP hit as well  
+   //calculateSector();
+   
+   
+   //We assume a real hit. If it is virtual, this has to be set.
+   _isVirtual = false;
+   
+   
+}
+
diff --git a/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.cc b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.cc
new file mode 100644
index 00000000..4237c06a
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.cc
@@ -0,0 +1,100 @@
+#include "ILDImpl/VXDSectorConnector.h"
+
+
+using namespace KiTrackMarlin;
+
+
+// Constructor
+VXDSectorConnector::VXDSectorConnector( const SectorSystemVXD* sectorSystemVXD , unsigned layerStepMax, unsigned lastLayerToIP, int neighPhi, int neighTheta, int layerMax ){
+   
+   _sectorSystemVXD = sectorSystemVXD ;
+   _layerStepMax = layerStepMax ;
+   _lastLayerToIP = lastLayerToIP ;
+
+   _nLayers = sectorSystemVXD->getNLayers();
+   _nDivisionsInPhi = sectorSystemVXD->getPhiSectors();
+   _nDivisionsInTheta = sectorSystemVXD->getThetaSectors();
+   _neighPhi = neighPhi ;
+   _neighTheta = neighTheta ;
+   _layerMax = layerMax ;
+}
+
+
+
+std::set< int > VXDSectorConnector::getTargetSectors ( int sector ){
+   
+   
+   std::set <int> targetSectors;
+
+   //std::cout << " check : n layers " << _nLayers << " n phi divisions " << _nDivisionsInPhi << " n theta divisions " << _nDivisionsInTheta << std::endl ;
+
+   // Decode the sector integer,  and take the layer, phi and theta bin
+   
+   int iTheta = sector/(_nLayers*_nDivisionsInPhi) ;
+   
+   int iPhi = ((sector - (iTheta*_nLayers*_nDivisionsInPhi)) / _nLayers) ;
+   
+   int layer = sector - (iTheta*_nLayers*_nDivisionsInPhi) - (iPhi*_nLayers) ; 
+
+   // search for sectors at the neighbouring theta nad phi bins
+
+   int iPhi_Up    = iPhi + _neighPhi;
+   int iPhi_Low   = iPhi - _neighPhi;
+   int iTheta_Up  = iTheta + _neighTheta; 
+   int iTheta_Low = iTheta - _neighTheta;
+   if (iTheta_Low < 0) iTheta_Low = 0;
+   if (iTheta_Up  >= _nDivisionsInTheta) iTheta_Up = _nDivisionsInTheta-1;
+   
+   //*************************************************************************************
+
+   //streamlog_out(DEBUG2) << " checking sector " << sector << " layer " << layer << " phi " << iPhi << " theta " << iTheta <<std::endl ;
+   
+   for( unsigned layerStep = 1; layerStep <= _layerStepMax; layerStep++ ){
+     
+     if ( layer >= layerStep ){ // +1 makes sense if I use IP as innermost layer
+       
+       unsigned layerTarget = layer - layerStep;
+
+        if (layerTarget >= 0 && layerTarget < _layerMax ){   // just a test to run cellular automaton over the whole VXD - SIT
+	 
+	 for (int iPhi = iPhi_Low ; iPhi <= iPhi_Up ; iPhi++){
+
+	   int ip = iPhi;
+	   
+	   // catch wrap-around
+	   if (ip < 0) ip = _nDivisionsInPhi-1;          
+	   if (ip >= _nDivisionsInPhi) ip = ip - _nDivisionsInPhi;
+	   
+	   for (int iTheta = iTheta_Low ; iTheta <= iTheta_Up ; iTheta++){
+	     
+	     targetSectors.insert( _sectorSystemVXD->getSector ( layerTarget , ip , iTheta ) ); 
+	     
+	   }
+	 }
+       }
+     }
+   }
+   
+
+   if ( layer > 0 && ( layer <= _lastLayerToIP ) ){
+      
+     unsigned layerTarget = 0;
+      
+     for (int ip = iPhi_Low ; ip <= iPhi_Up ; ip++){
+       
+       for (int iTheta = iTheta_Low ; iTheta <= iTheta_Up ; iTheta++){
+	 
+	 //streamlog_out(DEBUG1) << " VXDSectorConnector: from layer " << layer << " to layer " << layerTarget << std::endl ;
+	 
+	 targetSectors.insert( 0 ) ;
+       }
+     }
+   }
+   
+										 
+   return targetSectors;
+   
+   
+}
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.h b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.h
new file mode 100644
index 00000000..27ef66f7
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.h
@@ -0,0 +1,51 @@
+#ifndef VXDSectorConnector_h
+#define VXDSectorConnector_h
+
+#include "KiTrack/ISectorConnector.h"
+
+#include "ILDImpl/SectorSystemVXD.h"
+
+
+
+namespace KiTrackMarlin{
+   
+   /** Used to connect two sectors on the VXD.
+    * 
+    * 
+    * Allows:
+    * 
+    * - going to layers on the inside (how far see constructor)
+    * - jumping to the IP (from where see constructor)
+    */   
+   class VXDSectorConnector : public ISectorConnector{
+      
+      
+   public:
+      
+    VXDSectorConnector ( const SectorSystemVXD* sectorSystemVXD , unsigned layerStepMax, unsigned lastLayerToIP, int neighPhi = 8,  int neighTheta = 1, int layerMax = 10  ) ;
+      
+      /** @return a set of all sectors that are connected to the passed sector */
+      virtual std::set <int>  getTargetSectors ( int sector );
+      
+      virtual ~VXDSectorConnector(){};
+      
+   private:
+      
+      const SectorSystemVXD* _sectorSystemVXD;
+      
+      unsigned _layerStepMax;
+      unsigned _nLayers;
+      unsigned _lastLayerToIP;
+      unsigned _nDivisionsInPhi ;
+      unsigned _nDivisionsInTheta ; 
+      int _layerMax ;   
+      int _neighTheta ;
+      int _neighPhi ;
+   };
+   
+   
+}
+
+
+#endif
+
diff --git a/Utilities/KiTrack/src/ILDImpl/VXDTrack.cc b/Utilities/KiTrack/src/ILDImpl/VXDTrack.cc
new file mode 100644
index 00000000..b00b855e
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/VXDTrack.cc
@@ -0,0 +1,201 @@
+#include "ILDImpl/VXDTrack.h"
+
+#include <algorithm>
+
+//#include "UTIL/LCTrackerConf.h"
+
+// Root, for calculating the chi2 probability. 
+#include "Math/ProbFunc.h"
+
+
+
+using namespace KiTrackMarlin;
+
+// FIX ME
+/** @return if the radius of hit a is bigger than that of hit b */
+
+bool compare_IHit_R_3Dhits( IHit* a, IHit* b ){
+
+  double r2_a = fabs((a->getX()*a->getX()) + (a->getY()*a->getY()));
+  double r2_b = fabs((b->getX()*b->getX()) + (b->getY()*b->getY()));
+   
+   return ( r2_a < r2_b ); //compare their radii
+   
+}
+
+
+
+VXDTrack::VXDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem ){
+   
+   _trkSystem = trkSystem;
+   _chi2Prob = 0.;
+ 
+   _lcioTrack = new edm4hep::Track();
+   
+}
+/*
+VXDTrack::VXDTrack( std::vector< IVXDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){
+   
+   
+   _trkSystem = trkSystem;
+   _chi2Prob = 0.;
+   
+   _lcioTrack = new TrackImpl();
+   
+   for( unsigned i=0; i < hits.size(); i++ ){
+      
+      addHit( hits[i] );
+      
+      
+   }
+   
+}
+*/
+
+VXDTrack::VXDTrack( std::vector< IMiniVector* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){
+   
+   
+   _trkSystem = trkSystem;
+   _chi2Prob = 0.;
+   
+   _lcioTrack = new edm4hep::Track();
+   
+   for( unsigned i=0; i < hits.size(); i++ ){
+      
+      addHit( hits[i] );
+      
+      
+   }
+   
+}
+
+
+
+
+VXDTrack::VXDTrack( const VXDTrack& f ){
+
+   //make a new copied lcio track
+  _lcioTrack = new edm4hep::Track( *f._lcioTrack );
+   
+   
+   _hits = f._hits;
+   _chi2Prob = f._chi2Prob;
+   _trkSystem = f._trkSystem;
+
+}
+
+VXDTrack & VXDTrack::operator= (const VXDTrack & f){
+   
+   if (this == &f) return *this;   //protect against self assignment
+   
+   //make a new copied lcio track
+   _lcioTrack = new edm4hep::Track( *f._lcioTrack );
+   
+   
+   _hits = f._hits;
+   _chi2Prob = f._chi2Prob;
+   _trkSystem = f._trkSystem;
+   
+   return *this;
+   
+}
+
+
+/*
+void VXDTrack::addHit( IVXDHit* hit ){
+   
+   
+   
+   if ( hit != NULL ){
+      
+      _hits.push_back( hit );
+      
+      // and sort the track again
+      sort( _hits.begin(), _hits.end(), compare_IHit_R_3Dhits );
+      
+      
+      _lcioTrack->addHit( hit->getTrackerHit() );
+      
+   }
+   
+}
+*/
+
+
+
+void VXDTrack::addHit( IMiniVector* MV ){
+   
+   
+   
+   if ( MV != NULL ){
+
+     _hits.push_back( MV );  // so to be able to check the tracks compatibilty
+
+     MiniVector *MinVec = MV->getMiniVector();
+     TrackerHitVec HitVec = MinVec->getTrackerHitVec() ;
+ 
+ 	  
+     for (TrackerHitVec::iterator it = HitVec.begin(); it != HitVec.end() ; ++it ){
+
+       edm4hep::TrackerHit *trkHit = *it ;   
+       
+       //_trkhits.push_back( trkHit );
+     
+       _lcioTrack->addToTrackerHits( *trkHit );
+       
+     }
+     
+     // and sort the track again
+     //sort( _trkhits.begin(), _trkhits.end(), compare_IHit_R_3Dhits );
+     
+   }
+   
+}
+
+
+
+
+
+void VXDTrack::fit() {
+   
+   
+  Fitter fitter( _lcioTrack , _trkSystem , 1 );
+   
+   
+  _lcioTrack->setChi2( fitter.getChi2( 1/*lcio::TrackState::AtIP*/ ) );
+  _lcioTrack->setNdf( fitter.getNdf( 1/*lcio::TrackState::AtIP*/ ) );
+  _chi2Prob = fitter.getChi2Prob( 1/*lcio::TrackState::AtIP*/ );
+   
+  edm4hep::TrackState trkState( *fitter.getTrackState( 1/*lcio::TrackState::AtIP*/ ) ) ;
+  trkState.location = 1/*TrackState::AtIP*/;
+  _lcioTrack->addToTrackStates( trkState );
+      
+}
+
+
+double VXDTrack::getQI() const{
+  
+   
+   double QI = _chi2Prob;
+   
+   // make sure QI is between 0 and 1
+   if (QI > 1. ) QI = 1.;
+   if (QI < 0. ) QI = 0.;
+   
+   return QI;
+   
+}
+
+/*
+double VXDTrack::getPT() const{
+
+  double Omega = _lcioTrack->getOmega();
+  double PT = fabs((0.3*3.5)/(1000*Omega));
+
+  return PT ;
+
+}
+*/
+
+
+
diff --git a/Utilities/KiTrack/src/ILDImpl/VXDTrack.h b/Utilities/KiTrack/src/ILDImpl/VXDTrack.h
new file mode 100644
index 00000000..ad57501f
--- /dev/null
+++ b/Utilities/KiTrack/src/ILDImpl/VXDTrack.h
@@ -0,0 +1,89 @@
+#ifndef VXDTrack_h
+#define VXDTrack_h
+
+#include "edm4hep/Track.h"
+#include "edm4hep/TrackerHit.h"
+#include "TrackSystemSvc/IMarlinTrkSystem.h"
+#include "TrackSystemSvc/IMarlinTrack.h"
+
+#include <vector>
+
+#include "ILDImpl/IVXDHit.h"
+#include "ILDImpl/IMiniVector.h"
+#include "KiTrack/ITrack.h"
+
+#include "Tools/Fitter.h"
+
+//#include "SpacePointBuilder.h"
+// CLHEP tools
+#include "CLHEP/Vector/ThreeVector.h"
+#include "CLHEP/Matrix/SymMatrix.h"
+#include "CLHEP/Matrix/Matrix.h"
+
+
+namespace KiTrackMarlin{
+  /** A class for ITracks containing an lcio::Track at core
+   */
+  class VXDTrack : public ITrack {
+  public:
+      
+    /** @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks
+     */
+    VXDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem );
+    
+    /** @param hits The hits the track consists of 
+     * @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks
+     */
+    //VXDTrack( std::vector< IVXDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem );
+    VXDTrack( std::vector< IMiniVector* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem );
+    VXDTrack( const VXDTrack& f );
+    VXDTrack & operator= (const VXDTrack & f);
+          
+    /** @return a track in the lcio format
+     */
+    edm4hep::Track* getLcioTrack(){ return ( _lcioTrack );}
+    
+    //void addHit( IVXDHit* hit );
+    void addHit( IMiniVector* MV );
+    
+    virtual double getNdf() const { return _lcioTrack->getNdf(); }
+    virtual double getChi2() const { return _lcioTrack->getChi2(); }
+    virtual double getChi2Prob() const { return _chi2Prob; }
+
+    virtual std::vector< IHit* > getHits() const {
+      std::vector<IHit*> hits; 
+      for(unsigned i=0; i<_hits.size();i++) hits.push_back( _hits[i] ); 
+      return hits;
+    }
+ 
+    virtual std::vector< IMiniVector* > getMVs() const {
+      std::vector<IMiniVector*> mvhits; 
+      for(unsigned i=0; i<_hits.size();i++) mvhits.push_back( _hits[i] ); 
+      return mvhits;
+    }
+     
+    virtual double getQI() const;
+    
+    /** Fits the track and sets chi2, Ndf etc.
+     */
+    virtual void fit() ;
+    
+    virtual ~VXDTrack(){ delete _lcioTrack; }
+      
+  protected:
+    /** the hits the track consists of
+     */
+    //std::vector< IVXDHit* > _hits;
+    std::vector< IMiniVector* > _hits;     
+      
+    edm4hep::Track* _lcioTrack;
+      
+    // for fitting
+    MarlinTrk::IMarlinTrkSystem* _trkSystem;
+        
+    double _chi2Prob;
+  };
+}
+#endif
+
+
diff --git a/Utilities/KiTrack/src/KiTrack/Automaton.cc b/Utilities/KiTrack/src/KiTrack/Automaton.cc
new file mode 100644
index 00000000..870f276a
--- /dev/null
+++ b/Utilities/KiTrack/src/KiTrack/Automaton.cc
@@ -0,0 +1,498 @@
+#include "KiTrack/Automaton.h"
+
+#include <iostream>
+//#include "marlin/VerbosityLevels.h"
+
+using namespace KiTrack;
+
+void Automaton::addSegment ( Segment* segment ){
+  if ( segment->getLayer() >= _segments.size() ) { //in case this layer is not included so far
+    _segments.resize( segment->getLayer() + 1 ); //resize the vector, so that the layer of the segment is now included
+  }
+
+  _segments[ segment->getLayer() ].push_back ( segment );
+
+  _nConnections += segment->getChildren().size();
+}
+
+void Automaton::lengthenSegments(){
+
+  // Info A: On skipped layers
+  // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+  //
+  // (read this only if you are interested on how the number of skipped layers is determined)
+  //
+  // The skipped layers are always between the innermost two hits of a segment.
+  // Why? Because the connection between those two hits is the thing that differs
+  // from its parent. Let's assume two 5-segments like those:
+  //           /                                                               //
+  //           \\                                                              //
+  //           //                                                              //
+  //           \\      _layer 2                                                //
+  //            /      _layer 1                                                //
+  // You see how they overlap with all of their hits except the inner one of the child
+  // and the outer one of the parent. As the layer they are on equals the layer of the
+  // innermost point, the child will have layer 1 and the parent layer 2.
+  // (The choice of assigning the layer number of the innermost point and not the outermost
+  // is arbitrary, it could be the other way as well.)
+  //
+  // Now suppose the child skips layer 1: ( in this example a kink in the segment means the layer is hit,
+  // no kink means it is left out.)
+  //
+  //           /                                                               //
+  //           \\                                                              //
+  //           //                                                              //
+  //           \\      _layer 2                                                //
+  //            /      _layer 1                                                //
+  //           /       _layer 0                                                //
+  //
+  // That means the child has now layer 0 and the parent layer 2.
+  // This is no problem, the segment class has an outer and an inner state (simulating skipped layers)
+  // instead of just an int. (to be more precise it has a vector containing the inner state and every layer left out)
+  // Now when we want to make 6-segments (I know the numbers are high, but they help visualising), we would connect
+  // parent and child to a new segment.
+  //
+  //
+  //           /                                                               //
+  //           \                                                               //
+  //           /                                                               //
+  //           \      _layer 2                                                 //
+  //           /      _layer 1                                                 //
+  //          /       _layer 0                                                 //
+  //
+  // So how many layers does this track skip: again 1 layer, so we need a state vector with 2 elements.
+  // (one for layer 0, one for layer 1)
+  //
+  // So we don't care if there are any other skipped layers in the outer part of the segment, we only care about that
+  // bit that won't overlap with parents.
+  // So the easy recipe for the number of skipped layers after making a segment longer is:
+  //   Compare the layer before ( 2 ) to the layer after ( 0 ). The skipped layers are the difference -1
+  //   ( 2 - 0 - 1 = 1 --> segment->setSkippedLayers( 1 );
+  
+  //std::cout << "Combining the shorter segments to longer ones\n";
+  
+  //----------------------------------------------------------------------------------------------//
+  //                                                                                              //
+  // first: we create a new vector of a list of segments                                          //
+  //   to have somewhere we can put the longer segments                                           //
+  //                                                                                              //
+  //----------------------------------------------------------------------------------------------//
+
+  std::vector < std::list < Segment* > > longerSegments;
+   
+  if( _segments.size() > 0 ) longerSegments.resize ( _segments.size() -1 ); //This will have one layer less  
+
+  //----------------------------------------------------------------------------------------------//
+  //                                                                                              //
+  // next: find all the longer segments and store them in the new vector[][]                      //
+  //                                                                                              //
+  //----------------------------------------------------------------------------------------------//
+  
+  unsigned nLongerSegments=0;
+  unsigned nShorterSegments= _segments[0].size();
+  
+  for (unsigned layer = 1; layer < _segments.size(); layer++){ //over all layers where there still can be something below
+    std::list<Segment*> segments = _segments[layer];
+    for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg != segments.end(); iSeg++){ //over all segments in this layer
+      nShorterSegments++;
+         
+      Segment* parent = *iSeg;
+      
+      std::list <Segment*> children = parent->getChildren();
+         
+      for ( std::list<Segment*>::iterator iChild=children.begin(); iChild !=children.end(); iChild++){ //over all children of this parent
+	Segment* child = *iChild;
+            
+	//Combine the parent and the child to form a new longer segment
+        
+	//take all the hits from the parent
+	std::vector < IHit* > hits = parent->getHits();
+        
+	//and also add the inner hit from the child
+	hits.insert( hits.begin(), child->getHits().at(0) );
+        
+	//make the new (longer) segment
+	Segment* newSegment = new Segment ( hits );
+	nLongerSegments++;
+        
+	//set the layer to the layer of the childsegment
+	unsigned newLayer = child->getLayer();
+	newSegment->setLayer ( newLayer );
+        
+	// Set the skipped layers.                  For an explanation see Info A above
+	int skippedLayers = parent->getLayer() - child->getLayer() - 1;
+	if( skippedLayers < 0 ) throw InvalidParameter( "skippedLayers can't be < 0!" );
+	newSegment->setSkippedLayers( unsigned(skippedLayers) );      //
+        /*
+	std::cout << "Created longer segment: " << parent->getHits().size()
+		  << "hits -->" << newSegment->getHits().size()
+		  << " hits, layer = " << newLayer
+		  << ", skipped layers = " << skippedLayers <<"\n";
+	std::cout << "Combined: " << child->getInfo() << "<--with-->" << parent->getInfo() << "\n";
+	*/
+	// In a next step we want to again establish the conenctions between the longer segments (so we can do the 
+	// Automaton and later combine them and then do it all again... ).
+	// If we just created the Segments and dumped the old ones, we would have no idea what of the new, longer
+	// Segments we can connect.
+	// We could add some other container to store the possible connections of the longer Segments, but maybe
+	// it's the easiest approach to use, what is already there: the shorter Segments.
+	//
+	// So when we combine two shorter segments, we store the new longer Segment as a parent or child.
+	// Child, when the longer Segment goes on towards the inside, Parent if it continues on to the outside.
+	// So the shorter Segments kind of act as joints, that hold the longer Segments together.
+	//
+	// Let's visulaize that, so that it makes more sense:
+	// Let's have a look at 3 2-hit segments:
+	//
+	//          /       2-hit-Segment A
+	//          \       2-hit-Segment B
+	//          /       2-hit-Segment C
+	//
+	// Obviously we can make 2 3-hit segments out of this:
+	//
+	//          / -->   /       3-hit-Segment D
+	//          \       \  \    .
+	//          / -->      /    3-hit-Segment E
+	// 
+	// In the 2-hit-Segment B we store the 3-hit-Segments D and E as parent and child (while deleting A and C
+	// as parent and child, because that is now not needed anymore )
+	//
+	// So when we want to connect the 3-hit-Segments, all we have to do is iterate over all 2-hit-Segments which
+	// then only have 3-hit-Segments as parents and children.
+	// When we come to Segment B, we see that D is a parent and E is a child, thus we connect them. Or to be more
+	// precise, we connect them, if the criteria do say so.
+	//
+	// So, yes B acts like a joint connecting D and E
+	// 
+	// Erase the connection from the child to the parent segment and replace it with a link to the new
+	// (longer) segment. ( and vice versa ) This way we can connect the longer segments easily after.
+	child->deleteParent( parent );
+	child->addParent ( newSegment );
+	parent->deleteChild ( child );
+	parent->addChild ( newSegment );
+	// So now the new longer segment is a child of the old parent and a parent of the childsegment.
+        
+        
+	// Save the new segment in the new vector[][]
+	longerSegments[newLayer].push_back( newSegment );
+      }
+    }
+  }
+
+  //std::cout << " Made " << nLongerSegments << " longer segments from " << nShorterSegments << " shorter segments.\n";
+  
+  //----------------------------------------------------------------------------------------------//
+  //                                                                                              //
+  // Connect the new (longer) segments                                                            //
+  //                                                                                              //
+  //----------------------------------------------------------------------------------------------//
+  
+  //std::cout << "Next connecting the new longer segments\n";
+     
+  unsigned nConnections=0;
+  unsigned nPossibleConnections=0;
+  
+  for ( unsigned layer = 1; layer + 1 < _segments.size(); layer++ ){ // over all layers (of course the first and the last ones are spared out because there is nothing more above or below
+    std::list<Segment*> segments = _segments[layer];
+    for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg != segments.end(); iSeg++ ){ //over all (short) segments in this layer
+      Segment* segment = *iSeg;
+         
+      std::list<Segment*> parents = segment->getParents();
+      std::list<Segment*> children = segment->getChildren();
+      
+      for ( std::list<Segment*>::iterator iParent = parents.begin(); iParent != parents.end(); iParent++ ){ // over all parents of the segment
+	Segment* parent = *iParent;
+	for ( std::list<Segment*>::iterator iChild = children.begin(); iChild != children.end(); iChild++ ){ // over all children of the segment
+	  Segment* child = *iChild;
+	  
+	  // Check if they are compatible
+	  bool areCompatible = true;
+	  ICriterion* theFailedCrit = NULL; 
+          
+	  //check all criteria (or at least until one returns false)
+	  for ( unsigned iCrit = 0; iCrit < _criteria.size(); iCrit++ ){
+	    if ( _criteria[iCrit]->areCompatible ( parent , child ) == false ){
+	      areCompatible = false;
+	      theFailedCrit = _criteria[iCrit];
+	      break;
+	    }
+	  }
+               
+	  if ( areCompatible ){
+	    //connect parent and child (i.e. connect the longer segments we previously created)
+	    child->addParent( parent );
+	    parent->addChild( child );
+            
+	    nConnections++;
+            
+	    //std::cout << "Connected: " << child->getInfo() << "<--with-->" << parent->getInfo() << "\n";
+	  }
+	  else{
+	    //std::cout << "NOT Connected: " << child->getInfo() << "<--XXXX-->" << parent->getInfo() << "\n";
+	    //if( theFailedCrit != NULL ) std::cout << "Failed first at criterion: " << theFailedCrit->getName() << "\n";
+	  }
+                         
+	  nPossibleConnections++;
+	}
+      }
+    }
+  }
+  _nConnections = nConnections;
+
+  //std::cout << "Made " << nConnections << " of " << nPossibleConnections << " possible connections \n";
+  
+  //----------------------------------------------------------------------------------------------//
+  //                                                                                              //
+  //   Finally: replace the vector<list<segment*>> of the old segments with the new one           //
+  //                                                                                              //
+  //----------------------------------------------------------------------------------------------//
+  
+  //delete all old Segments:
+  for( unsigned i=0; i<_segments.size(); i++){
+    std::list<Segment*>& segments = _segments[i];
+    for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg != segments.end(); iSeg++ ){
+      Segment* segment = *iSeg;
+      delete segment;
+    }
+    segments.clear();
+  }
+   
+  // And replace with the newer ones
+  _segments = longerSegments;
+}
+
+void Automaton::doAutomaton(){
+
+  bool hasChanged = true;
+  int nIterations = -1;
+  
+  while ( hasChanged == true ){ //repeat this until no more changes happen (this should always be equal or smaller to the number of layers - 1
+    hasChanged = false;
+    nIterations++;
+    
+    for ( int layer = _segments.size()-1; layer >= 0; layer--){ //for all layers from outside in
+      std::list <Segment*> segments = _segments[layer];
+      for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg!= segments.end(); iSeg++ ){ //for all segments in the layer
+	Segment* parent= *iSeg;
+            
+	//Simulate skipped layers
+	std::vector < int >& state = parent->getState();
+	
+	for ( int j= state.size()-1; j>=1; j--){
+	  if ( state[j] == state[j-1] ){
+	    state[j]++;
+	    hasChanged = true; //something changed
+	  }
+	}
+	
+	if ( parent->isActive() ){
+	  bool isActive = false; //whether the segment is active (i.e. still changing). This will be changed in the for loop, if it is active
+	  
+	  //Check if there is a neighbor
+	  std::list <Segment*> children = parent->getChildren();
+                         
+	  for ( std::list<Segment*>::iterator iChild=children.begin(); iChild != children.end(); iChild++ ){// for all children
+	    Segment* child = *iChild;
+
+	    if ( child->getOuterState() == parent->getInnerState() ){  //Only if they have the same state
+	      parent->raiseState(); //So it has a neighbor --> raise the state
+
+	      hasChanged = true; //something changed
+	      isActive = true;
+	      
+	      break; //It has a neighbor, we raised the state, so we need not check again in this iteration
+	    }
+	  }
+               
+	  parent->setActive( isActive );
+	}
+      }
+    }
+  }
+
+  //std::cout << "Automaton performed using " << nIterations << " iterations.\n";
+}
+
+void Automaton::cleanBadStates(){
+
+  unsigned nErasedSegments = 0;
+  unsigned nKeptSegments = 0;
+
+  for( unsigned layer=0; layer < _segments.size(); layer++ ){//for every layer
+    std::list <Segment*> & segments = _segments[layer]; // We want to change things in the original list! Therefore the reference operator
+    for( std::list<Segment*>::iterator iSeg= segments.begin(); iSeg != segments.end(); iSeg++ ){//over every segment
+      Segment* segment = *iSeg;
+
+      if( segment->getInnerState() == (int) layer ){ //the state is alright (equals the layer), this segment is good
+	nKeptSegments++;
+      }
+      else { //state is wrong, delete the segment
+	nErasedSegments++;
+
+	//erase it from all its children
+	std::list <Segment*> children = segment->getChildren();
+	
+	for (std::list<Segment*>::iterator iChild = children.begin(); iChild != children.end(); iChild++ ){
+	  (*iChild)->deleteParent ( segment );
+	  _nConnections--;
+	}
+
+	//erase it from all its parents
+	std::list <Segment*> parents = segment->getParents();
+
+	for (std::list<Segment*>::iterator iParent = parents.begin(); iParent!= parents.end(); iParent++){
+	  (*iParent)->deleteChild ( segment );
+	  _nConnections--;
+	}
+
+	//erase from the automaton
+	delete *iSeg;
+	iSeg = segments.erase( iSeg ); // erase the segment and update the iterator (updating is important!!!)
+      }
+    }
+  }
+
+  //std::cout << "Erased segments because of bad states= " << nErasedSegments << "\n";
+  //std::cout << "Kept segments because of good states= " << nKeptSegments << "\n";
+}
+
+void Automaton::resetStates(){
+  for ( unsigned layer = 0; layer < _segments.size(); layer++ ){ //over all layers
+    std::list<Segment*> segments = _segments[layer];
+    
+    for ( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg != segments.end(); iSeg++ ){ //over all segments in the layer
+      (*iSeg)->resetState();
+      (*iSeg)->setActive( true );
+    }
+  }
+}
+
+void Automaton::cleanBadConnections(){
+
+  unsigned nConnectionsKept = 0;
+  unsigned nConnectionsErased = 0;
+  
+  for ( int layer = _segments.size()-1 ; layer >= 1 ; layer-- ){ //over all layers from outside in. And there's no need to check layer 0, as it has no children.
+    std::list<Segment*> segments = _segments[layer];
+    for ( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg!=segments.end(); iSeg++ ){ // over all segments in the layer
+      Segment* parent = *iSeg;
+      std::list < Segment* > children = parent->getChildren();
+      
+      for ( std::list<Segment*>::iterator iChild = children.begin(); iChild != children.end(); iChild++ ){ //over all children the segment has got
+	Segment* child = *iChild;
+	
+	bool areCompatible = true; //whether segment and child are compatible
+	
+	//check all criteria (or at least until the first false pops up)
+	for ( unsigned iCrit=0; iCrit < _criteria.size() ; iCrit++ ){
+	  if ( _criteria[iCrit]->areCompatible( parent , child ) == false ){
+	    areCompatible = false;
+	    break; //no need to continue, now that we know, they're not compatible
+	  }
+	}
+	
+	if ( areCompatible == false ){ // they are not compatible --> erase the connection
+	  nConnectionsErased++;
+	  _nConnections--;
+          
+	  //erase the connection:
+	  parent->deleteChild ( child );
+	  child->deleteParent ( parent );
+          
+	  //A small note here: although we deleted a child from the vector, this doesn't mean we have to do iSeg--!
+	  //Because we copied the value of segment->getChildren to the vector children. And this one doesn't change!
+	}
+	else{
+	  nConnectionsKept++;
+	}
+      }
+    }
+  }
+  
+  //std::cout << "Erased bad connections= " << nConnectionsErased << "\n";
+  //std::cout << "Kept good connections= " << nConnectionsKept << "\n";
+}
+
+std::vector < std::vector< IHit* > > Automaton::getTracksOfSegment ( Segment* segment, std::vector< IHit*> hits , unsigned minHits ){
+
+  std::vector < std::vector< IHit* > > tracks; //the vector of the tracks to be returned
+
+  std::vector <IHit*> segHits = segment->getHits(); // the hits of the segment
+
+  //add the outer hit
+  if ( segHits.back()->isVirtual() == false ) hits.push_back ( segHits.back() );  //Of course add only real hits to the track
+  
+  std::list <Segment*> children = segment->getChildren();
+
+  if ( children.empty() ){ //No more children --> we are at the bottom --> start a new Track here
+    //add the rest of the hits to the vector
+    for ( int i = segHits.size()-2 ; i >= 0; i--){
+      if ( segHits[i]->isVirtual() == false ) hits.push_back ( segHits[i] );
+    }
+          
+    if ( hits.size() >= minHits ){
+      //add this to the tracks
+      tracks.push_back ( hits );
+    }
+  }
+  else{// there are still children below --> so just take all their tracks and do it again
+    for ( std::list<Segment*>::iterator iChild=children.begin(); iChild!= children.end(); iChild++){ //for all children
+      std::vector < std::vector< IHit* > > newTracks = getTracksOfSegment( *iChild , hits );
+      for (unsigned int j=0; j < newTracks.size(); j++){//for all the tracks of the child
+	tracks.push_back ( newTracks[j] );
+      }
+    }
+  }
+
+  return tracks;
+}
+
+std::vector < std::vector< IHit* > > Automaton::getTracks( unsigned minHits ){
+
+  std::vector < std::vector< IHit* > > tracks;
+  std::vector <IHit*> emptyHitVec;
+
+  for ( unsigned layer = 0 ; layer < _segments.size() ; layer++ ){ //over all layers
+    std::list<Segment*> segments = _segments[layer];
+    for ( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg != segments.end(); iSeg++ ){ //over all segments
+      Segment* segment = *iSeg;
+      // by fucd: comment "if" in new ILC version of Automaton, why?
+      if ( segment->getParents().empty() ){ // if it has no parents it is the end of a possible track
+	// get the tracks from the segment
+	std::vector < std::vector< IHit* > > newTracks = getTracksOfSegment( segment , emptyHitVec , minHits );
+	
+	// and add them to the vector of all tracks
+	tracks.insert( tracks.end() , newTracks.begin() , newTracks.end() );
+      }
+    }
+  }
+  return tracks;
+}
+
+std::vector <const Segment*> Automaton::getSegments() const{
+   
+  std::vector <const Segment*> segments;
+  
+  for( unsigned layer=0; layer < _segments.size(); layer++ ){
+    segments.insert( segments.end() , _segments[layer].begin() , _segments[layer].end() );
+  }
+     
+  return segments; 
+}
+
+Automaton::~Automaton(){
+  //delete the segments
+  for( unsigned layer=0; layer < _segments.size(); layer++){ //over all layers
+    std::list<Segment*> segments = _segments[layer];
+    for( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg!=segments.end(); iSeg++ ){ //over all segments
+      delete *iSeg;
+    }
+  }
+}
+
+
+
+
+
+
+
diff --git a/Utilities/KiTrack/src/KiTrack/HopfieldNeuralNet.cc b/Utilities/KiTrack/src/KiTrack/HopfieldNeuralNet.cc
new file mode 100644
index 00000000..6597b191
--- /dev/null
+++ b/Utilities/KiTrack/src/KiTrack/HopfieldNeuralNet.cc
@@ -0,0 +1,217 @@
+#include "KiTrack/HopfieldNeuralNet.h"
+
+#include <cmath>
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <random>
+
+
+using namespace KiTrack;
+
+HopfieldNeuralNet::HopfieldNeuralNet( std::vector < std::vector <bool> > G , std::vector < double > QI , std::vector < double > states , double omega) {
+
+   unsigned int nNeurons = G.size();
+
+   
+   
+   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   // Check the validity of the input parameters
+   
+   
+   std::stringstream s;
+   s << "HopfieldNeuralNet: ";
+   
+   // Is G a square matrix?
+   for( unsigned i=0; i< nNeurons; i++ ){
+      
+      if( G[i].size() != nNeurons ){
+         
+         s << "G must be a square matrix!!! G[" << i << "].size() == " << G[i].size() << " != G.size() (" << nNeurons << ")\n";
+         throw InvalidParameter( s.str() );
+         
+      }
+      
+   }
+   
+   // Does the QI vector have the right size?
+   if( QI.size() != nNeurons ){
+      
+      s << "The QI vector must have the same size as G! QI.size() == " << QI.size() << " != G.size() (" << nNeurons << ")\n";
+      throw InvalidParameter( s.str() );
+      
+   }
+   
+   // Are all the Quality Indicators in the range 0 - 1
+   for( unsigned i=0; i< nNeurons; i++ ){
+      
+      if( ( QI[i] < 0. ) || ( QI[i] > 1. ) ){
+         
+         s << "The QI must be between 0 and 1, QI[" << i << "] == " << QI[i] << " is not a valid value!\n";
+         
+      }
+      
+   }
+   
+   // Does the states vector have the right size?
+   if( states.size() != nNeurons ){
+      
+      s << "The vector of the states must have the same size as G! states.size() == " << states.size() << " != G.size() (" << nNeurons << ")\n";
+      throw InvalidParameter( s.str() );
+      
+   }
+   
+   // Are all the states in the range 0 - 1
+   for( unsigned i=0; i< nNeurons; i++ ){
+      
+      if( ( states[i] < 0. ) || ( states[i] > 1. ) ){
+         
+         s << "The states must be between 0 and 1, states[" << i << "] == " << states[i] << " is not a valid value!\n";
+         
+      }
+      
+   }
+   
+   // Is omega in the range from  0 to 1
+   if( ( omega < 0. ) || ( omega > 1. ) ){
+      
+      s << "Omega must be in the range from 0 to 1, omega == " << omega << " is not a valid value!\n";
+      
+   }
+   // End of checking the parameters
+   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   _omega = omega;
+   _States = states;
+   
+   // resize the vectors.
+   _States.resize( nNeurons );
+   _w0.resize( nNeurons );
+   _W.resize( nNeurons );
+   _order.resize( nNeurons);
+   
+   for ( unsigned int i =0; i < nNeurons; i++){
+      
+      // resize the vectors of the matrix W
+      _W[i].resize( nNeurons );
+      
+      
+      // initialise the order vector
+      _order[i]=i;                      //the order now is 0,1,2,3... (will be changed to a random sequence in the iteration)
+      
+   }
+   
+   
+   //calculate _w0
+   for (unsigned int i=0; i < QI.size(); i++) _w0[i] = omega * QI[i];
+   
+   
+   
+   // Build the W matrix. (the matrix of the influences including their force)
+   
+   double comp = 1;
+   if (nNeurons > 0 ) comp = (1. - omega) / double (nNeurons);
+   
+
+   for (unsigned int i=0; i< nNeurons ; i++){ 
+
+      for (unsigned int j=0; j< nNeurons ; j++){
+       
+         if (i == j) _W[i][j] = 0.; //diagonal elements are 0 --> whatever the matrix G says here is ignored.
+            
+         else{  
+            
+            if ( G[i][j] == 1 ) _W[i][j] = -1;   //Neurons are incompatible
+            
+            else _W[i][j] =  comp;   //Neurons are compatible
+            
+         }
+         
+      }
+      
+   }
+   
+  
+   
+
+
+   _T = 0;
+   _TInf = 0;
+   
+   _isStable = false;
+   _limitForStable = 0.01;
+
+
+
+}
+
+
+
+double HopfieldNeuralNet::activationFunction ( double state , double T ){
+   
+   
+   double y = 1;
+   
+   if (T > 0) y = 0.5 * ( 1 + tanh( state / T ) ); //if T==0  tanh( infinity ) gives 1.
+
+
+   return y;
+   
+   
+}
+
+
+
+
+bool HopfieldNeuralNet::doIteration(){
+   
+   _isStable = true;
+   
+   // initialize the random generator
+   std::random_device rng;
+   std::mt19937 urng(rng());
+
+   shuffle ( _order.begin() , _order.end() , urng ); //shuffle the order
+   
+   for (unsigned int i=0; i<_States.size() ; i++){ //for all entries of the vector
+      
+      unsigned iNeuron = _order[i];
+      
+      
+      double y;
+      
+      y = _w0[iNeuron];
+      
+      //matrix vector multiplication (or one line of it to be precise)  
+      for (unsigned int j=0; j< _W[iNeuron].size(); j++){ 
+       
+         y  += _W[iNeuron][j] * _States[j]; 
+         
+      }
+      
+      y = activationFunction ( y , _T );
+      
+      // check if the change was big enough that the Network is not stable
+      if ( fabs( _States[iNeuron] - y ) > _limitForStable ) _isStable = false;
+      
+      // update the state
+      _States[iNeuron] = y;
+      
+   }
+   
+   
+   
+   // after the iteration, we need to calculate a new tempereatur _T
+   
+   _T = 0.5* ( _T + _TInf);
+   
+   
+   return _isStable;
+   
+}
+
+
+
+
+
+
diff --git a/Utilities/KiTrack/src/KiTrack/IHit.cc b/Utilities/KiTrack/src/KiTrack/IHit.cc
new file mode 100644
index 00000000..e4381d84
--- /dev/null
+++ b/Utilities/KiTrack/src/KiTrack/IHit.cc
@@ -0,0 +1,28 @@
+#include "KiTrack/IHit.h"
+
+#include <cmath>
+#include <sstream>
+
+using namespace KiTrack;
+
+float IHit::distTo( IHit* otherHit ){
+   
+   
+   
+   float dx = otherHit->getX() - _x;
+   float dy = otherHit->getY() - _y;
+   float dz = otherHit->getZ() - _z;
+      
+   return sqrt( dx*dx + dy*dy + dz*dz );
+   
+}
+
+std::string IHit::getPositionInfo(){
+   
+   std::stringstream info;
+   
+   info << "(" << _x << "," << _y << "," << _z << ")";
+   
+   return info.str();
+   
+}
\ No newline at end of file
diff --git a/Utilities/KiTrack/src/KiTrack/Segment.cc b/Utilities/KiTrack/src/KiTrack/Segment.cc
new file mode 100644
index 00000000..0fd8916f
--- /dev/null
+++ b/Utilities/KiTrack/src/KiTrack/Segment.cc
@@ -0,0 +1,67 @@
+#include "KiTrack/Segment.h"
+
+#include <sstream>
+
+using namespace KiTrack;
+
+Segment::Segment( std::vector <IHit*> hits){ 
+
+   _hits = hits; 
+   
+   _state.push_back(0); 
+   
+   _children.clear(); 
+   _parents.clear();
+
+   _active = true;
+   
+   _layer=0;
+}
+
+
+
+Segment::Segment( IHit* hit){ 
+   
+   _hits.push_back( hit) ;
+   _state.push_back(0); 
+   _children.clear(); 
+   _parents.clear();
+   
+   _active = true;
+   
+   _layer=0;
+}
+
+
+
+void Segment::resetState(){
+   
+   
+   for ( unsigned i = 0; i <_state.size(); i++){
+      
+      _state[i] = 0;
+      
+   }
+   
+}
+
+std::string Segment::getInfo(){
+   
+ 
+   std::stringstream info;
+   
+   for( unsigned i=0; i<_hits.size(); i++ ) info << _hits[i]->getPositionInfo();
+   
+   info << "[";
+   for( unsigned i=0; i+1<_state.size(); i++ ) info << _state[i] << ",";
+   info << _state.back() << "]";
+   
+   return info.str();
+   
+   
+}
+
+
+
+   
+
diff --git a/Utilities/KiTrack/src/KiTrack/SegmentBuilder.cc b/Utilities/KiTrack/src/KiTrack/SegmentBuilder.cc
new file mode 100644
index 00000000..7a19c4df
--- /dev/null
+++ b/Utilities/KiTrack/src/KiTrack/SegmentBuilder.cc
@@ -0,0 +1,117 @@
+#include "KiTrack/SegmentBuilder.h"
+
+// ----- include for verbosity dependend logging ---------
+//#include "marlin/VerbosityLevels.h"
+#include <iostream>
+
+using namespace KiTrack;
+
+SegmentBuilder::SegmentBuilder(  std::map< int , std::vector< IHit* > > map_sector_hits ): 
+  _map_sector_hits( map_sector_hits){}
+
+Automaton SegmentBuilder::get1SegAutomaton(){
+  /**********************************************************************************************/
+  /*                Create and fill a map for the segments                                      */
+  /**********************************************************************************************/
+  std::map< int , std::vector< IHit* > >::iterator itSecHit; // Sec = sector , Hit = hits
+  std::map< int , std::vector< Segment* > > map_sector_segments;
+  std::map< int , std::vector< Segment* > > ::iterator itSecSeg; // Sec = sector , Seg = segments
+        
+  unsigned nCreatedSegments=0;
+     
+  for ( itSecHit = _map_sector_hits.begin(); itSecHit!=_map_sector_hits.end(); itSecHit++ ){ //over all sectors
+    // All the hits in the sector
+    int sector = itSecHit->first;
+    std::vector <IHit*> hits = itSecHit->second;
+    for ( unsigned int i=0; i < hits.size(); i++ ){ //over every hit in the sector
+      // create a Segment
+      Segment* segment = new Segment( hits[i] );
+      segment->setLayer( hits[i]->getLayer() );
+      
+      // Store the segment in its map
+      map_sector_segments[sector].push_back( segment );
+      
+      nCreatedSegments++;
+    }
+  }
+     
+  //std::cout << " Number of created 1-segments: " << nCreatedSegments <<"\n";
+  
+  /**********************************************************************************************/
+  /*                Now check all 1-Segments and connect them to others                         */
+  /*                Afterwards store them in an Automaton                                       */
+  /**********************************************************************************************/
+  
+  unsigned nConnections=0;
+  unsigned nStoredSegments = 0;
+  
+  Automaton automaton;
+  
+  for ( itSecSeg = map_sector_segments.begin(); itSecSeg != map_sector_segments.end(); itSecSeg++ ){ // over all sectors
+    // All the segments with one certain code
+    int sector = itSecSeg->first;
+    std::vector <Segment*> segments = itSecSeg->second;
+          
+    // Now find out, what the allowed codes to connect to are:
+    std::set <int> targetSectors;
+    
+    for ( unsigned i=0; i < _sectorConnectors.size(); i++ ){ // over all IHitConnectors
+      // get the allowed targets
+      std::set <int> newTargetSectors = _sectorConnectors[i]->getTargetSectors( sector );
+      
+      //insert them into our set
+      targetSectors.insert( newTargetSectors.begin() , newTargetSectors.end() );
+    }
+          
+    for ( unsigned int i=0; i< segments.size(); i++ ){ //over all segments within the sector
+      Segment* parent = segments[i]; 
+      
+      for ( std::set<int>::iterator itTarg = targetSectors.begin(); itTarg!=targetSectors.end(); itTarg++ ){ // over all target codes
+	int targetSector = *itTarg;
+	std::vector <Segment*> targetSegments = map_sector_segments[ targetSector ];
+                    
+	for ( unsigned int j=0; j < targetSegments.size(); j++ ){ // over all segments in the target sector
+	  Segment* child = targetSegments[j];
+	  bool areCompatible = true;
+	  ICriterion* theFailedCrit = NULL; 
+                         
+	  for (unsigned int iCrit = 0; iCrit < _criteria.size(); iCrit++){
+	    if ( _criteria[iCrit]->areCompatible( parent , child ) == false ){
+	      areCompatible = false;
+	      theFailedCrit = _criteria[iCrit];
+	      break;
+	    }
+	  }
+                         
+	  if ( areCompatible ){ //the connection was successful 
+	    parent->addChild( child );
+	    child->addParent( parent );
+            
+	    nConnections++;              
+	    //std::cout << "Connected: " << child->getInfo() << "<--with-->" << parent->getInfo() << "\n"; 
+	  } 
+	  else{
+	    //std::cout << "NOT Connected: " << child->getInfo() << "<--XXXX-->" << parent->getInfo() << "\n";
+	    //if( theFailedCrit != NULL ) std::cout << "Failed first at criterion: " << theFailedCrit->getName() << "\n";
+	  }
+	}
+      }
+         
+      // Store the segment in the automaton
+      automaton.addSegment( parent );
+      nStoredSegments++;
+    }      
+  }
+      
+  //std::cout << "Number of connections made " << nConnections <<"\n";
+  //std::cout << "Number of 1-segments, that got stored in the automaton: " << nStoredSegments <<"\n";
+    
+  return automaton;
+}
+
+
+
+
+
+
+
diff --git a/Utilities/KiTrack/src/Tools/FTDHelixFitter.cc b/Utilities/KiTrack/src/Tools/FTDHelixFitter.cc
new file mode 100644
index 00000000..2f0492a0
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/FTDHelixFitter.cc
@@ -0,0 +1,124 @@
+#include "Tools/FTDHelixFitter.h"
+
+#include <sstream>
+#include <algorithm>
+#include <cmath>
+
+#include "edm4hep/TrackerHit.h"
+#include "UTIL/BitSet32.h"
+#include "UTIL/ILDConf.h"
+#include "UTIL/LCTrackerConf.h"
+//#include "marlin/VerbosityLevels.h"
+#include "TrackSystemSvc/HelixFit.h"
+
+#include "Tools/KiTrackMarlinTools.h"
+
+
+FTDHelixFitter::FTDHelixFitter( std::vector<edm4hep::ConstTrackerHit> trackerHits ){
+  _trackerHits = trackerHits;
+  fit();
+}
+
+FTDHelixFitter::FTDHelixFitter( edm4hep::Track* track ){
+  _trackerHits.clear();
+  //int nHits = track->trackerHits_size();
+  std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(_trackerHits));
+  //for(int i=0;i<nHits;i++){
+  //  edm4hep::ConstTrackerHit* hit = &track->getTrackerHits(i);
+  //  _trackerHits.push_back(hit);
+  //}
+  fit();
+}
+
+void FTDHelixFitter::fit(){
+  std::sort( _trackerHits.begin(), _trackerHits.end(), KiTrackMarlin::compare_TrackerHit_z );
+   
+  int nHits = _trackerHits.size();
+  int iopt = 2;
+  float chi2RPhi;
+  float chi2Z;
+  
+  if( nHits < 3 ){
+    std::stringstream s;
+    s << "FTDHelixFitter::fit(): Cannot fit less with less than 3 hits. Number of hits =  " << nHits << "\n";
+      
+    throw FTDHelixFitterException( s.str() );
+  }
+   
+  double* xh  = new double[nHits];
+  double* yh  = new double[nHits];
+  float*  zh  = new float[nHits];
+  double* wrh = new double[nHits];
+  float*  wzh = new float[nHits];
+  float*  rh  = new float[nHits];
+  float*  ph  = new float[nHits];
+  
+  float par[5];
+  float epar[15];
+  
+  for( int i=0; i<nHits; i++ ){
+    edm4hep::ConstTrackerHit hit = _trackerHits[i];
+      
+    xh[i] = hit.getPosition()[0];
+    yh[i] = hit.getPosition()[1];
+    zh[i] = hit.getPosition()[2];
+      
+    float resZ = 0.1;
+    wzh[i] = 1.0/( resZ * resZ );
+      
+    rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i]));
+    ph[i] = atan2(yh[i],xh[i]);
+    if (ph[i] < 0.)  ph[i] = 2.*M_PI + ph[i]; 
+            
+    if( UTIL::BitSet32( hit.getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){
+      float sigX = hit.getCovMatrix()[0];
+      float sigY = hit.getCovMatrix()[2];
+      wrh[i] = 1/sqrt( sigX*sigX + sigY*sigY );
+    }
+    else {
+      //TrackerHitPlane* hitPlane = dynamic_cast<TrackerHitPlane*>( hit );
+      //wrh[i] = double(1.0/( hitPlane->getdU()*hitPlane->getdU() + hitPlane->getdV()*hitPlane->getdV() ) );
+      wrh[i] = double(1.0/( hit.getCovMatrix(2)*hit.getCovMatrix(2) + hit.getCovMatrix(5)*hit.getCovMatrix(5) ));
+    }
+  }
+     
+  MarlinTrk::HelixFit helixFitter;
+   
+  helixFitter.fastHelixFit(nHits, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+  par[3] = par[3]*par[0]/fabs(par[0]);
+   
+  _omega = par[0];
+  _tanLambda = par[1];
+  _phi0 = par[2];
+  _d0 = par[3];
+  _z0 = par[4];
+  
+  float chi2 = chi2RPhi+chi2Z;
+  int Ndf = 2*nHits-5;
+     
+  delete[] xh;
+  delete[] yh;
+  delete[] zh;
+  delete[] wrh;
+  delete[] wzh;
+  delete[] rh;
+  delete[] ph;
+  xh  = NULL; 
+  yh  = NULL; 
+  zh  = NULL; 
+  wrh = NULL; 
+  wzh = NULL; 
+  rh = NULL; 
+  ph = NULL; 
+     
+  //streamlog_out(DEBUG1) << "chi2 = " << chi2 << ", Ndf = " << Ndf << "\n";
+  
+  _chi2 = chi2;
+  _Ndf = Ndf;
+  
+  return;
+}
+
+
+
+
diff --git a/Utilities/KiTrack/src/Tools/Fitter.cc b/Utilities/KiTrack/src/Tools/Fitter.cc
new file mode 100644
index 00000000..13ae3aab
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/Fitter.cc
@@ -0,0 +1,598 @@
+#include "Tools/Fitter.h"
+
+#include <algorithm>
+
+//#include "marlin/Global.h"
+//#include "UTIL/LCTrackerConf.h"
+#include <UTIL/ILDConf.h>
+
+#include <DD4hep/DD4hepUnits.h>
+#include <DD4hep/Detector.h>
+
+#include "TrackSystemSvc/HelixTrack.h"
+#include "DataHelper/Navigation.h"
+#include "Tools/KiTrackMarlinTools.h"
+
+typedef std::vector<edm4hep::ConstTrackerHit> TrackerHitVec;
+using namespace MarlinTrk;
+
+// by fucd: 3.5->3.0 default, will be read from GeoSvc
+// if compare to Marlin, should change to 3.5
+float Fitter::_bField = 3.5;//later on overwritten with the value read by geo file
+
+void Fitter::init_BField(){
+
+  // B field from DD4hep
+  /*
+  dd4hep::Detector & lcdd = dd4hep::Detector::getInstance();
+  const double pos[3]={0,0,0}; 
+  double bFieldVec[3]={0,0,0}; 
+  lcdd.field().magneticField(pos,bFieldVec); // get the magnetic field vector from DD4hep
+  _bField = bFieldVec[2]/dd4hep::tesla; // z component at (0,0,0)    
+  */
+
+}
+
+bool compare_TrackerHit_z( edm4hep::TrackerHit* a, edm4hep::TrackerHit* b ){
+  return ( fabs(a->getPosition()[2]) < fabs( b->getPosition()[2]) ); //compare their z values
+}
+
+bool compare_TrackerHit_R( edm4hep::TrackerHit* a, edm4hep::TrackerHit* b ){
+  double Rad_a2 = (a->getPosition()[0]*a->getPosition()[0]) + (a->getPosition()[1]*a->getPosition()[1]) ;
+  double Rad_b2 = (b->getPosition()[0]*b->getPosition()[0]) + (b->getPosition()[1]*b->getPosition()[1]) ;
+  
+  return ( Rad_a2 < Rad_b2 ); //compare their radii
+}
+
+Fitter::Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem ): _trkSystem( trkSystem ){
+  _trackerHits.clear();
+
+  std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(_trackerHits));
+  //_trackerHits = track->getTrackerHits();
+
+  fit();
+}
+
+Fitter::Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem, int VXDFlag ): _trkSystem( trkSystem ){
+  _trackerHits.clear();
+  std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(_trackerHits));
+  //_trackerHits = track->getTrackerHits();
+  fitVXD();
+}
+
+Fitter::Fitter( std::vector<edm4hep::ConstTrackerHit> trackerHits , MarlinTrk::IMarlinTrkSystem* trkSystem ): _trkSystem( trkSystem ){
+  _trackerHits = trackerHits;
+  fit();
+}
+
+void Fitter::fitVXD(){
+  //create the MarlinTrk
+  _marlinTrk = _trkSystem->createTrack();
+
+  /**********************************************************************************************/
+  /*       Add the hits to the MarlinTrack                                                      */
+  /**********************************************************************************************/
+   
+  // hits are in reverse order 
+  std::sort( _trackerHits.begin(), _trackerHits.end(), KiTrackMarlin::compare_TrackerHit_R );
+  // now at [0] is the hit with the smallest |z| and at [1] is the one with a bigger |z| and so on
+  // So the direction of the hits when following the index from 0 on is:
+  // from inside out: from the IP into the distance. 
+  // (It is important to keep in mind, in which direction we fit, when using MarlinTrk)
+  
+  TrackerHitVec::iterator it;
+     
+  unsigned number_of_added_hits = 0;
+  unsigned ndof_added = 0;
+  std::vector< edm4hep::TrackerHit* > added_hits;
+  std::vector< edm4hep::TrackerHit* > added_hits_2D;
+  
+  for( it = _trackerHits.begin() ; it != _trackerHits.end() ; ++it ) {
+    edm4hep::TrackerHit* trkHit = Navigation::Instance()->GetTrackerHit((*it).getObjectID());
+    bool isSuccessful = false; 
+    
+    if( UTIL::BitSet32( trkHit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ]   ){ //it is a composite spacepoint
+      //Split it up and hits to the MarlinTrk
+      std::vector< edm4hep::TrackerHit* > rawHits;
+      //const LCObjectVec rawObjects = trkHit->getRawHits();
+      //for( unsigned k=0; k<rawObjects.size(); k++ ) rawHits.push_back( dynamic_cast< TrackerHit* >( rawObjects[k] ) );
+      int nRawHit = trkHit->rawHits_size();
+      for( unsigned k=0; k< nRawHit; k++ ){
+	edm4hep::TrackerHit* rawHit = Navigation::Instance()->GetTrackerHit(trkHit->getRawHits(k));
+	rawHits.push_back(rawHit);
+      }
+      std::sort( rawHits.begin(), rawHits.end(), compare_TrackerHit_R );
+      
+      for( unsigned k=0; k< rawHits.size(); k++ ){
+	if( _marlinTrk->addHit( rawHits[k] ) == IMarlinTrack::success ){
+	  isSuccessful = true; //if at least one hit from the spacepoint gets added
+	  ++ndof_added; // 1 degree of freedom for each strip hit
+	}
+	else{
+	  //std::cout << "Cannot addHit " << rawHits[k]->id() << " to MarlinTrk" << std::endl; 
+	}
+      }
+    }
+    else { // normal non composite hit
+      if (_marlinTrk->addHit( trkHit ) == 0) {
+	isSuccessful = true;
+	ndof_added += 2;
+      }
+    }
+    
+    if (isSuccessful) {
+      added_hits.push_back(trkHit);
+      ++number_of_added_hits;
+    }
+    else{
+      //std::cout << "DEBUG Fitter::fit(): Hit " << it - _trackerHits.begin() << " Dropped " << std::endl;          
+    }
+  }
+  
+  if( ndof_added < 6 ) {
+    std::stringstream s;
+    s << "Fitter::fit(): Cannot fit less with less than 6 degrees of freedom. Number of hits =  " << number_of_added_hits << " ndof = " << ndof_added << "\n";
+    
+    throw FitterException( s.str() );
+  }
+   
+  /**********************************************************************************************/
+  /*       Create a helix from the first, last and middle hit                                   */
+  /**********************************************************************************************/
+  
+  for (unsigned ihit=0; ihit <added_hits.size(); ++ihit) {
+    // check if this a space point or 2D hit 
+    if(UTIL::BitSet32( added_hits[ihit]->getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] == false ){
+      // then add to the list 
+      added_hits_2D.push_back(added_hits[ihit]);
+      
+    }
+  }
+  
+  // initialise with space-points not strips 
+  // make a helix from 3 hits to get a trackstate
+  const edm4hep::Vector3d x1 = added_hits_2D[0]->getPosition();
+  const edm4hep::Vector3d x2 = added_hits_2D[ added_hits_2D.size()/2 ]->getPosition();
+  const edm4hep::Vector3d x3 = added_hits_2D.back()->getPosition();   
+  
+  init_BField();
+  HelixTrack helixTrack( x1, x2, x3, _bField, HelixTrack::forwards );
+  
+  helixTrack.moveRefPoint(0.0, 0.0, 0.0);
+  
+  //const float referencePoint[3] = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY() ), float(helixTrack.getRefPointZ() )};
+  edm4hep::Vector3f referencePoint = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY() ), float(helixTrack.getRefPointZ() )};
+  
+  /**********************************************************************************************/
+  /*       Create a TrackStateImpl from the helix values and use it to initalise the fit        */
+  /**********************************************************************************************/
+  std::array<float,15> covMatrix;
+  
+  for (unsigned icov = 0; icov<covMatrix.size(); ++icov) {
+    covMatrix[icov] = 0;
+  }
+  
+  covMatrix[0]  = ( 1.e6 ); //sigma_d0^2
+  covMatrix[2]  = ( 1.e2 ); //sigma_phi0^2
+  covMatrix[5]  = ( 1.e-4 ); //sigma_omega^2
+  covMatrix[9]  = ( 1.e6 ); //sigma_z0^2
+  covMatrix[14] = ( 1.e2 ); //sigma_tanl^2
+  
+  
+  edm4hep::TrackState trackState = {0/*TrackState::AtOther*/, 
+				    helixTrack.getD0(), 
+				    helixTrack.getPhi0(), 
+				    helixTrack.getOmega(), 
+				    helixTrack.getZ0(), 
+				    helixTrack.getTanLambda(),
+				    referencePoint,
+				    covMatrix};
+  
+  //init_BField();
+  _marlinTrk->initialise( trackState, _bField, IMarlinTrack::backward ) ;
+  
+  //     _marlinTrk->initialise( IMarlinTrack::backward ) ;
+   
+  /**********************************************************************************************/
+  /*       Do the fit                                                                           */
+  /**********************************************************************************************/
+  
+  int fit_status = 0;
+  
+  try{
+    
+    fit_status = _marlinTrk->fit() ; 
+    
+  }
+  catch( MarlinTrk::Exception& e ){
+    
+    std::stringstream s;
+    s << "Fitter::fit(): Couldn't fit, MarlinTrk->fit() gave: " << e.what() << "\n";
+    throw FitterException( s.str() );
+    
+  }
+  
+  if( fit_status != IMarlinTrack::success ){ 
+    
+    std::stringstream s;
+    s << "Fitter::fit(): MarlinTrk->fit() wasn't successful, fit_status = " << fit_status << "\n";
+    throw FitterException( s.str() );
+    
+  }
+  
+  
+  // fitting finished get hits in the fit for safety checks:
+  
+  std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit;
+  
+  // remember the hits are ordered in the order in which they were fitted
+  // here we are fitting inwards so the first is the last and vice verse
+  
+  _marlinTrk->getHitsInFit(hits_in_fit);
+  
+  if( hits_in_fit.size() < 3 ) {
+    
+    
+    std::stringstream s;
+    s << "Fitter::fit() Less than 3 hits in fit: Only " << hits_in_fit.size() << 
+      " of " << _trackerHits.size() << " hits\n";
+    
+    throw FitterException( s.str() );
+    
+  }
+  edm4hep::TrackerHit* first_hit_in_fit = hits_in_fit.back().first;
+  if (!first_hit_in_fit) {
+    throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to first hit == NULL ")  ) ;
+  }
+  
+  
+  edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first;
+  if (!last_hit_in_fit) {
+    throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to last hit == NULL ")  ) ;
+  }
+  
+  return;
+}
+
+
+
+void Fitter::fit(){
+  //create the MarlinTrk
+  _marlinTrk = _trkSystem->createTrack();
+  
+  /**********************************************************************************************/
+  /*       Add the hits to the MarlinTrack                                                      */
+  /**********************************************************************************************/
+  
+  // hits are in reverse order 
+  std::sort( _trackerHits.begin(), _trackerHits.end(), KiTrackMarlin::compare_TrackerHit_z );
+  // now at [0] is the hit with the smallest |z| and at [1] is the one with a bigger |z| and so on
+  // So the direction of the hits when following the index from 0 on is:
+  // from inside out: from the IP into the distance. 
+  // (It is important to keep in mind, in which direction we fit, when using MarlinTrk)
+  
+  TrackerHitVec::iterator it;
+  
+  unsigned number_of_added_hits = 0;
+  unsigned ndof_added = 0;
+  std::vector<edm4hep::TrackerHit*> added_hits;
+  
+  for( it = _trackerHits.begin() ; it != _trackerHits.end() ; ++it ) {
+    edm4hep::TrackerHit* trkHit = Navigation::Instance()->GetTrackerHit((*it).getObjectID());
+    bool isSuccessful = false; 
+    //std::cout << "Hit " << trkHit->id() << " " << trkHit->getPosition() << std::endl;
+    if( UTIL::BitSet32( trkHit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ]   ){ //it is a composite spacepoint
+      //Split it up and hits to the MarlinTrk
+      std::vector<edm4hep::TrackerHit*> rawHits;
+      //const LCObjectVec rawObjects = trkHit->getRawHits();                    
+      //for( unsigned k=0; k<rawObjects.size(); k++ ) rawHits.push_back( dynamic_cast< TrackerHit* >( rawObjects[k] ) );
+      int nRawHit = trkHit->rawHits_size();
+      for( unsigned k=0; k< nRawHit; k++ ){
+	edm4hep::TrackerHit* rawHit = Navigation::Instance()->GetTrackerHit(trkHit->getRawHits(k));
+	//std::cout << "Raw Hit " << rawHit->id() << " " << rawHit->getPosition() << std::endl;
+	rawHits.push_back(rawHit);
+      }
+      std::sort( rawHits.begin(), rawHits.end(), compare_TrackerHit_z );
+      
+      for( unsigned k=0; k< rawHits.size(); k++ ){
+	if( _marlinTrk->addHit( rawHits[k] ) == IMarlinTrack::success ){
+	   isSuccessful = true; //if at least one hit from the spacepoint gets added
+	   ++ndof_added; // 1 degree of freedom for each strip hit
+	}
+	else{
+	  //std::cout << "Cannot addHit " << rawHits[k]->id() << " to MarlinTrk" << std::endl;
+	}
+      }
+    }
+    else { // normal non composite hit
+      
+      if (_marlinTrk->addHit( trkHit ) == 0) {
+	isSuccessful = true;
+	ndof_added += 2;
+      }
+    }
+    
+    if (isSuccessful) {
+      added_hits.push_back(trkHit);
+      ++number_of_added_hits;
+    }
+    else{
+      //std::cout << "DEBUG: Fitter::fit(): Hit " << it - _trackerHits.begin() << " Dropped " << std::endl;          
+    }
+  }
+  
+  if( ndof_added < 6 ) {
+    std::stringstream s;
+    s << "Fitter::fit(): Cannot fit less with less than 6 degrees of freedom. Number of hits =  " << number_of_added_hits << " ndof = " << ndof_added << "\n";
+    
+    throw FitterException( s.str() );
+  }
+   
+  /**********************************************************************************************/
+  /*       Create a helix from the first, last and middle hit                                   */
+  /**********************************************************************************************/
+    
+  // initialise with space-points not strips 
+  // make a helix from 3 hits to get a trackstate
+  const edm4hep::Vector3d x1 = added_hits[0]->getPosition();
+  const edm4hep::Vector3d x2 = added_hits[ added_hits.size()/2 ]->getPosition();
+  const edm4hep::Vector3d x3 = added_hits.back()->getPosition();
+  
+  init_BField();
+  HelixTrack helixTrack( x1, x2, x3, _bField, HelixTrack::forwards );
+  
+  helixTrack.moveRefPoint(0.0, 0.0, 0.0);
+  
+  //const float referencePoint[3] = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY()) , float(helixTrack.getRefPointZ()) };
+  edm4hep::Vector3f referencePoint = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY()) , float(helixTrack.getRefPointZ()) };
+  
+  /**********************************************************************************************/
+  /*       Create a TrackStateImpl from the helix values and use it to initalise the fit        */
+  /**********************************************************************************************/
+  std::array<float,15> covMatrix;
+  for (unsigned icov = 0; icov<covMatrix.size(); ++icov) {
+    covMatrix[icov] = 0;
+  }
+  
+  covMatrix[0]  = ( 1.e6 ); //sigma_d0^2
+  covMatrix[2]  = ( 1.e2 ); //sigma_phi0^2
+  covMatrix[5]  = ( 1.e-4 ); //sigma_omega^2
+  covMatrix[9]  = ( 1.e6 ); //sigma_z0^2
+  covMatrix[14] = ( 1.e2 ); //sigma_tanl^2
+  
+  edm4hep::TrackState trackState = {0/*TrackState::AtOther*/, 
+				    helixTrack.getD0(), 
+				    helixTrack.getPhi0(), 
+				    helixTrack.getOmega(), 
+				    helixTrack.getZ0(), 
+				    helixTrack.getTanLambda(), 
+				    referencePoint,
+				    covMatrix};
+  
+  //init_BField();
+  _marlinTrk->initialise( trackState, _bField, IMarlinTrack::backward ) ;
+  
+  //     _marlinTrk->initialise( IMarlinTrack::backward ) ;
+  
+  /**********************************************************************************************/
+  /*       Do the fit                                                                           */
+  /**********************************************************************************************/
+  int fit_status = 0;
+  
+  try{
+    fit_status = _marlinTrk->fit() ; 
+  }
+  catch( MarlinTrk::Exception& e ){
+    std::stringstream s;
+    s << "Fitter::fit(): Couldn't fit, MarlinTrk->fit() gave: " << e.what() << "\n";
+    throw FitterException( s.str() );
+  }
+   
+  if( fit_status != IMarlinTrack::success ){ 
+    std::stringstream s;
+    s << "Fitter::fit(): MarlinTrk->fit() wasn't successful, fit_status = " << fit_status << "\n";
+    throw FitterException( s.str() );
+  }
+  
+  // fitting finished get hits in the fit for safety checks:
+  
+  std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit;
+  
+  // remember the hits are ordered in the order in which they were fitted
+  // here we are fitting inwards so the first is the last and vice verse
+  
+  _marlinTrk->getHitsInFit(hits_in_fit);
+  
+  if( hits_in_fit.size() < 3 ) {
+    std::stringstream s;
+    s << "Fitter::fit() Less than 3 hits in fit: Only " << hits_in_fit.size()
+      << " of " << _trackerHits.size() << " hits\n";
+    
+    throw FitterException( s.str() );
+  }
+  edm4hep::TrackerHit* first_hit_in_fit = hits_in_fit.back().first;
+  if (!first_hit_in_fit) {
+    throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to first hit == NULL ")  ) ;
+  }
+  
+  edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first;
+  if (!last_hit_in_fit) {
+    throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to last hit == NULL ")  ) ;
+  }
+  
+  return;
+}
+   
+   
+const edm4hep::TrackState* Fitter::getTrackState( int trackStateLocation ){
+  return getTrackStatePlus( trackStateLocation )->getTrackState();
+}
+
+double Fitter::getChi2Prob( int trackStateLocation ){
+  return ROOT::Math::chisquared_cdf_c( getChi2( trackStateLocation ) , getNdf( trackStateLocation ) );   
+}
+
+double Fitter::getChi2( int trackStateLocation ){
+  return getTrackStatePlus( trackStateLocation )->getChi2();
+}
+   
+int Fitter::getNdf( int trackStateLocation ){
+   return getTrackStatePlus( trackStateLocation )->getNdf();
+}
+   
+   
+const TrackStatePlus* Fitter::getTrackStatePlus( int trackStateLocation ){
+   // check if there is already an entry with this trackState location
+   for( unsigned i=0; i<_trackStatesPlus.size(); i++ ){
+     if( _trackStatesPlus[i]->getTrackState()->location == trackStateLocation ){
+       return _trackStatesPlus[i];
+     }
+   }
+   
+   // If we reach this point, obviously no trackState with the given location has been created so far
+   // Thus we create it now
+   edm4hep::TrackState* trackState = new edm4hep::TrackState;
+   int return_code = 0;
+   double chi2;
+   int ndf;
+   switch( trackStateLocation ){
+   case 1/*lcio::TrackState::AtIP*/:{
+     const edm4hep::Vector3d point(0.,0.,0.); // nominal IP
+              
+     return_code = _marlinTrk->propagate(point, *trackState, chi2, ndf ) ;
+         
+     if (return_code != MarlinTrk::IMarlinTrack::success ) {
+       delete trackState;
+            
+       std::stringstream s;
+       s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at IP, return code from propagation = " << return_code << "\n";
+       throw FitterException( s.str() );
+       
+       break;
+     }
+     else{
+       trackState->location = trackStateLocation;
+       TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf );
+       _trackStatesPlus.push_back( trackStatePlus );
+       return trackStatePlus;
+     }
+   }
+   case 2/*lcio::TrackState::AtFirstHit*/:{
+     std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit;
+         
+     // remember the hits are ordered in the order in which they were fitted
+     // here we are fitting inwards so the first is the last and vice verse
+     _marlinTrk->getHitsInFit(hits_in_fit);
+     
+     edm4hep::TrackerHit* first_hit_in_fit = hits_in_fit.back().first;
+          
+     return_code = _marlinTrk->getTrackState(first_hit_in_fit, *trackState, chi2, ndf ) ;
+     
+     if(return_code !=MarlinTrk::IMarlinTrack::success){
+       
+       delete trackState;
+       
+       std::stringstream s;
+       s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at first hit, return code from propagation = " << return_code << "\n";
+       throw FitterException( s.str() );
+	    
+       break;
+     }
+     else{
+       trackState->location = trackStateLocation;
+       TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf );
+       _trackStatesPlus.push_back( trackStatePlus );
+       return trackStatePlus;
+     }
+   }
+   case 3/*lcio::TrackState::AtLastHit*/:{
+     std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit;
+     _marlinTrk->getHitsInFit(hits_in_fit);
+     
+     edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first;
+          
+     return_code = _marlinTrk->getTrackState(last_hit_in_fit, *trackState, chi2, ndf ) ;
+         
+     if(return_code !=MarlinTrk::IMarlinTrack::success){
+       delete trackState;
+            
+       std::stringstream s;
+       s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at last hit, return code from propagation = " << return_code << "\n";
+       throw FitterException( s.str() );
+       
+       break;
+     }
+     else{
+       trackState->location = trackStateLocation;
+       TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf );
+       _trackStatesPlus.push_back( trackStatePlus );
+       return trackStatePlus;
+     }
+     break;
+   }
+   case 4/*lcio::TrackState::AtCalorimeter*/:{
+     std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit;
+     _marlinTrk->getHitsInFit(hits_in_fit);
+     
+     edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first;
+          
+     UTIL::BitField64 encoder( UTIL::ILDCellID0::encoder_string ) ; 
+     encoder.reset() ;  // reset to 0
+         
+     // ================== need to get the correct ID(s) for the calorimeter face  ============================
+     unsigned ecal_barrel_face_ID = UTIL::ILDDetID::ECAL ;
+     //unsigned ecal_endcap_face_ID = UTIL::ILDDetID::ECAL_ENDCAP ;
+     //=========================================================================================================
+
+     encoder[UTIL::ILDCellID0::subdet] =  ecal_barrel_face_ID ;
+     encoder[UTIL::ILDCellID0::side]   = UTIL::ILDDetID::barrel;
+     encoder[UTIL::ILDCellID0::layer]  = 0 ;
+     
+     int detElementID = 0;
+     return_code = _marlinTrk->propagateToLayer(encoder.lowWord(), last_hit_in_fit, *trackState, chi2, ndf, detElementID, IMarlinTrack::modeForward ) ;
+     
+     if (return_code == MarlinTrk::IMarlinTrack::no_intersection ) { // try forward or backward
+       //encoder[UTIL::ILDCellID0::subdet] = ecal_endcap_face_ID ;
+       
+       const edm4hep::TrackState* trkStateLastHit = getTrackStatePlus( 3/*lcio::TrackState::AtLastHit*/ )->getTrackState();
+       
+       if (trkStateLastHit->tanLambda>0) {
+	 encoder[UTIL::ILDCellID0::side] = UTIL::ILDDetID::fwd;
+       }
+       else{
+	 encoder[UTIL::ILDCellID0::side] = UTIL::ILDDetID::bwd;
+       }
+       return_code = _marlinTrk->propagateToLayer(encoder.lowWord(), last_hit_in_fit, *trackState, chi2, ndf, detElementID, IMarlinTrack::modeForward ) ;
+     }
+                 
+     if(return_code !=MarlinTrk::IMarlinTrack::success){
+       delete trackState;
+            
+       std::stringstream s;
+       s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at Calorimeter, return code from propagation = " << return_code << "\n";
+       throw FitterException( s.str() );
+       break;
+     }
+     else{
+       trackState->location = trackStateLocation;
+       TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf );
+       _trackStatesPlus.push_back( trackStatePlus );
+       return trackStatePlus;
+     }
+   }
+   default:{
+     std::stringstream s;
+     s << "Creation of a trackState for the given location " << trackStateLocation 
+       << " is not yet implemented for the class Fitter. \nImplemented are: AtIP, AtFirstHit, AtLastHit, AtCalorimeter.\n"
+       << "If another location is desired, it must be implemented in the method Fitter::getTrackStatePlus.\n";
+     
+     throw FitterException( s.str() );
+     return NULL;
+   }
+   }
+      
+   return NULL; // if we haven't returned so far, there was no success, so we return NULL
+}
+   
+   
+
diff --git a/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.cc.bak b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.cc.bak
new file mode 100644
index 00000000..9ff3a242
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.cc.bak
@@ -0,0 +1,122 @@
+#include "Tools/KiTrackMarlinCEDTools.h"
+
+#include <cmath>
+
+#include <CLHEP/Random/RandFlat.h>
+
+#include "MarlinCED.h"
+
+
+void KiTrackMarlin::drawAutomatonSegments( const Automaton& automaton ){
+   
+   
+   std::vector< const Segment* > segments = automaton.getSegments();
+   
+   
+   for( unsigned i=0 ; i < segments.size(); i++ ){
+      
+      
+      const Segment* segment = segments[i];
+      std::vector < IHit* > hits = segment->getHits();         
+      
+     
+      if ( hits.size() == 1){ //exactly one hit, so draw a point
+         
+         
+         IHit* a = hits[0];
+         ced_hit( a->getX() ,a->getY() , a->getZ() , 0 , 3 ,0xff0000 );
+         
+         
+      }
+      else{ //more than one point or no points
+         
+         for( unsigned j=1 ; j< hits.size() ; j++ ){ // over all hits in the segment (as we connect it with the previous we start with hit 1)
+            
+            IHit* a = hits[j];
+            IHit* b = hits[j-1];
+            
+            
+            unsigned int color=0;
+            unsigned int red=0;
+            unsigned int blue=0;
+            unsigned int green=0;
+            
+            float p =  sqrt ((float)  segment->getInnerState() / (float) ( 7 ));
+            
+            green = unsigned( ceil ( (1.-p) * 255 ) );
+            red = unsigned( floor( 255*p ) );
+            blue = unsigned( ceil ( (1.-p) * 255 ) );
+            
+            color = red * 256*256 + green * 256 + blue;
+            
+            
+            ced_line_ID( a->getX() ,a->getY() , a->getZ() , b->getX() ,b->getY() , b->getZ() , 2 , segment->getInnerState()+2 , color, 0);
+            
+         }
+         
+      }
+      
+   }
+   
+   
+}
+
+
+
+void KiTrackMarlin::drawTrack( ITrack* track, int color ){
+   
+   
+   std::vector < IHit* > hits = track->getHits();     
+   
+   for( unsigned j=1 ; j< hits.size() ; j++ ){ // over all hits in the segment (as we connect it with the previous we start with hit 1)
+      
+      IHit* a = hits[j];
+      IHit* b = hits[j-1];
+      
+      ced_line_ID( a->getX() ,a->getY() , a->getZ() , b->getX() ,b->getY() , b->getZ() , 2 , 5 , color, 0);
+      
+   }
+   
+   
+   
+   
+}
+
+
+void KiTrackMarlin::drawTrackRandColor( ITrack* track ){
+   
+   
+   int red = 0;
+   int green = 0;
+   int blue = 0;
+   
+   int dist = 0;
+   int distmin = 60;
+   
+   while( dist < distmin ){
+      
+      red = CLHEP::RandFlat::shootInt(256);
+      green = CLHEP::RandFlat::shootInt(256);
+      blue = CLHEP::RandFlat::shootInt(256);
+      
+      
+      dist = std::abs( red - green );
+      if( std::abs( green - blue ) > dist ) dist = std::abs( green - blue );
+      if( std::abs( red - blue ) > dist ) dist = std::abs( red - blue );
+      
+   }
+   
+   int color = red * 256*256 + green * 256 + blue;
+   drawTrack( track, color );
+   
+   
+   
+}
+
+
+
+
+
+
+
+
diff --git a/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.h b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.h
new file mode 100644
index 00000000..e2f3ad29
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.h
@@ -0,0 +1,31 @@
+#ifndef KiTrackMarlinCEDTools_h
+#define KiTrackMarlinCEDTools_h
+
+#include "KiTrack/Automaton.h"
+#include "KiTrack/ITrack.h"
+
+using namespace KiTrack;
+
+namespace KiTrackMarlin{
+   
+   
+   
+   /**
+   * Draws the segments of an automaton.
+   * Segments will be colored according to their state.
+   * Also the higher the state, the thicker the line.
+   */
+   void drawAutomatonSegments( const Automaton& automaton );
+   
+   /**
+    * Draws a track by making straight lines between the hits
+    */
+   void drawTrack( ITrack* track, int color = 0x00ff00 );
+   
+   /** Draw a track in a random color, but not too bright */
+   void drawTrackRandColor( ITrack* track );
+   
+}
+
+#endif 
+
diff --git a/Utilities/KiTrack/src/Tools/KiTrackMarlinTools.cc b/Utilities/KiTrack/src/Tools/KiTrackMarlinTools.cc
new file mode 100644
index 00000000..7bb007c9
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/KiTrackMarlinTools.cc
@@ -0,0 +1,262 @@
+#include "Tools/KiTrackMarlinTools.h"
+
+#include <sstream>
+#include <fstream>
+#include <cmath>
+
+#include "TROOT.h"
+#include "TTree.h"
+#include "TFile.h"
+
+#include "UTIL/LCTrackerConf.h"
+
+using namespace KiTrackMarlin;
+
+
+std::string KiTrackMarlin::getCellID0Info( int cellID0 ){
+   
+   std::stringstream s;
+   
+   //find out layer, module, sensor
+   UTIL::BitField64  cellID( UTIL::LCTrackerCellID::encoding_string() );
+   cellID.setValue( cellID0 );
+   
+   int subdet = cellID[ UTIL::LCTrackerCellID::subdet() ] ;
+   int side   = cellID[ UTIL::LCTrackerCellID::side() ];
+   int module = cellID[ UTIL::LCTrackerCellID::module() ];
+   int sensor = cellID[ UTIL::LCTrackerCellID::sensor() ];
+   int layer  = cellID[ UTIL::LCTrackerCellID::layer() ];
+   
+   s << "(su" << subdet << ",si" << side << ",la" << layer << ",mo" << module << ",se" << sensor << ")";
+   
+   return s.str();
+   
+}
+
+int KiTrackMarlin::getCellID0Layer( int cellID0 ){
+   
+   
+   UTIL::BitField64  cellID( UTIL::LCTrackerCellID::encoding_string() );
+   cellID.setValue( cellID0 );
+   
+   return cellID[ UTIL::LCTrackerCellID::layer() ];
+   
+   
+}
+
+
+
+
+void KiTrackMarlin::setUpRootFile( std::string rootNamePath, std::string treeName ,  std::set<std::string> branchNames , bool createNew ){
+   
+   
+   std::string fileNamePath = rootNamePath.substr( 0 , rootNamePath.find_last_of(".")  );
+   
+   
+   
+   std::ifstream rf ((fileNamePath + ".root").c_str());       //rf for RootFile
+   if ((rf) && (createNew)) { // The file already exists and we don't want to append
+   
+    int i=0;
+    std::stringstream newname;
+    while (rf){         //Try adding a number starting from 1 to the filename until no file with this name exists and use this.
+      
+      rf.close();
+      i++;
+      newname.str("");
+      newname << fileNamePath << i << ".root";
+      
+      rf.open( newname.str().c_str() );
+      
+    }
+    rename ( (fileNamePath + ".root").c_str() , newname.str().c_str());      //renames the file in the way,so that our new file can have it's name
+    //and not ovrewrite it.
+    
+   }
+   
+   float x = 0;
+   
+   std::string modus = "RECREATE";
+   if ( !createNew ) modus = "UPDATE";
+   
+   TFile* myRootFile = new TFile((fileNamePath + ".root").c_str(), modus.c_str() );        //Make new file or update it
+   TTree* myTree;
+   
+   myTree = new TTree(treeName.c_str(),"My tree"); //make a new tree
+   
+   //create the branches:
+   
+   std::set < std::string >::iterator it;
+   
+   
+   for ( it = branchNames.begin() ; it != branchNames.end() ; it++ ){
+      
+      
+      myTree->Branch( (*it).c_str() , &x );
+      
+   }
+   
+   
+   myTree->Write("",TObject::kOverwrite);
+   myRootFile->Close();
+   
+}
+
+
+
+
+
+void KiTrackMarlin::saveToRoot( std::string rootFileName, std::string treeName , std::map < std::string , float > map_name_data ){
+  std::map < std::string , float >::iterator it;
+     
+  TFile*   myRootFile = new TFile( rootFileName.c_str(), "UPDATE"); //add values to the root file
+  TTree*   myTree = dynamic_cast <TTree*>( myRootFile->Get( treeName.c_str()) );
+   
+  if( myTree == NULL ){
+    std::cout << "ERROR: KiTrackMarlin::saveToRoot could not get tree " << treeName << std::endl;
+    return;
+  }
+      
+  for( it = map_name_data.begin() ; it != map_name_data.end() ; it++){
+    myTree->SetBranchAddress( it->first.c_str(), & it->second );   
+  }
+     
+  myTree->Fill();
+  myTree->Write("",TObject::kOverwrite);
+  
+  myRootFile->Close();
+}
+
+void KiTrackMarlin::saveToRoot( std::string rootFileName, std::string treeName , std::vector < std::map < std::string , float > > rootDataVec ){
+  std::map < std::string , float >::iterator it;
+     
+  TFile*   myRootFile = new TFile( rootFileName.c_str(), "UPDATE"); //add values to the root file
+  TTree*   myTree = dynamic_cast <TTree*>( myRootFile->Get( treeName.c_str()) );
+  
+  if( myTree == NULL ){
+    std::cout << "ERROR: KiTrackMarlin::saveToRoot could not get tree " << treeName << std::endl;
+    return;
+  }
+     
+  for( unsigned i=0; i<rootDataVec.size(); i++ ){ //for all entries
+    std::map < std::string , float > map_name_data = rootDataVec[i];
+    for( it = map_name_data.begin() ; it != map_name_data.end() ; it++){ // for all data in the entrie
+      myTree->SetBranchAddress( it->first.c_str(), & it->second );   
+    }
+    myTree->Fill();
+  }
+  myTree->Write("",TObject::kOverwrite);   
+  myRootFile->Close();
+}
+
+
+//bool KiTrackMarlin::compare_TrackerHit_z( edm4hep::ConstTrackerHit* a, edm4hep::ConstTrackerHit* b ){
+//  return ( fabs(a->getPosition()[2]) < fabs( b->getPosition()[2]) ); //compare their z values
+//}
+
+bool KiTrackMarlin::compare_TrackerHit_z( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b ){
+  return ( fabs(a.getPosition()[2]) < fabs( b.getPosition()[2]) );
+}
+
+bool KiTrackMarlin::compare_TrackerHit_R( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b ){
+  double Rad_a2 = (a.getPosition()[0]*a.getPosition()[0]) + (a.getPosition()[1]*a.getPosition()[1]) ;
+  double Rad_b2 = (b.getPosition()[0]*b.getPosition()[0]) + (b.getPosition()[1]*b.getPosition()[1]) ;
+  
+  return ( Rad_a2 < Rad_b2 ); //compare their radii
+}
+
+
+
+FTDHitSimple* KiTrackMarlin::createVirtualIPHit( int side , const SectorSystemFTD* sectorSystemFTD ){
+   
+   unsigned layer = 0;
+   unsigned module = 0;
+   unsigned sensor = 0;
+   FTDHitSimple* virtualIPHit = new FTDHitSimple( 0.,0.,0., side , layer , module , sensor , sectorSystemFTD );
+   
+   
+   virtualIPHit->setIsVirtual ( true );
+   
+   return virtualIPHit;
+   
+}
+
+
+VXDHitSimple* KiTrackMarlin::createVirtualIPHit( const SectorSystemVXD* sectorSystemVXD ){
+   
+   int layer = 0 ;
+   int phi = 0 ;
+   int theta = 0 ;
+
+   VXDHitSimple* virtualIPHit = new VXDHitSimple( 0.,0.,0., layer, phi, theta, sectorSystemVXD );
+
+   virtualIPHit->setIsVirtual ( true );
+   
+   return virtualIPHit;
+   
+}
+
+
+std::string KiTrackMarlin::getPositionInfo( edm4hep::ConstTrackerHit* hit ){
+   
+   std::stringstream info;
+   
+   double x = hit->getPosition()[0];
+   double y = hit->getPosition()[1];
+   double z = hit->getPosition()[2];
+   
+   info << "(" << x << "," << y << "," << z << ")";
+   
+   return info.str();
+   
+}
+
+std::string KiTrackMarlin::getPositionInfo( IHit* hit ){
+   
+   std::stringstream info;
+   
+   double x = hit->getX();
+   double y = hit->getY();
+   double z = hit->getZ();
+   
+   info << "(" << x << "," << y << "," << z << ")";
+   
+   return info.str();
+   
+}
+
+
+std::string KiTrackMarlin::getTrackHitInfo( ITrack* track){
+   
+   std::stringstream info;
+   
+   std::vector< IHit* > hits = track->getHits();
+   
+   for( unsigned i=0; i < hits.size(); i++ ){
+      
+      info << getPositionInfo( hits[i] );
+      
+   };
+   
+   return info.str();
+   
+   
+}
+
+std::string KiTrackMarlin::getTrackHitInfo( edm4hep::Track* track){
+  std::stringstream info;
+  //std::vector< edm4hep::TrackerHit* > hits;
+  unsigned int nHits = track->trackerHits_size();
+  for(unsigned i=0; i<nHits; i++){
+    edm4hep::ConstTrackerHit hit = track->getTrackerHits(i);
+    info << getPositionInfo(&hit);
+  }
+   
+  //for( unsigned i=0; i < hits.size(); i++ ){
+  //  info << getPositionInfo( hits[i] );
+  //};
+   
+  return info.str();
+}
+
+
diff --git a/Utilities/KiTrack/src/Tools/Timer.cc b/Utilities/KiTrack/src/Tools/Timer.cc
new file mode 100644
index 00000000..2597141d
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/Timer.cc
@@ -0,0 +1,127 @@
+#include "Tools/Timer.h"
+
+#include <string>
+#include <fstream>
+#include <iterator>
+#include <cstdlib>
+#include <iostream>
+
+#define FINE_GRAINED_LINUX_TIMING
+
+#include <ctime>
+#include <sys/times.h>
+#include <unistd.h>
+
+using namespace std;
+using namespace KiTrackMarlin;
+
+namespace {
+  #ifdef FINE_GRAINED_LINUX_TIMING
+  static unsigned cyc_hi = 0;
+  static unsigned cyc_lo = 0;
+
+  void access_counter(unsigned *hi, unsigned *lo)
+  {
+    asm("rdtsc; movl %%edx,%0; movl %%eax,%1"
+        : "=r" (*hi), "=r" (*lo)
+        :
+        : "%edx", "%eax");
+  }
+
+  double get_counter()
+  {
+    unsigned ncyc_hi, ncyc_lo;
+    unsigned hi, lo, borrow;
+    access_counter(&ncyc_hi, &ncyc_lo);
+    lo = ncyc_lo - cyc_lo;
+    borrow = lo > ncyc_lo;
+    hi = ncyc_hi - cyc_hi - borrow;
+    return (double) hi * (1 << 30) * 4 + lo;
+  }
+  #else
+  clock_t before;
+  #endif
+}
+
+double Timer::cpuMHz()
+{
+  static double ret=-1.;
+  if ( ret > -.5 ) return ret;
+  string input="Unknow CPU";
+  {
+    ifstream cpuinfo("/proc/cpuinfo");
+    if ( cpuinfo.is_open() )
+    {
+      cpuinfo.unsetf( ios::skipws );
+      istream_iterator<char> sbegin(cpuinfo),send;
+      copy(sbegin,send,inserter(input,input.end()));
+      cpuinfo.close();
+    };
+  }
+
+  size_t i = input.find("model name");
+  if (i!=string::npos )
+  {
+    i = input.find("@ ",i);
+    if ( i != string::npos )
+    {
+      size_t j = input.find("GHz",i);
+      //cout << "[debug] i=" << i << " j=" << j << " string=" << input.substr(i+1,j-i-1) << "X" << endl;
+      return 1000.*atof(input.substr(i+1,j-i-1).c_str() );
+    };
+
+  }
+
+  i = input.find("cpu MHz");
+  if (i==string::npos)
+  {
+    cout << "[Timer] /proc/cpuinfo does not contain cpu speed..." << endl;
+    ret=0.;
+  };
+  i = input.find(":",i);
+  ret=atof(input.substr(i+1,input.find("/n",i)-i).c_str());
+  return ret;
+}
+
+void Timer::start_counter()
+{
+  #ifdef FINE_GRAINED_LINUX_TIMING
+  access_counter(&cyc_hi, &cyc_lo);
+  #else
+  tms buf;
+  times( &buf );     
+  before = buf.tms_utime;
+  #endif
+}
+
+double Timer::lap()
+{
+  #ifdef FINE_GRAINED_LINUX_TIMING
+  return get_counter() / cpuMHz() / 1.e6;
+  #else
+  tms buf;
+  times ( &buf );
+  clock_t after = buf.tms_utime;
+  static float cps=sysconf(_SC_CLK_TCK);
+  double t = ( after - before )  / cps;    
+  return t;
+  #endif
+}
+
+double Timer::ticks()
+{
+  #ifdef FINE_GRAINED_LINUX_TIMING
+  return get_counter();
+  #else
+  tms buf;
+  times ( &buf );
+  clock_t after = buf.tms_utime;
+  // static float cps=sysconf(_SC_CLK_TCK);
+  double t = ( after - before ); 
+  return t;
+  #endif
+}
+
+#ifdef FINE_GRAINED_LINUX_TIMING
+#undef FINE_GRAINED_LINUX_TIMING
+#endif
diff --git a/Utilities/KiTrack/src/Tools/Timer.h b/Utilities/KiTrack/src/Tools/Timer.h
new file mode 100644
index 00000000..7c3cd3bd
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/Timer.h
@@ -0,0 +1,22 @@
+#ifndef dataharvester_Timer_H_
+#define dataharvester_Timer_H_
+
+namespace KiTrackMarlin {
+class Timer {
+public:
+  /**
+   *  A fast, precise timer
+   *  Works on linux only
+   * 
+   * Author: Wolfgang Waltenberger
+   */
+  static void start_counter();
+
+  /// Return what the harvester thinks is the CPU frequency.
+  static double cpuMHz();
+  static double lap(); //< lapsed time, in seconds.
+  static double ticks(); //< lapsed time, in clock ticks.
+};
+}
+
+#endif // dataharvester_Timer_H_
diff --git a/Utilities/KiTrack/src/Tools/VXDHelixFitter.cc.bak b/Utilities/KiTrack/src/Tools/VXDHelixFitter.cc.bak
new file mode 100644
index 00000000..515a8029
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/VXDHelixFitter.cc.bak
@@ -0,0 +1,190 @@
+#include "Tools/VXDHelixFitter.h"
+
+#include <sstream>
+#include <algorithm>
+#include <cmath>
+
+#include "edm4hep/TrackerHit.h"
+#include "UTIL/ILDConf.h"
+#include "UTIL/LCTrackerConf.h"
+//#include "marlin/VerbosityLevels.h"
+#include "TrackSystemSvc/HelixFit.h"
+
+#include "Tools/KiTrackMarlinTools.h"
+
+
+VXDHelixFitter::VXDHelixFitter( std::vector< TrackerHit* > trackerHits ){
+   
+   _trackerHits = trackerHits;
+   
+   fit();
+   
+}
+
+VXDHelixFitter::VXDHelixFitter( Track* track ){
+   
+   _trackerHits = track->getTrackerHits();
+   
+   fit();
+
+}
+
+void VXDHelixFitter::fit(){
+   
+  std::vector< TrackerHit* > trackerHits2D ;
+
+  for (unsigned ihit=0; ihit <_trackerHits.size(); ++ihit) {
+    
+    // check if this a space point or 2D hit 
+    if(UTIL::BitSet32( _trackerHits[ihit]->getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] == false ){
+      // then add to the list 
+      trackerHits2D.push_back(_trackerHits[ihit]);
+      
+    }
+  }
+
+   std::sort( trackerHits2D.begin(), trackerHits2D.end(), KiTrackMarlin::compare_TrackerHit_R );
+   
+   int nHits = trackerHits2D.size();
+
+   int iopt = 2;
+   float chi2RPhi;
+   float chi2Z;
+
+   // DEBUG
+   //streamlog_out(DEBUG4) << " no of hits fitted " << nHits << std::endl ; 
+   
+   if( nHits < 3 ){
+      
+      std::stringstream s;
+      s << "VXDHelixFitter::fit(): Cannot fit less with less than 3 hits. Number of hits =  " << nHits << "\n";
+      
+      throw VXDHelixFitterException( s.str() );
+      
+   }
+   
+   double* xh  = new double[nHits];
+   double* yh  = new double[nHits];
+   float*  zh  = new float[nHits];
+   double* wrh = new double[nHits];
+   float*  wzh = new float[nHits];
+   float*  rh  = new float[nHits];
+   float*  ph  = new float[nHits];
+   
+   float par[5];
+   float epar[15];
+   
+   for( int i=0; i<nHits; i++ ){
+     
+     TrackerHit* hit = trackerHits2D[i];
+     
+     xh[i] = hit->getPosition()[0];
+     yh[i] = hit->getPosition()[1];
+     zh[i] = float(hit->getPosition()[2]);
+     
+     //wrh[i] = double(1.0/(hit->getResolutionRPhi()*hit->getResolutionRPhi()));
+     //wzh[i] = 1.0/(hit->getResolutionZ()*hit->getResolutionZ());
+     //wrh[i] = double(1.0/(sqrt((hit->getCovMatrix()[0]*hit->getCovMatrix()[0]) + (hit->getCovMatrix()[2]*hit->getCovMatrix()[2]))));
+     //wzh[i] = 1.0/(hit->getCovMatrix()[5]);
+     
+     rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i]));
+     ph[i] = atan2(yh[i],xh[i]);
+     if (ph[i] < 0.) 
+       ph[i] = 2.*M_PI + ph[i]; 
+     
+     // Just to debug the resolutions
+     //streamlog_out(DEBUG4) << " hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " Cov[0] " << hit->getCovMatrix()[0] << " Cov[2] " << hit->getCovMatrix()[2] << " Cov[5] " << hit->getCovMatrix()[5] << std::endl ;
+     
+     // check for composite spacepoints
+     if( BitSet32( hit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){
+       
+       //streamlog_out(DEBUG4) << " COMPOSITE SPACEPOINT radius: " <<  rh[i] << std::endl ;
+       
+       float sigX = hit->getCovMatrix()[0];
+       float sigY = hit->getCovMatrix()[2];
+       wrh[i] = 1/sqrt( sigX*sigX + sigY*sigY );
+       wzh[i] = 1.0/(hit->getCovMatrix()[5]);
+       
+       //streamlog_out(DEBUG4) << " SPACEPOINT:: hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " res RPhi " << sqrt( sigX*sigX + sigY*sigY ) << " res Z " << (hit->getCovMatrix()[5]) << std::endl ;         
+       
+     }
+     else if  (  BitSet32( hit->getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] ) {
+       
+       // YV: FIXME: very crude hack, hard coded the SIT strip digital resolution in V 
+       //streamlog_out(DEBUG4) << " 1D hit radius: " <<  rh[i] << std::endl ;
+       
+       //TrackerHitPlane* hitPlane = dynamic_cast<TrackerHitPlane*>( hit );
+       //wrh[i] = double(1.0/( hitPlane->getdU()*hitPlane->getdU()  ));
+       wrh[i] = double(1.0/( hit->getCovMatrix(2)*hit->getCovMatrix(2) ));
+       double resZ = 92.0  / std::sqrt( 12. ) ;
+       //double resZ = 0.003 ;
+       wzh[i] = 1.0/( resZ * resZ ); 
+
+       //streamlog_out(DEBUG4) << " 1Dimensional TRACKERHITPLANE:: hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " dU " << hitPlane->getdU() << " dV " << resZ  << " 1/du^2 "<< (1/(hitPlane->getdU()*hitPlane->getdU())) <<  " 1/dv^2 "<< wzh[i] << std::endl ;
+
+     }
+     
+     else {
+      
+       //streamlog_out(DEBUG4) << " 2D hit radius: " <<  rh[i]  << std::endl ; 
+       //TrackerHitPlane* hitPlane = dynamic_cast<TrackerHitPlane*>( hit );
+       //wrh[i] = double(1.0/( hitPlane->getdU()*hitPlane->getdU()  ));
+       //wzh[i] = wrh[i]; // pixel VXD 
+       wrh[i] = double(1.0/( hit->getCovMatrix(2)*hit->getCovMatrix(2) ));
+       wzh[i] = double(1.0/( hit->getCovMatrix(5)*hit->getCovMatrix(5) ));
+
+       //streamlog_out(DEBUG4) << "2D pixel TRACKERHITPLANE:: hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " dU " << hitPlane->getdU() << " dV " << hitPlane->getdV()  << " 1/du^2 "<< (1/(hitPlane->getdU()*hitPlane->getdU())) <<  " 1/dv^2 "<< (1/(hitPlane->getdV()*hitPlane->getdV())) << std::endl ;
+            
+     }     
+   }
+   
+   
+   
+   
+   MarlinTrk::HelixFit helixFitter;
+   
+   helixFitter.fastHelixFit(nHits, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+   par[3] = par[3]*par[0]/fabs(par[0]);
+   
+   _omega = par[0];
+   _tanLambda = par[1];
+   _phi0 = par[2];
+   _d0 = par[3];
+   _z0 = par[4];
+   
+   float chi2 = chi2RPhi+chi2Z;
+   int Ndf = 2*nHits-5;
+   
+   
+   
+   
+   delete[] xh;
+   delete[] yh;
+   delete[] zh;
+   delete[] wrh;
+   delete[] wzh;
+   delete[] rh;
+   delete[] ph;
+   xh  = NULL; 
+   yh  = NULL; 
+   zh  = NULL; 
+   wrh = NULL; 
+   wzh = NULL; 
+   rh = NULL; 
+   ph = NULL; 
+   
+ 
+   //streamlog_out(DEBUG4) << "chi2 rphi = " << chi2RPhi << ", chi2 Z = " << chi2Z << ", Ndf = " << Ndf << "\n";
+   
+   _chi2 = chi2;
+   _Ndf = Ndf;
+   
+   return;
+   
+   
+   
+}
+
+
+
+
diff --git a/Utilities/KiTrack/src/Tools/VXDHelixFitter.h b/Utilities/KiTrack/src/Tools/VXDHelixFitter.h
new file mode 100644
index 00000000..cf066262
--- /dev/null
+++ b/Utilities/KiTrack/src/Tools/VXDHelixFitter.h
@@ -0,0 +1,82 @@
+#ifndef VXDHelixFitter_h
+#define VXDHelixFitter_h
+
+#include "edm4hep/Track.h"
+#include "edm4hep/TrackerHit.h"
+
+//#include "lcio.h"
+
+
+
+//using namespace lcio;
+
+
+
+class VXDHelixFitterException : public std::exception {
+   
+   
+protected:
+   std::string message ;
+   
+   VXDHelixFitterException(){  /*no_op*/ ; } 
+   
+public: 
+   virtual ~VXDHelixFitterException() { /*no_op*/; } 
+   
+   VXDHelixFitterException( const std::string& text ){
+      message = "VXDHelixFitterException: " + text ;
+   }
+   
+   virtual const char* what() const noexcept { return  message.c_str() ; } 
+   
+};
+
+
+
+/** A class to make it quick to fit a track or hits and get back the chi2 and Ndf values and
+ * also bundle the code used for that, so it doesn't have to be copied all over the places.
+ * Uses a helix fit from the MarlinTrk class HelixFit.cc
+ * It is named VXDHelixFitter, because it makes some assumptions about the hits, that come from them
+ * being on the VXD. Specifically the errors passed to the helix fit are calculated on the assumption,
+ * that du and dv are errors in the xy plane.
+ * If this class is intended to be used for hits on different detectors, a careful redesign is necessary!
+ */
+class VXDHelixFitter{
+   
+   
+public:
+   
+  VXDHelixFitter( edm4hep::Track* track ) ;
+  VXDHelixFitter( std::vector < edm4hep::TrackerHit* > trackerHits ) ;
+   
+   
+   double getChi2(){ return _chi2; }
+   int getNdf(){ return _Ndf; }
+   
+   float getOmega(){ return _omega; }
+   float getTanLambda(){ return _tanLambda; }
+   float getPhi0(){ return _phi0; }
+   float getD0(){ return _d0; }
+   float getZ0(){ return _z0; }
+   
+private:
+   
+  
+   
+   void fit();
+   
+   double _chi2;
+   int _Ndf;
+   
+   float _omega;
+   float _tanLambda;
+   float _phi0;
+   float _d0;
+   float _z0;
+   
+   std::vector< edm4hep::TrackerHit* > _trackerHits;
+  
+   
+};
+
+#endif
-- 
GitLab