From dcff3795ff1fbff87899b0bc169f0edaf4678bc1 Mon Sep 17 00:00:00 2001
From: Stefan Schmitt <sschmitt@mail.desy.de>
Date: Tue, 13 Jun 2017 18:12:03 +0000
Subject: [PATCH] Add FTK pattern bank production software to ATLAS

---
 Trigger/TrigFTK/TrigFTKBankGen/CMakeLists.txt |   38 +
 .../TrigFTKBankGen/FTKBankGenAlgo.h           |  284 ++
 .../TrigFTKBankGen/FTKCachedBankGenAlgo.h     |   71 +
 .../TrigFTKBankGen/FTKConstGenAlgo.h          |  151 +
 .../TrigFTKBankGen/FTKPattGenRoot.h           |  157 ++
 .../TrigFTKBankGen/FTKPattGenRootAlgo.h       |   91 +
 .../TrigFTKBankGen/FTKPattKDTree.h            |  213 ++
 .../TrigFTKBankGen/FTKSectorSlice.h           |  115 +
 .../TrigFTKBankGen/PattMergeRootAlgo.h        |   44 +
 .../TrigFTKBankGen/atlparslice_root.h         |   65 +
 .../TrigFTKBankGen/decodeEtacode.h            |   17 +
 .../scripts/FTKConstantGen_tf.py              |   70 +
 .../scripts/FTKMatrixMerge_tf.py              |   83 +
 .../scripts/FTKMatrixReduction_tf.py          |   73 +
 .../scripts/FTKPattGenRoot_tf.py              |  247 ++
 .../share/FTKBankGen_joboptions.py            |  323 +++
 .../share/FTKCachedBankGen_jobOptions.py      |   63 +
 ...articleGenerator_mu_Pt1to1000_Eta30_FTK.py |   17 +
 ...cleGenerator_mu_Pt1to1000_Eta30_x10_FTK.py |   21 +
 ...articleGenerator_pi_Pt1to1000_Eta30_FTK.py |   16 +
 ...cleGenerator_pi_Pt1to1000_Eta30_x10_FTK.py |   16 +
 .../share/PattMergeRoot_jobOptions.py         |   85 +
 .../bsub_find_extrapolation_relations.py      |   22 +
 .../make_conn/find_extrapolation_relations.py |  485 ++++
 .../find_extrapolation_relations_v2.py        |  429 +++
 .../generate_connection/make_conn/ftkutils.py |  809 ++++++
 .../prep_banks_for_connection_prod.sh         |  138 +
 .../make_conn/prep_banks_for_simulation.sh    |  138 +
 .../make_conn/process_conn.sh                 |   86 +
 .../make_conn/tar_extrapolated_gcon.sh        |   53 +
 .../generate_connection/make_conn/utils.sh    |  153 +
 ...TKBankGenIBL_32TModB_HWMode2_joboptions.py |  109 +
 .../r2e_FTKBankGenIBL_32TModB_joboptions.py   |  109 +
 ...TKBankGenIBL_64TModB_HWMode2_joboptions.py |  109 +
 .../r2e_FTKBankGenIBL_64TModB_joboptions.py   |  109 +
 .../r2e_FTKBankGenIBL_HWMode2_joboptions.py   |   98 +
 ...TKBankGenIBL_Run2GEO_32TModB_joboptions.py |  111 +
 .../share/r2e_FTKBankGenIBL_joboptions.py     |   50 +
 .../share/r2e_FTKBankGenITk_joboptions.py     |   67 +
 .../share/r2e_FTKBankGen_joboptions.py        |  108 +
 .../share/skeleton.FTKCachedBankGen.py        |   91 +
 .../share/skeleton.FTKConstantGen.py          |   46 +
 .../share/skeleton.FTKMatrixMerge.py          |   48 +
 .../share/skeleton.FTKMatrixReduction.py      |   59 +
 .../share/skeleton.FTKPattBankGenRoot.py      |  192 ++
 .../TrigFTKBankGen/src/FTKBankGenAlgo.cxx     | 1460 ++++++++++
 .../src/FTKCachedBankGenAlgo.cxx              |  355 +++
 .../TrigFTKBankGen/src/FTKConstGenAlgo.cxx    | 2468 +++++++++++++++++
 .../TrigFTKBankGen/src/FTKPattGenRoot.cxx     | 1059 +++++++
 .../TrigFTKBankGen/src/FTKPattGenRootAlgo.cxx |  315 +++
 .../TrigFTKBankGen/src/FTKPattKDTree.cxx      |  765 +++++
 .../TrigFTKBankGen/src/FTKSectorSlice.cxx     |  321 +++
 .../TrigFTKBankGen/src/PattMergeRootAlgo.cxx  |  116 +
 .../TrigFTKBankGen/src/atlparslice_root.cxx   |  459 +++
 .../src/components/TrigFTKBankGen_entries.cxx |   33 +
 .../src/components/TrigFTKBankGen_load.cxx    |    6 +
 .../TrigFTKSim/TrigFTKSim/FTKDetectorTool.h   |    2 +
 .../TrigFTKSim/TrigFTKSim/FTKDetectorToolI.h  |    2 +
 .../TrigFTKSim/TrigFTKSim/FTKDumpCondAlgo.h   |    2 +
 .../TrigFTKSim/scripts/TrigFTKSim_tf.py       |    2 +
 .../share/FTKDumpCond_8LcIbl123_jobOptions.py |    5 +-
 .../share/skeleton.FTKStandaloneSim.py        |   22 +-
 .../TrigFTKSim/src/FTKDetectorTool.cxx        |   40 +
 .../TrigFTKSim/src/FTKDumpCondAlgo.cxx        |    8 +
 .../TrigFTK/TrigFTKSim/src/FTKMergerAlgo.cxx  |   19 +-
 .../TrigFTKSim/src/FTK_CompressedAMBank.cxx   |   29 +-
 .../src/components/TrigFTKSim_entries.cxx     |    3 +
 .../src/components/TrigFTKSim_load.cxx        |    3 +
 .../TrigFTK/TrigFTKSim/standalone/dataflow.cc |  207 +-
 .../TrigFTK/TrigFTKSim/standalone/dataflow.h  |   12 +-
 70 files changed, 13461 insertions(+), 131 deletions(-)
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/CMakeLists.txt
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKBankGenAlgo.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKCachedBankGenAlgo.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKConstGenAlgo.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRoot.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRootAlgo.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattKDTree.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKSectorSlice.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/PattMergeRootAlgo.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/atlparslice_root.h
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/decodeEtacode.h
 create mode 100755 Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKConstantGen_tf.py
 create mode 100755 Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixMerge_tf.py
 create mode 100755 Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixReduction_tf.py
 create mode 100755 Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKPattGenRoot_tf.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/FTKBankGen_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/FTKCachedBankGen_jobOptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_FTK.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_x10_FTK.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_FTK.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_x10_FTK.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/PattMergeRoot_jobOptions.py
 create mode 100755 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/bsub_find_extrapolation_relations.py
 create mode 100755 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations.py
 create mode 100755 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations_v2.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/ftkutils.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_connection_prod.sh
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_simulation.sh
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/process_conn.sh
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/tar_extrapolated_gcon.sh
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/utils.sh
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_HWMode2_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_HWMode2_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_HWMode2_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_Run2GEO_32TModB_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenITk_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGen_joboptions.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKCachedBankGen.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKConstantGen.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixMerge.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixReduction.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKPattBankGenRoot.py
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/FTKBankGenAlgo.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/FTKCachedBankGenAlgo.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/FTKConstGenAlgo.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRoot.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRootAlgo.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattKDTree.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/FTKSectorSlice.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/PattMergeRootAlgo.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/atlparslice_root.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_entries.cxx
 create mode 100644 Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_load.cxx

diff --git a/Trigger/TrigFTK/TrigFTKBankGen/CMakeLists.txt b/Trigger/TrigFTK/TrigFTKBankGen/CMakeLists.txt
new file mode 100644
index 00000000000..d39311afc5a
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/CMakeLists.txt
@@ -0,0 +1,38 @@
+################################################################################
+# Package: TrigFTKBankGen
+################################################################################
+
+# Declare the package name:
+atlas_subdir( TrigFTKBankGen )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          AtlasPolicy
+                          Control/AthenaBaseComps
+                          Control/AthenaKernel
+                          GaudiKernel
+                          Trigger/TrigFTK/TrigFTKSim )
+
+# External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
+find_package( Eigen )
+find_package( HepPDT )
+find_package( CLHEP )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+find_package( TBB )
+
+add_definitions(-DHAVE_BOOST_IOSTREAMS)
+
+# Component(s) in the package:
+atlas_add_component( TrigFTKBankGen
+                     src/*.cxx
+                     src/components/*.cxx
+                     INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${HEPPDT_INCLUDE_DIRS} ${TBB_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${HEPPDT_LIBRARIES} ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES} ${TBB_LIBRARIES} ${Boost_LIBRARIES} GaudiKernel TrigFTKSimLib )
+
+# Install files from the package:
+atlas_install_headers( TrigFTKBankGen )
+atlas_install_joboptions( share/*job[Oo]ptions.py share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_x10_FTK.py share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_x10_FTK.py share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_FTK.py share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_FTK.py )
+atlas_install_joboptions( share/skeleton.*.py )
+atlas_install_runtime( scripts/*_tf.py )
+
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKBankGenAlgo.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKBankGenAlgo.h
new file mode 100644
index 00000000000..78fd4e1a00e
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKBankGenAlgo.h
@@ -0,0 +1,284 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef FTKBankGenAlgo_h
+#define FTKBankGenAlgo_h
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+#include "TrigFTKSim/FTKPMap.h"
+#include "TrigFTKSim/FTKRegionMap.h"
+#include "TrigFTKSim/FTK_SGHitInput.h"
+#include "TrigFTKSim/FTKDataInput.h"
+#include "TrigFTKSim/TrackFitter.h"
+
+#include "TrigFTKBankGen/FTKConstGenAlgo.h"
+
+#include "TTree.h"
+
+#include <string>
+#include <vector>
+#include <ostream>
+#include <cassert>
+#include <fstream>
+#include <bitset>
+
+/////////////////////////////////////////////////////////////////////////////
+class ITHistSvc;
+class TH1F;
+class TH2F;
+
+//TODO prefer FTKHit
+//originally in FTKBankGenAlgo.h
+class filterSecHit{
+ public:
+  int count;
+  int sector;
+  int sector_HW;
+  int plane;
+  int hittype;
+  float dimx;
+  float dimy;
+  int ndim;
+  int CSide;
+  int ASide;
+  FTKHit originalhit;
+};
+
+class matrix{
+ public:
+  double C;
+  double D;
+  double Phi;
+  double Coto;
+  double Z;
+  float  nhit;
+};
+
+class FTKBankGenAlgo: public AthAlgorithm {
+public:
+  FTKBankGenAlgo (const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~FTKBankGenAlgo ();
+  StatusCode initialize();
+  StatusCode execute();
+  StatusCode finalize();
+  
+  class StoreGateSvc;
+  
+private:
+  
+  ITHistSvc *m_thistSvc;
+  StoreGateSvc*  m_storeGate;
+  ToolHandle<FTK_SGHitInputI> m_hitInputTool; // input handler
+  
+  TFile *file;
+
+  //for ConstGenTest  
+  int count_match;
+  int count_pass_filter;
+  double coverage;
+
+  //for event filter
+  int nmuon;
+  double pt,eta,truth_phi;
+
+  int m_nevent;
+  // Number of regions/banks
+  int m_nbanks;
+  int m_nsubregions;
+  int m_nregions;
+  
+  int m_verbosity;
+  bool m_BarrelOnly;
+  int m_rawMode;
+  int m_IBLMode; // flag to change the IBLMode
+  bool m_fixEndcapL0;
+  bool m_ITkMode; // flag to use ITk geometry
+
+  // Plane map pointer, to be set during the initialization
+  FTKPlaneMap *m_pmap;
+  FTKPlaneMap *m_pmap_8L;
+  
+  // region map used in this session
+  FTKRegionMap *m_rmap;
+  
+  int whichRegionAlt(int *sector, FTKRegionMap *rmap);
+
+  std::string m_pmap_path;
+  std::string m_pmap_8L_path;
+
+  std::string m_rmap_path;
+
+  /* the following flags were copied from TrigFTKSim/FTKDataInput.h on 11/02/14 check they are still up to date. Thanks, Guido*/
+  bool m_Clustering; // flag to enable the clustering
+  bool m_SaveClusterContent; // flag to allow the debug of the cluster content
+  bool m_DiagClustering; // true if diagonal clustering is used
+  bool m_SctClustering; // true if SCT clustering is performed
+  unsigned int m_PixelClusteringMode; // 1 means ToT information is used
+                                      //   && 400/600um pixels are accounted for
+                                      // 0 is default used up to 2013
+  bool m_DuplicateGanged;
+  bool m_GangedPatternRecognition;
+
+
+  bool m_UseIdentifierHash; // if true define a sector as a sequence of identifier hashes
+  
+  std::string m_sector_dir_path;//for const test
+  std::string m_gcon_dir_path;//for const test
+  char c_sector_dir_path[200];
+  char c_gcon_dir_path[200];
+
+  int m_nplanes;
+  int  TotalDim;
+  int  TotalDim2;
+  int *npatterns;
+  int *ntracks;
+  TTree *m_tree[100]; // expanded from 64-->100 to allow for more ITk regions
+
+  TTree *m_slicetree;
+  TTree *m_montree;
+  ULong64_t m_monval[100];
+
+  std::vector <short> int_c,int_phi,int_d0,int_z0,int_eta; 
+  std::vector<short> *m_intc;
+  std::vector<short> *m_intphi;
+  std::vector<short> *m_intd0;
+  std::vector<short> *m_intz0;
+  std::vector<short> *m_inteta;
+
+  int m_nc;
+  int m_nphi;
+  int m_nd0;
+  int m_nz0;
+  int m_neta;
+      
+  double m_par_c_max;
+  double m_par_c_min;
+  int m_par_c_slices;
+  
+  double m_par_phi_max;
+  double m_par_phi_min;
+  int m_par_phi_slices;
+
+  double m_par_d0_max;
+  double m_par_d0_min;
+  int m_par_d0_slices;
+  
+  double m_par_z0_max;
+  double m_par_z0_min;
+  int m_par_z0_slices;
+
+  double m_par_eta_max;
+  double m_par_eta_min;
+  int m_par_eta_slices; 
+
+  double m_c_max;
+  double m_c_min;
+  int m_c_slices;
+
+  double m_phi_max;
+  double m_phi_min;
+  int m_phi_slices;
+
+  double m_d0_max;
+  double m_d0_min;
+  int m_d0_slices;
+  
+  double m_z0_max;
+  double m_z0_min;
+  int m_z0_slices;
+
+  double m_eta_max;
+  double m_eta_min;
+  int m_eta_slices; 
+
+  
+  // hit information
+  unsigned int nhits;
+  int nsinglemu;
+  std::vector<FTKRawHit> orig_hits;
+  std::vector<FTKTruthTrack> truth_track;
+  std::vector<FTKTruthTrack> m_trainingtracks; // list of good training tracks
+  std::vector<FTKHit> hitslist;//use hit infomation
+  std::map<int, std::vector<FTKHit> > m_maphits;// map of the hits according the barcode
+  
+  // definitions of truth track 
+  float m_PT_THRESHOLD;
+  int m_TRAIN_PDG;
+  
+  int *p_ss;
+  int *p_hashss;
+  double *tmphitc;
+  
+  double *tmpxC;
+  double *tmpxD;
+  double *tmpxPhi;
+  double *tmpxCoto;
+  double *tmpxZ;
+  double *tmpcovx;
+     
+  int addPattReturnCode;
+
+  //track parameter
+  double x0,y0;
+  double c,d,phi,z0,coto;
+   
+  int m_nsector;
+  float m_nhit;
+  // tmp sector and matrix elements
+  
+  //TODO vector<int> m_sectorID;
+  int *m_sectorID;
+  int *m_hashID;
+  double*  m_tmpVec;
+  double m_tmpC;
+  double m_tmpD;
+  double m_tmpPhi;
+  double m_tmpCoto;
+  double m_tmpZ;
+
+  double *m_tmpxC;
+  double *m_tmpxD;
+  double *m_tmpxPhi;
+  double *m_tmpxCoto;
+  double *m_tmpxZ;
+  double *m_tmpcovx;
+  
+  matrix Mtmp;
+
+  //event definitions  
+  bool GoodTrack;
+  bool doPattgen;
+    
+  int tmp_sectorID;
+  int the_sectorID;
+  int *tmp_ssID; //TODO std::vector<int> tmp_SSID;
+  int *tmp_hashID; //TODO std::vector<int> tmp_SSID;
+
+  //for culcurate resolution
+  double dC;
+  double dD;
+  double dPhi;
+  double dZ0;
+  double dCoto;
+
+  ofstream file_resolution;
+  ofstream file_truthpar;
+  ofstream file_recpar;
+  ofstream file_coverage;
+
+  char str_gcon_file_name[200];
+  char str_sector_file_name[200];
+  string gcon_path;
+
+   FTKTrack base_trk;
+   FTKConstantBank **m_constant; // constant banks
+   bool m_const_test_mode;
+
+  double header[2];
+  double dummy;
+
+  std::bitset<128> m_compsecbitmask;
+};
+
+#endif // FTKBankGenAlgo_h
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKCachedBankGenAlgo.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKCachedBankGenAlgo.h
new file mode 100644
index 00000000000..7225e07cfb9
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKCachedBankGenAlgo.h
@@ -0,0 +1,71 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef FTKCachedBankGenAlgo_h
+#define FTKCachedBankGenAlgo_h
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaKernel/IAtRndmGenSvc.h"
+#include "GaudiKernel/ITHistSvc.h"
+#include <string>
+#include <vector>
+
+/////////////////////////////////////////////////////////////////////////////
+
+class FTKCachedBankGenAlgo: public AthAlgorithm {
+ public:
+  FTKCachedBankGenAlgo(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~FTKCachedBankGenAlgo();
+  StatusCode initialize();
+  StatusCode execute();
+  StatusCode finalize();
+  StatusCode RunCachedBankGenerator();
+   
+
+protected:
+   std::string m_pmap_path;
+   std::string m_rmap_path;
+   std::string m_modulelut_path =""; // ModuleLUT, required only for HWMODEID=2
+   std::string m_ssmapTSP_path;
+   std::string m_ssmapAM_path;
+
+   // Path of Bank
+   std::string m_in_bank_path;
+   std::string m_in_cache_path;
+   std::string m_out_ccache_path;
+   std::string m_out_pcache_path;
+
+   std::string m_sectordefHW0;
+   std::string m_sectordefHW2;
+
+   int m_hwmodeid_default; // HWMODEID
+   int m_hwmodeid_tspcc; // HWMODEID for sector-ordered and ccache format
+   int m_hwmodeid_dc; // HWMODEID for pcache format
+   int m_curreg; //! Region of interest
+   int m_nSubReg; //! number of subregions
+   int m_iSubReg; //! current subregion
+   int m_verbosity; // for debugging
+   long m_maxpatt; //! max. number of patterns, -1 if no cut is employed
+   int m_IBLMode; //! IBLMode (0: noIBL, 1: with IBL, 2: 3DIBL)
+   bool m_ITkMode; //! ITkMode (0: current geometry, 1: with ITk geometry)
+   std::string m_WhereToRun; //! in which athena step the pattern generation should be run
+   int m_flatFormat;
+
+   std::string m_partitionList;
+   int m_nSectorMax;
+   int m_nLamb;
+
+   int m_ndcMax;
+   std::vector<int> m_ndcMaxPlane;
+   int m_wildcardPenalty;
+   std::vector<int> m_wildcardPenaltyPlane;
+
+   std::string m_badmap_path;
+   std::string m_badmap_path2;
+
+private:
+
+};
+
+#endif // FTKCachedBankGenAlgo_h
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKConstGenAlgo.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKConstGenAlgo.h
new file mode 100644
index 00000000000..be7e5416dc2
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKConstGenAlgo.h
@@ -0,0 +1,151 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef FTKConstGenAlgo_h
+#define FTKConstGenAlgo_h
+
+#include "TrigFTKSim/FTKPMap.h"
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+#include "TTree.h"
+
+#include <string>
+#include <vector>
+#include <ostream>
+#include <cassert>
+
+
+class ITHistSvc;
+class TH1F;
+class TH2F;
+#define NPARS 5
+
+/** data structure that contain definition of geometrical
+    constants for linear fits */
+class geo_constants
+{
+ public:
+
+  double *Vd; // impact paramers coefs
+  double *Vc; // curvature coefs
+  double *Vf; // phi coefs
+  double *Vz0; // z0 coefs
+  double *Vo; // cot(theta) coefs
+  double **kernel; // kernel
+  double *kaverages; // averages
+  double Cd; // constant terms for: impact parameter
+  double Cc; // curvature
+  double Cf; // phi
+  double Cz0; // z0
+  double Co; // cot(theta)
+  int real; // this values is greater than 0 if these constants are correctly evaulated
+}; 
+
+
+class FTKConstGenAlgo: public AthAlgorithm {
+public:
+  FTKConstGenAlgo (const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~FTKConstGenAlgo ();
+  StatusCode initialize();
+  StatusCode execute();
+  StatusCode finalize();
+   
+  class StoreGateSvc;
+  
+ private:
+
+  ITHistSvc *m_thistSvc;
+  StoreGateSvc*  m_storeGate;
+  bool m_merging;
+  bool m_genconst;
+  bool m_subregion;
+  bool m_extract_1stStage;
+  std::string m_cfpath; 
+  std::vector<std::string> m_fpath;  
+  std::vector<std::string> m_gfpath;
+  std::vector<std::string> m_sfpath;
+  string m_extractpath;  
+  
+  std::string m_outfilename; // the algorithm mostly produce a single file, if set this is the name of the file, a default option is otherwise used
+  TFile *file;
+  TFile *good_file;
+  TFile *cfile;
+  TTree *m_ctree;
+
+  bool m_ITkMode; // toggle ITk geometry
+  bool m_allregion;
+  int m_region;
+  int m_nsubregion;
+  int m_nbank;
+  int m_nfile;
+  int addPattReturnCode;
+  float nsector;
+  bool match;
+ 
+  double pr;
+
+  int nevent;
+
+  int nplane;
+  int nplane8;
+
+  // variables for merge
+  std::vector<short> *m_mergeintc;
+  std::vector<short> *m_mergeintphi;
+  std::vector<short> *m_mergeintd0;
+  std::vector<short> *m_mergeintz0;
+  std::vector<short> *m_mergeinteta;
+  
+  // variables for extract 1st stage
+  int plane_index_1st_stage;
+  int plane_index_2nd_stage;
+  int coord_index_1st_stage;
+  int coord_index_2nd_stage;
+  int index_missing_plane;
+  int index_missing_coord;
+
+  std::vector<int> vec_plane_index_1st_stage;
+  std::vector<int> vec_plane_index_2nd_stage;
+  std::vector<int> vec_coord_index_1st_stage;
+  std::vector<int> vec_coord_index_2nd_stage;
+  std::vector<int> vec_doInvert;
+  std::vector<int> vec_ndimension;
+
+  // variables for 12L->8L
+  bool doRelation; // if true, this layer/coords has/have missing layer/coords
+  bool doInvert;// endcap inversion for some SCT layers
+  int inversion;
+  int inversion2;
+
+  std::vector<short> *m_extract_intc;
+  std::vector<short> *m_extract_intphi;
+  std::vector<short> *m_extract_intd0;
+  std::vector<short> *m_extract_intz0;
+  std::vector<short> *m_extract_inteta;
+  
+  // Plane map pointer, to be set during the initialization
+  FTKPlaneMap *m_pmap;
+  FTKPlaneMap *m_pmap_8L;
+
+  std::string m_pmap_path;
+  std::string m_pmap_8L_path;
+
+  bool *endcap_inversion; // true if endcap invert stereo and axial layer IDs
+
+  // functions
+  void merge();
+  void constantgen();
+  void extract_1stStage();
+  void make_subregion();
+  int mtx_eigen(int dim, double *mtx_v, double *eigval_v, double *eigvecs_v);
+  int mtx_invert(int dim, double *mtx_v);
+  void nullifyConstants(int sector,int ndim);
+  void sigmad(double *geoconstvect/*, double **marray*/, double **marrayinv,double *v,int dim);
+  float proj(double *vec1, double *vec2, int size);
+  int failedConstants(int sector,int ndim);
+
+};
+
+#endif // FTKConstGenAlgo_h
+
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRoot.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRoot.h
new file mode 100644
index 00000000000..6dc821017a4
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRoot.h
@@ -0,0 +1,157 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef FTKPattGenRoot_h
+#define FTKPattGenRoot_h
+
+/* package FTKPattGenRoot
+ *
+ * Class for merging of patterns stored in root format
+ * For instruction, see FTKPattGenRoot.cxx
+ *
+ */
+
+//#define DEBUG_BEAMSPOT
+
+#ifdef DEBUG_BEAMSPOT
+//#include "EventPrimitives/EventPrimitives.h"
+//#include "GeoPrimitives/GeoPrimitives.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkExInterfaces/IPropagator.h"
+#endif
+
+
+
+
+#include <iostream>
+#include <map>
+#include <vector>
+#include <string>
+#include <inttypes.h>
+#include <TDirectory.h>
+#include "TrigFTKSim/FTKLogging.h"
+#include "TrigFTKSim/FTKPMap.h"
+#include "TrigFTKSim/FTKRegionMap.h"
+#include "TrigFTKSim/FTKSSMap.h"
+#include "TrigFTKSim/FTKConstantBank.h"
+#include "TrigFTKBankGen/FTKSectorSlice.h"
+#include "TrigFTKSim/FTKPatternWithCoverage.h"
+#include "TrigFTKSim/FTKPatternBySector.h"
+#include "CLHEP/Random/RandomEngine.h"
+#include "CLHEP/Random/RandGauss.h"
+#include "CLHEP/Random/RandFlat.h"
+
+class FTKPattGenRoot : FTKLogging {
+public:
+   
+   enum SectorSelection {
+      // random sector
+      RndSector=0,
+      // check module geometry
+      //   if there are exact matches, use one of them, drop others. 
+      //   if there are no exact matches, use one of them
+      ModuleGeometry=1,
+      // check module geometry
+      //   if there are exact matches, use the one with lowest sectorID
+      //   if there are no exact matches, use one of them
+      ModuleGeometrySmallestSector=2,
+      ModuleGeometryBestMatch=3
+   };
+
+   FTKPattGenRoot(int curreg, FTKSSMap* ssmap , FTKSectorSlice* slices, FTKConstantBank* constbank,int keep7of8,double tolerance7of8
+#ifdef DEBUG_BEAMSPOT
+                  ,ToolHandle<Trk::IPropagator> *propagator
+#endif
+                  );
+   ~FTKPattGenRoot();
+   void setBeamspot(double beamspotX,double beamspotY);
+   bool isBeamAtZero(void) const;
+   void transformToOrigin(FTKTrack &track);
+   uint64_t trackInvertion(u_int64_t ntrials, bool smear=true);
+   void SetRandomNumberGenerator(CLHEP::HepRandomEngine* RndEng );				//! Track inversion
+   void ConvertPhi(FTKTrack& track);								//! Convert phi to the format used in the constants calculations
+   void GetRandomTrack(FTKTrack& track);							//! Generate random track
+   FTKPattGenRoot::SectorSelection GetSectorSelection() const { return m_select;}		//! Get selector algorithm
+   bool GoodTrack(const FTKTrack& track, int sector, FTKPatternWithSector* tmp_curpatt,int *missingPlanesPtr,double *distancePtr);
+   void SetModuleGeometryCheck(const std::string &fileName,
+                               FTKPattGenRoot::SectorSelection select); //! set sector selection algorithm and module geometry
+   void SetRootOutput(const std::string& outfilename);		                                //! Set filename to write patterns to root file  
+   void SetOverlapRemoval(int overlap) { m_overlap = overlap;}                                  //! Set algorithm for overlap removal: 0=disabled; 1=barrel-only, 2=everywhere
+   bool ReadSectorFile(const std::string& sectorfile);						//! Read in sector file
+   void DeleteMaps();										//! Delete/destroy all the given maps/slices/etc...
+   void WriteMapsToFile();                                                                      //! Write ssmap (and hence pmap and rmap) to output root-file.
+   void SetSliceParameters(double phi_min=-999,double phi_max=999, double c_min=-999,double c_max=999, 
+			   double d0_min=-999,double d0_max=999, double z0_min=-999,double z0_max=999, 
+			   double eta_min=-999, double eta_max=999);				//! Set slice parameters. If slice parametersa re not set, take them from the autotune procedure. Use +/- 999 for autotune parameters
+
+   void SetD0Exponent(double d0_alpha) { m_d0_alpha=d0_alpha; }
+protected:
+   
+   // input
+   const FTKPlaneMap* pmap() const;                                                             //! pmap is an ASCII file containing the match between the ATLAS planes and the FTK planes
+   int m_curreg;										//! Region
+   FTKSSMap *m_ssmap;										//! Super-strip map, this object transform an hit in a SS index
+   FTKSectorSlice* m_sectorslice;								//! FTKSectorSlice reads the slices file
+   FTKConstantBank* m_constbank;								//! FTKConstantsBank reads the fit constants file
+   SectorSelection m_select;									//! Selector algorithm
+
+   int m_overlap = 2;                                                                           //! Selector for overlap removal: 0=disabled; 1=barrel-only, 2=everywhere
+
+   // internal variables
+   // // HepRandomEngine is an abstract class defining the interface for each random engine.
+   //CLHEP::HepRandomEngine *m_pEng;
+   CLHEP::RandGauss *m_RndGauss;
+   CLHEP::RandFlat *m_RndFlat;
+ 
+   // sectors
+   std::vector<FTKHitPattern> m_sectorbank;  
+
+
+   // output
+   TDirectory *m_output;
+   FTKPatternBySectorWriter* m_patternWriter;                                                   //! output root file
+   // keep 7/8 layer patterns
+   int m_keep7of8;
+   double m_tolerance7of8;
+
+   // Slice parameters
+   double m_phi_min;
+   double m_phi_max;
+   double m_c_min;  
+   double m_c_max;  
+   double m_d0_min; 
+   double m_d0_max;
+   double m_z0_min; 
+   double m_z0_max; 
+   double m_eta_min;
+   double m_eta_max;
+   double m_d0_alpha;
+   // beamspot
+   double m_beamspot[2];
+#ifdef DEBUG_BEAMSPOT
+   double m_d0BS,m_z0BS;
+#endif
+   typedef struct {
+      float rMin,rMax,zMin,zMax;
+   } RZminmax_t;
+
+   std::map<int,RZminmax_t > m_moduleBounds;
+
+private:
+   double getRandom();
+   double getRandomGaus();
+   void OverlapRemoval(std::vector<FTKPatternWithSector>& patterns);
+   void RemovePattern(std::vector<FTKPatternWithSector>& patterns, unsigned int id);
+   int OverlapSectorBarrel(int s1, int s2 );
+   int OverlapSector(int s1, int s2 );
+
+protected:
+
+private:
+#ifdef DEBUG_BEAMSPOT
+   ToolHandle<Trk::IPropagator> *m_propagator;
+#endif
+};
+
+#endif
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRootAlgo.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRootAlgo.h
new file mode 100644
index 00000000000..099ee86b354
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattGenRootAlgo.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef FTKPattBankGenRootAlgo_h
+#define FTKPattBankGenRootAlgo_h
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaKernel/IAtRndmGenSvc.h"
+#include "GaudiKernel/ITHistSvc.h"
+#include "TrigFTKSim/FTKLogging.h"
+#include "TrigFTKBankGen/FTKPattGenRoot.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+class FTKPattGenRootAlgo: public AthAlgorithm , public FTKLogger {
+ public:
+  FTKPattGenRootAlgo(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~FTKPattGenRootAlgo();
+  StatusCode initialize();
+  StatusCode execute();
+  StatusCode finalize();
+
+protected:
+   virtual void PostMessage(void);
+
+   // Handle to the IAtRndmGenSvc
+   ServiceHandle<IAtRndmGenSvc> m_rndmSvc;
+
+   // // HepRandomEngine is an abstract class defining the interface for each random engine.
+   //CLHEP::HepRandomEngine* m_pEng;
+   
+   std::string m_ssmap_path;
+   //std::string m_ssmaptsp_path;
+   std::string m_pmap_path;
+   std::string m_rmap_path;
+   std::string m_modulelut_path;
+   std::string m_slices_path;
+   std::string m_fitconstants_path;
+   std::string m_sectors_path;
+   // std::string m_dbghit_path;
+
+   int m_curreg = 0; //! Region of interest
+   int m_overlap = 2; //! overlap removal: 0=disabled; 1=barrel-only, 2=everywhere
+   int m_HWMODEID = 0; //! (SS)HWMODEID (0 or 2)
+   int m_IBLMode; // flag to change the IBLMode
+   bool m_fixEndcapL0;
+   bool m_ITkMode; // flag to use ITk geometry
+
+   std::string m_rndStreamName;
+
+   u_int64_t m_trials; //! Number of trials of the trackInvertion function
+
+   // sector parameters
+   double m_phi_min;
+   double m_phi_max;
+   double m_c_min;
+   double m_c_max;
+   double m_d0_min;
+   double m_d0_max;
+   double m_z0_min;
+   double m_z0_max;
+   double m_eta_min;
+   double m_eta_max;
+   double m_d0_alpha;
+
+   // beam spot
+   double m_beamspotX,m_beamspotY;
+   
+   FTKSectorSlice* m_sectorslice  ; //! FTKSectorSlice reads the slices file
+   std::string m_OutputFile; //! output file to store patterns in
+
+   int m_keep7of8;
+   double m_tolerance7of8;
+
+   int m_sectorSelection;
+
+#ifdef DEBUG_BEAMSPOT
+   ToolHandle<Trk::IPropagator> *m_propagator;
+#endif
+   FTKPattGenRoot *m_pattgen;
+   uint64_t m_totalPatterns;
+   uint64_t m_totalThrown;
+
+   std::string m_ModuleGeometryFile;
+
+private:
+
+};
+
+#endif // FTKPattGenRootAlgo_h
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattKDTree.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattKDTree.h
new file mode 100644
index 00000000000..1d81c820e72
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKPattKDTree.h
@@ -0,0 +1,213 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef FTKPATTKDTREE_H
+#define FTKPATTKDTREE_H
+
+#include "TrigFTKBankGen/FTKBankGenAlgo.h"
+#include <stdio.h>
+
+#include <set>
+#include <map>
+#include <list>
+#include <vector>
+#include <utility>
+
+/** this class describes a KD-Tree to simplify
+    the search for patterns */
+class FTKPattKDTree {
+private:
+  int m_dim; // dimension of the space
+  int m_depth; // depth level, 0 is the top level
+  int m_below; // This element plus the number below it
+  int m_splitplane; // coordinate compared at this level
+  std::vector<int> m_pattern; // the pattern
+  std::vector<int> m_hashID; // the pattern
+  float m_hitcount; // number of times this pattern was hit
+  double m_tmpC;//tmpc
+  double m_tmpD;//tmpD
+  double m_tmpPhi;//tmpPhi
+  double m_tmpCoto;//tmCoto
+  double m_tmpZ;//tmpZ
+  float m_tmpnhit;//tmpnhit
+  std::vector<double> m_tmphitc; // the pattern
+  std::vector<double> m_tmpxC;
+  std::vector<double> m_tmpxD; 
+  std::vector<double> m_tmpxPhi;
+  std::vector<double> m_tmpxCoto;
+  std::vector<double> m_tmpxZ; 
+  std::vector<double> m_tmpcovx; 
+  std::vector<short> m_intc;
+  std::vector<short> m_intphi;
+  std::vector<short> m_intd0;
+  std::vector<short> m_intz0;
+  std::vector<short> m_inteta; 
+
+  int m_nmissing; // Number of wildcard hits in this pattern
+  FTKPattKDTree *m_parent; // parent element
+  FTKPattKDTree *m_left; // left sub-tree
+  FTKPattKDTree *m_right; // right sub-tree
+  
+
+public:
+  //    FTKPattKDTree(const std::vector<int>& pattern, 
+    FTKPattKDTree(const std::vector<int>& pattern, 
+		  const std::vector<int>& hashID, 
+		  const std::vector<double>& tmphitc,
+		  const std::vector<double>& tmpxC,
+		  const std::vector<double>& tmpxD,
+		  const std::vector<double>& tmpxPhi,
+		  const std::vector<double>& tmpxCoto,
+		  const std::vector<double>& tmpxZ,
+		  const std::vector<double>& tmpcovx,
+		  const std::vector<short>& int_c,
+		  const std::vector<short>& int_phi,
+		  const std::vector<short>& int_d0,
+		  const std::vector<short>& int_z0,
+		  const std::vector<short>& int_eta,
+		  const float& hitcount,
+		  int depth=0, FTKPattKDTree *parent=0,
+		  const double& tmpC=0,const double& tmpD=0,const double& tmpPhi=0,
+		  const double& tmpCoto=0,const double& tmpZ=0,const float& tmpnhit=0
+		  );
+    
+  ~FTKPattKDTree();
+
+  int addNode(const std::vector<int>& pattern,
+	      const std::vector<int>& hashID,
+	      const std::vector<double>& tmphic,
+	      const std::vector<double>& tmpxC,
+	      const std::vector<double>& tmpxD,
+	      const std::vector<double>& tmpxPhi,
+	      const std::vector<double>& tmpxCoto,
+	      const std::vector<double>& tmpxZ,
+	      const std::vector<double>& tmpcovx,
+	      const std::vector<short>& int_c,
+	      const std::vector<short>& int_phi,
+	      const std::vector<short>& int_d0,
+	      const std::vector<short>& int_z0,
+	      const std::vector<short>& int_eta,
+	      const float& hitcount,const double& tmpC,
+	      const double& tmpD,const double& tmpPhi,const double& tmpCoto,const double& tmpZ,
+	      const float& tmpnhit);
+  
+  int getCount() const { return m_below; }
+  float getHitCount() const { return m_hitcount; }
+  void incHitCount( float v=1 ) { m_hitcount += v; }
+  
+  void settmpC(double v){m_tmpC=v;};
+  void settmpD(double v){m_tmpD=v;};
+  void settmpPhi(double v){m_tmpPhi=v;};
+  void settmpCoto(double v){m_tmpCoto=v;};
+  void settmpZ(double v){m_tmpZ=v;};
+  void settmphitc(const std::vector<double>& v){m_tmphitc=v;};
+  void settmpxC(const std::vector<double>& v){m_tmpxC=v;};
+  void settmpxD(const std::vector<double>& v){m_tmpxD=v;};
+  void settmpxPhi(const std::vector<double>& v){m_tmpxPhi=v;};
+  void settmpxCoto(const std::vector<double>& v){m_tmpxCoto=v;};
+  void settmpxZ(const std::vector<double>& v){m_tmpxZ=v;};
+  void settmpcovx(const std::vector<double>& v){m_tmpcovx=v;};
+  
+  void setintc(const std::vector<short>& v){m_intc=v;};
+  void setintphi(const std::vector<short>& v){m_intphi=v;};
+  void setintd0(const std::vector<short>& v){m_intd0=v;};
+  void setintz0  (const std::vector<short>& v){m_intz0=v;};
+  void setinteta  (const std::vector<short>& v){m_inteta=v;};
+  
+  void settmpnhit(float v){m_tmpnhit=v;};
+
+  double gettmpC() const { return m_tmpC;}
+  double gettmpD() const { return m_tmpD;}
+  double gettmpPhi() const { return m_tmpPhi;}
+  double gettmpCoto() const { return m_tmpCoto;}
+  double gettmpZ() const { return m_tmpZ;}
+  double gettmpnhit() const{ return m_tmpnhit;}
+
+  const std::vector<double>& gettmphitc() const { return m_tmphitc;}
+  const std::vector<double>& gettmpxC() const { return m_tmpxC;}
+  const std::vector<double>& gettmpxD() const { return m_tmpxD;}
+  const std::vector<double>& gettmpxPhi() const { return m_tmpxPhi;}
+  const std::vector<double>& gettmpxCoto() const { return m_tmpxCoto;}
+  const std::vector<double>& gettmpxZ() const { return m_tmpxZ;}
+  const std::vector<double>& gettmpcovx() const { return m_tmpcovx;}
+  
+  const std::vector<short>& getintc() const { return m_intc;}
+  const std::vector<short>& getintphi() const { return m_intphi;}
+  const std::vector<short>& getintd0() const { return m_intd0;}
+  const std::vector<short>& getintz0() const { return m_intz0;}
+  const std::vector<short>& getinteta() const { return m_inteta;}
+  
+  int getNMissing() const { return m_nmissing; }
+  void getEndangered(std::set<std::pair<std::vector<int>, float> > &, bool);
+  void getAllBelow(std::vector< FTKPattKDTree* >& );
+  int recursiveRemove();
+  void markForRemoval();
+  void cleanup();
+  const std::vector<int>& getPattern() const { return m_pattern; }
+  const std::vector<int>& gethashID() const { return m_hashID; }
+  bool markedForRemoval() const { return (m_hitcount < 0); }
+  const int &getDepth() const { return m_depth; }
+  int getSplitPlane() const { return m_splitplane; }
+  void findSimilar(bool const_test,
+		   const std::vector<int>&, 
+		   const std::vector<double>&,
+		   const std::vector<double>&,
+		   const std::vector<double>&,
+		   const std::vector<double>&,
+		   const std::vector<double>&,
+		   const std::vector<double>&,
+		   const std::vector<double>&,
+		   const std::vector<short>&,
+		   const std::vector<short>&,
+		   const std::vector<short>&,
+		   const std::vector<short>&,
+		   const std::vector<short>&,
+		   std::set<FTKPattKDTree*> &, 
+		   bool exactmatch = false,const double& C=0,
+		   const double& tmpD=0,const double& tmpPhi=0,const double& tmpCoto=0,const double& tmpZ=0,
+		   const float& tmpnhit=0);
+};
+
+// Interface functions go here
+void initPattTree(int nbanks, int nplanes,int ndims);
+void finishPattTree();
+int addKDPattern(int bank, bool const_test_mode, int* pattern, int *hashID, int mult,matrix Mtmp,double* hitc,
+		 double* xC,double* xD,double* xPhi,double* xCoto,double* xZ,double* covx,
+		 vector<short> int_c,vector<short> int_phi,vector<short> int_d0,
+		 vector<short> int_z0,vector<short> int_eta);
+
+int loadPatterns(int bank, FILE *infile, int npatterns);
+int isTherePatt(int bank, int* pattern);
+int sortPatterns(int bank);
+int sortMPatterns(int bank);
+int getNPatterns( int bank);
+int getPatternSS(int bank, int pattid, int plane);
+int getPatthashID(int bank, int pattid, int plane);
+int getPattNHits(int bank, int pattid);
+double getPattC(int bank, int pattid);
+double getPattD(int bank, int pattid);
+double getPattPhi(int bank, int pattid);
+double getPattCoto(int bank, int pattid);
+double getPattZ(int bank, int pattid);
+double getPatthitc(int bank, int pattid,int dim);
+float  getPattnhit(int bank, int pattid);
+
+double getPattxC(int bank, int pattid,int dim);
+double getPattxD(int bank, int pattid,int dim);
+double getPattxPhi(int bank, int pattid,int dim);
+double getPattxCoto(int bank, int pattid,int dim);
+double getPattxZ(int bank, int pattid,int dim);
+double getPattcovx(int bank, int pattid,int dim);
+
+short getPattintc(int bank, int pattid,int nhit);
+short getPattintphi(int bank, int pattid,int nhit);
+short getPattintd0(int bank, int pattid,int nhit);
+short getPattintz0(int bank, int pattid,int nhit);
+short getPattinteta(int bank, int pattid,int nhit);
+
+//void print(); // used for debugging
+
+bool compare_patt(const FTKPattKDTree* a, const FTKPattKDTree* b);
+bool compare_Mpatt(const FTKPattKDTree* a, const FTKPattKDTree* b);
+
+#endif // FTKPATTKDTREE_H
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKSectorSlice.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKSectorSlice.h
new file mode 100644
index 00000000000..da1526e2c23
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/FTKSectorSlice.h
@@ -0,0 +1,115 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef FTKSectorSlice_h
+#define FTKSectorSlice_h
+
+#include <TROOT.h>
+#include <TrigFTKSim/FTKTrack.h>
+
+class FTKSectorSlice {
+
+ public:
+  FTKSectorSlice();
+   ~FTKSectorSlice(){};
+
+  void loadSlices(std::string slice_file_path);
+  double getAutotunePhiMin();
+  double getAutotuneCMin();
+  double getAutotuneDMin();
+  double getAutotuneZ0Min();
+  double getAutotuneCthetaMin();
+  double getAutotuneEtaMin();
+  double getAutotunePhiMax();
+  double getAutotuneCMax();
+  double getAutotuneDMax();
+  double getAutotuneZ0Max();
+  double getAutotuneCthetaMax();
+  double getAutotuneEtaMax();
+
+  // In case user wants to set ranges manually
+  void setPhiMin(const double &v) { m_phi_min = v; }
+  void setPhiMax(const double &v) { m_phi_max = v; }
+  void setCMin(const double &v) { m_c_min = v; }
+  void setCMax(const double &v) { m_c_max = v; }
+  void setD0Min(const double &v) { m_d0_min = v; }
+  void setD0Max(const double &v) { m_d0_max = v; }
+  void setZ0Min(const double &v) { m_z0_min = v; }
+  void setZ0Max(const double &v) { m_z0_max = v; }
+  void setEtaMin(const double &v) { m_eta_min = v; m_ctheta_min = TMath::SinH(v); }
+  void setEtaMax(const double &v) { m_eta_max = v; m_ctheta_max = TMath::SinH(v); }
+
+  // JW - to be used if the user inputs parameter ranges by hand after loading the slices
+  void resetStepSizes() {
+    m_step_phi = (m_phi_max - m_phi_min)/m_phi_nbins;
+    autotune(bits_phi,m_phi_min,m_phi_max,m_autotune_phi_min,m_autotune_phi_max,true,"phi");
+    m_step_c = (m_c_max - m_c_min)/m_c_nbins;
+    autotune(bits_c,m_c_min,m_c_max,m_autotune_c_min,m_autotune_c_max,false,"c");
+    m_step_d0 = (m_d0_max - m_d0_min)/m_d0_nbins;
+    autotune(bits_d,m_d0_min,m_d0_max,m_autotune_d0_min,m_autotune_d0_max,false,"d0");
+    m_step_z0 = (m_z0_max - m_z0_min)/m_z0_nbins;
+    autotune(bits_z0,m_z0_min,m_z0_max,m_autotune_z0_min,m_autotune_z0_max,false,"z0");
+    m_step_ctheta = (m_ctheta_max - m_ctheta_min)/m_ctheta_nbins;
+    autotune(bits_ctheta,m_ctheta_min,m_ctheta_max,m_autotune_ctheta_min,m_autotune_ctheta_max,false,"cos(theta)");
+    m_autotune_eta_min=TMath::ASinH(m_autotune_ctheta_min);
+    m_autotune_eta_max=TMath::ASinH(m_autotune_ctheta_max);
+  }
+
+  std::vector<int> *searchSectors(FTKTrack& track);
+
+ private:
+  TClonesArray *bits_phi;
+  TClonesArray *bits_c;
+  TClonesArray *bits_d;
+  TClonesArray *bits_z0;
+  TClonesArray *bits_ctheta;
+
+  void autotune(const TClonesArray *array,double_t x0,double_t x1,
+                double &autoMin,double &autoMax,
+                bool isAzimuth,const char *debug);
+
+  // Min and max parameters found out in the slice file
+  Double_t m_phi_min;
+  Double_t m_phi_max;
+  Double_t m_c_min;
+  Double_t m_c_max;
+  Double_t m_d0_min;
+  Double_t m_d0_max;
+  Double_t m_z0_min;
+  Double_t m_z0_max;
+  Double_t m_ctheta_min;
+  Double_t m_ctheta_max;
+  Double_t m_eta_min;
+  Double_t m_eta_max;
+  
+  double m_autotune_phi_min;
+  double m_autotune_c_min;
+  double m_autotune_d0_min;
+  double m_autotune_z0_min;
+  double m_autotune_ctheta_min;
+  double m_autotune_eta_min;
+  double m_autotune_phi_max;
+  double m_autotune_c_max;
+  double m_autotune_d0_max;
+  double m_autotune_z0_max;
+  double m_autotune_ctheta_max;
+  double m_autotune_eta_max;
+  
+  Int_t m_phi_nbins;
+  Int_t m_c_nbins;
+  Int_t m_d0_nbins;
+  Int_t m_z0_nbins;
+  Int_t m_ctheta_nbins;
+
+  Double_t m_step_phi;
+  Double_t m_step_c;
+  Double_t m_step_d0;
+  Double_t m_step_z0;
+  Double_t m_step_ctheta;
+
+  // Flag to use ITk geometry
+  bool m_ITkMode;
+
+  };
+
+#endif // FTKSectorSlice_h
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/PattMergeRootAlgo.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/PattMergeRootAlgo.h
new file mode 100644
index 00000000000..ce65c24d990
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/PattMergeRootAlgo.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef PattMergeRootAlgo_h
+#define PattMergeRootAlgo_h
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaKernel/IAtRndmGenSvc.h"
+#include "GaudiKernel/ITHistSvc.h"
+
+#include "TrigFTKSim/FTKLogging.h"
+#include <vector>
+#include <string>
+/////////////////////////////////////////////////////////////////////////////
+
+
+class PattMergeRootAlgo: public AthAlgorithm , public FTKLogger {
+ public:
+  PattMergeRootAlgo(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~PattMergeRootAlgo();
+  StatusCode initialize();
+  StatusCode execute();
+  StatusCode finalize();
+  StatusCode RunMerging();
+
+protected:
+   virtual void PostMessage(void); // FTKLogger write out to Athena
+
+
+protected:
+   std::string m_TextImportRootFile;
+   std::string m_RootOutFile;
+   std::string m_TextOutFile;
+   bool m_DeleteAfterMerging;   
+   int m_NSub;
+   int m_MinCov;
+   int m_Compression;
+   std::string m_WhereToRunMerging;
+   std::vector< std::string > m_InputFiles;
+ 
+};
+
+#endif // PattMergeRootAlgo_h
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/atlparslice_root.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/atlparslice_root.h
new file mode 100644
index 00000000000..67f9cf3aa8d
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/atlparslice_root.h
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef ATLPARSLICE_ROOT_H
+#define ATLPARSLICE_ROOT_H
+
+#include <TMath.h>
+#include <TFile.h>
+#include <TNtuple.h>
+#include <TClonesArray.h>
+#include <TBits.h>
+#include <vector>
+#include <iostream>
+class TSlices {
+ public:
+  TFile *ofile; // output file
+  TNtuple *n_slicedef; // ntuple with all the slice definitions
+  TClonesArray *c_bits_c; // c slices
+  TClonesArray *c_bits_d; // d slices
+  TClonesArray *c_bits_phi; // phi slices
+  TClonesArray *c_bits_z0; // z0 slices
+  TClonesArray *c_bits_ctheta; // ctheta slices
+  TBits *result_bits;
+  //    std::vector<int> finalSectors;
+  unsigned int curPos; // popSector current position pointer
+  
+ public:
+  // slice parameters
+  Int_t par_c_slices;
+  Double_t par_c_max;
+  Double_t par_c_min;
+  
+  Int_t par_d_slices;
+  Double_t par_d_max;
+  Double_t par_d_min;
+  
+  Int_t par_phi_slices;
+  Double_t par_phi_max;
+  Double_t par_phi_min;
+  
+  Int_t par_z0_slices;
+  Double_t par_z0_max;
+  Double_t par_z0_min;
+  
+  Int_t par_ctheta_slices;
+  Double_t par_ctheta_max;
+  Double_t par_ctheta_min;
+ public:
+  TSlices(int *nslices, double *min_vals, double *max_vals);
+  ~TSlices();
+};
+
+  
+// FlagAK: allow to work with multiple slices simultaneously, indexed by the index variable
+void initNSlices(int N, int *nslices, double *min_vals, double *max_vals);
+void initSlices(int index, int nsectors);
+void addSectorToSlice(int index, int sector, int c, int d, int phi, int z0, int ctheta);
+void saveSlices(int index, char *slice_file);
+//int popSector(int index);
+//void printSectors(int index);
+void searchSectors(int index, double c, double d, double phi, double z0, double ctheta);
+int checkSector(int index, int sector,double c, double d, double phi, double z0, double ctheta);
+void loadSlices(int index, char *slice_file);
+
+#endif // ATLPARSLICE_ROOT_H
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/decodeEtacode.h b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/decodeEtacode.h
new file mode 100644
index 00000000000..f3d99816ddf
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/TrigFTKBankGen/decodeEtacode.h
@@ -0,0 +1,17 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef __H_DECODEETACODE__
+#define __H_DECODEETACODE__
+
+// decode "etacode", see TrigFTKSim/FTKHit.h
+
+#define SECTION_INT(a) (a%1000 < 20 ? 0 : (a%10))
+#define ETA_CODE_INT(a) (a%1000)
+#define PHI_MOD_INT(a) (a/1000)
+#define ETA_MOD_INT(a) (a%1000 < 20 ? a%1000 : (a%1000)/20-1)
+#define ASIDE_INT(a) (a%1000 < 20 ? 0 : ((ETA_CODE_INT(a))/10)%2 == 0) //POSEC
+#define CSIDE_INT(a) (a%1000 < 20 ? 0 : ((ETA_CODE_INT(a))/10)%2)      //NEGEC
+
+
+#endif
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKConstantGen_tf.py b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKConstantGen_tf.py
new file mode 100755
index 00000000000..b5223f11b6c
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKConstantGen_tf.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+## FTK Simulation Transform
+# @version $Id: FTKConstantGen_tf.py 718878 2016-01-20 17:27:51Z jwebster $ 
+import argparse
+import sys
+import time
+import traceback
+
+import logging
+
+# Setup core logging here
+from PyJobTransforms.trfLogger import msg
+msg.info('logging set in %s' % sys.argv[0])
+
+from PyJobTransforms.trfExitCodes import trfExit
+from PyJobTransforms.transform import transform
+from PyJobTransforms.trfExe import athenaExecutor
+from PyJobTransforms.trfDecorators import stdTrfExceptionHandler, sigUsrStackTrace
+
+import PyJobTransforms.trfExceptions as trfExceptions
+import PyJobTransforms.trfArgClasses as trfArgClasses
+
+@stdTrfExceptionHandler
+@sigUsrStackTrace
+def main():
+    
+    msg.info('This is %s' % sys.argv[0])
+        
+    trf = getTransform() 
+    trf.parseCmdLineArgs(sys.argv[1:])
+    trf.execute()
+    trf.generateReport()
+
+    msg.info("%s stopped at %s, trf exit code %d" % (sys.argv[0], time.asctime(), trf.exitCode))
+    sys.exit(trf.exitCode)
+
+
+## Get the base transform with all arguments added
+def getTransform():
+    trf = transform(executor = athenaExecutor(name = 'FTKConstantGen', 
+                                              skeletonFile = 'TrigFTKBankGen/skeleton.FTKConstantGen.py'))
+    addFTKPattGenArgs(trf.parser)
+    return trf
+
+
+def addFTKPattGenArgs(parser):
+    # Add a specific FTK argument group
+    parser.defineArgGroup('FTKConstantGen', 'Fast tracker simulation options')
+
+    parser.add_argument('--NBanks', type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Number of pattern banks', group='FTKConstantGen')
+
+    parser.add_argument('--bankregion', type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Bank region number', group='FTKConstantGen')
+   
+    # parser.add_argument('--allregions', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+    #                     help='Merge all regions', group='FTKConstantGen')
+    
+    parser.add_argument('--genconst', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Generate the sectors and constants', group='FTKConstantGen')
+    
+    parser.add_argument('--inputFTKMatrixFile', type=trfArgClasses.argFactory(trfArgClasses.argNTUPFile,runarg=True), 
+                       help="input matrix file", group="FTKConstantGen" )
+
+    parser.add_argument('--ITkMode', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Use ITk geometry', group='FTKConstantGen')
+
+if __name__ == '__main__':
+    main()
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixMerge_tf.py b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixMerge_tf.py
new file mode 100755
index 00000000000..a72626e97a8
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixMerge_tf.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+
+## FTK Simulation Transform
+# @version $Id: FTKMatrixMerge_tf.py 574395 2013-12-07 10:13:16Z gvolpi $ 
+import argparse
+import sys
+import time
+import traceback
+
+import logging
+
+# Setup core logging here
+from PyJobTransforms.trfLogger import msg
+msg.info('logging set in %s' % sys.argv[0])
+
+from PyJobTransforms.trfExitCodes import trfExit
+from PyJobTransforms.transform import transform
+from PyJobTransforms.trfExe import athenaExecutor
+from PyJobTransforms.trfDecorators import stdTrfExceptionHandler, sigUsrStackTrace
+
+import PyJobTransforms.trfExceptions as trfExceptions
+import PyJobTransforms.trfArgClasses as trfArgClasses
+
+@stdTrfExceptionHandler
+@sigUsrStackTrace
+def main():
+    
+    msg.info('This is %s' % sys.argv[0])
+        
+    trf = getTransform() 
+    trf.parseCmdLineArgs(sys.argv[1:])
+    trf.execute()
+    trf.generateReport()
+
+    msg.info("%s stopped at %s, trf exit code %d" % (sys.argv[0], time.asctime(), trf.exitCode))
+    sys.exit(trf.exitCode)
+
+
+## Get the base transform with all arguments added
+def getTransform():
+    trf = transform(executor = athenaExecutor(name = 'FTKMatrixMerge', 
+                                              skeletonFile = 'TrigFTKBankGen/skeleton.FTKMatrixMerge.py'))
+    addFTKPattGenArgs(trf.parser)
+    return trf
+
+
+def addFTKPattGenArgs(parser):
+    # Add a specific FTK argument group
+    parser.defineArgGroup('FTKMatrixMerge', 'Fast tracker simulation options')
+
+    parser.add_argument('--NBanks', type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Number of pattern banks', group='FTKMatrixMerge')
+
+    parser.add_argument('--bankregion', type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Bank region number', group='FTKMatrixMerge')
+   
+    parser.add_argument('--allregions', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Merge all regions', group='FTKMatrixMerge')
+    
+    parser.add_argument('--genconst', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Generate the sectors and constants', group='FTKMatrixMerge')
+    
+    parser.add_argument('--inputFTKMatrixFile', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argNTUPFile, runarg=True, io='input'),
+
+                        help='List of matrix files',group='FTKMatrixMerge',nargs='+')
+
+    parser.add_argument('--FTKMatrixFileRegEx', group="FTKMatrixMerge",
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True),
+                        help="Regular expression to select the input files from the working dir")
+
+    parser.add_argument('--MaxInputFiles', group="FTKMatrixMerge",
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True),
+                        help="Max number of input files to include, only interpretted when used in combination with FTKMatrixFileRegEx")
+
+    parser.add_argument('--outputMergedFTKMatrixFile', type=trfArgClasses.argFactory(trfArgClasses.argNTUPFile,runarg=True),
+                       help="Output file", group="FTKMatrixMerge" )
+
+    parser.add_argument('--ITkMode', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Use ITk geometry', group='FTKMatrixMerge')
+
+if __name__ == '__main__':
+    main()
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixReduction_tf.py b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixReduction_tf.py
new file mode 100755
index 00000000000..890f94a06e8
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKMatrixReduction_tf.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+## FTK Simulation Transform
+# @version $Id: FTKMatrixReduction_tf.py 686533 2015-07-30 15:33:01Z tomoya $ 
+import argparse
+import sys
+import time
+import traceback
+
+import logging
+
+# Setup core logging here
+from PyJobTransforms.trfLogger import msg
+msg.info('logging set in %s' % sys.argv[0])
+
+from PyJobTransforms.trfExitCodes import trfExit
+from PyJobTransforms.transform import transform
+from PyJobTransforms.trfExe import athenaExecutor
+from PyJobTransforms.trfDecorators import stdTrfExceptionHandler, sigUsrStackTrace
+
+import PyJobTransforms.trfExceptions as trfExceptions
+import PyJobTransforms.trfArgClasses as trfArgClasses
+
+@stdTrfExceptionHandler
+@sigUsrStackTrace
+def main():
+    
+    msg.info('This is %s' % sys.argv[0])
+        
+    trf = getTransform() 
+    trf.parseCmdLineArgs(sys.argv[1:])
+    trf.execute()
+    trf.generateReport()
+
+    msg.info("%s stopped at %s, trf exit code %d" % (sys.argv[0], time.asctime(), trf.exitCode))
+    sys.exit(trf.exitCode)
+
+
+## Get the base transform with all arguments added
+def getTransform():
+    trf = transform(executor = athenaExecutor(name = 'FTKMatrixReduction', 
+                                              skeletonFile = 'TrigFTKBankGen/skeleton.FTKMatrixReduction.py'))
+    addFTKPattGenArgs(trf.parser)
+    return trf
+
+
+def addFTKPattGenArgs(parser):
+    # Add a specific FTK argument group
+    parser.defineArgGroup('FTKMatrixReduction', 'Fast tracker simulation options')
+
+    parser.add_argument('--NBanks', type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Number of pattern banks', group='FTKMatrixReduction')
+
+    parser.add_argument('--bankregion', type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Bank region number', group='FTKMatrixReduction')
+   
+    parser.add_argument('--allregions', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Merge all regions', group='FTKMatrixReduction')
+    
+    parser.add_argument('--eightLayer', type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Reduce 12L matrix to 8L matrix', group='FTKMatrixReduction')
+    
+    parser.add_argument('--pmap_12L', type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='12L pmap file', group='FTKMatrixReduction')
+    
+    parser.add_argument('--pmap_8L', type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='8L pmap file', group='FTKMatrixReduction')
+    
+    parser.add_argument('--inputFTKMatrixFile', type=trfArgClasses.argFactory(trfArgClasses.argNTUPFile,runarg=True), 
+                       help="input matrix file", group="FTKMatrixReduction" )
+
+if __name__ == '__main__':
+    main()
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKPattGenRoot_tf.py b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKPattGenRoot_tf.py
new file mode 100755
index 00000000000..0654f8bd7e8
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/scripts/FTKPattGenRoot_tf.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python
+
+## FTK Simulation Transform
+
+import argparse
+import sys
+import time
+import traceback
+import logging
+
+# Setup core logging here
+from PyJobTransforms.trfLogger import msg
+msg.info('logging set in %s' % sys.argv[0])
+
+from PyJobTransforms.trfExitCodes import trfExit
+from PyJobTransforms.transform import transform
+from PyJobTransforms.trfExe import athenaExecutor
+from PyJobTransforms.trfArgs import addAthenaArguments
+from PyJobTransforms.trfDecorators import stdTrfExceptionHandler, sigUsrStackTrace
+
+import PyJobTransforms.trfExceptions as trfExceptions
+import PyJobTransforms.trfArgClasses as trfArgClasses
+
+@stdTrfExceptionHandler
+@sigUsrStackTrace
+
+# ___________________________________________________________________________ #
+def main():
+    
+    msg.info('This is %s' % sys.argv[0])
+        
+    trf = getTransform() 
+    trf.parseCmdLineArgs(sys.argv[1:])
+    trf.execute()
+    trf.generateReport()
+
+    msg.info("%s stopped at %s, trf exit code %d" % (sys.argv[0], time.asctime(), trf.exitCode))
+    sys.exit(trf.exitCode)
+
+
+
+# ___________________________________________________________________________ #
+def getTransform():
+# Get the base transform with all arguments added
+    trf = transform(executor = athenaExecutor(name = 'FTKPattGenRoot', 
+                                              skeletonFile = 'TrigFTKBankGen/skeleton.FTKPattBankGenRoot.py'))
+    addAthenaArguments(trf.parser)
+    addFTKPattGenArgs(trf.parser)
+    return trf
+
+
+
+# ___________________________________________________________________________ #
+def addFTKPattGenArgs(parser):
+    # Add a specific FTK argument group
+    parser.defineArgGroup('FTKPattGenRoot', 'Options for FTKPattGenRootAlgo for pattern generation')
+
+    # --- 'number of calls of trackInvertion '
+    parser.add_argument('--maxEvents', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True),
+                        help='Number of events to be processed', 
+                        group='FTKPattGenRoot')
+
+    # --- output file (optional)
+    parser.add_argument('--OutputFile', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='Name of the output file', 
+                        group='FTKPattGenRoot')
+
+    # --- path's to maps
+    parser.add_argument('--pmap_path', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='Location of pmap file', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--rmap_path', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='Location of rmap file', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--ssmap_path', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='Location of ssmap file', 
+                        group='FTKPattGenRoot')
+    
+    # --- path's to constants
+    parser.add_argument('--slices', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True),
+                        help='Slices file', 
+                        group='FTKPattGenRoot')
+    parser.add_argument('--fitconsts', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True),
+                        help='Fit-constants path file', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--sectors', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True),
+                        help='sectors  path file', 
+                        group='FTKPattGenRoot')
+
+    # --- patt-gen options
+    parser.add_argument('--curreg', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Current region', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--seed', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='primary seed of the random generator', 
+                        group='FTKPattGenRoot')
+    parser.add_argument('--seed2', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='secondary seed of the random generator', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--hwmodeid', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Set format of the SS-ID.', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--ModuleLUTPath', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='look-up table for HWMODEID=2',
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--IBLMode', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Set IBL Mode. Options are 0, 1 or 2.', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--FixEndcapL0', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Endcap layer fix, 0 or 1.', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--ITkMode', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True), 
+                        help='Run assuming ITk geometry', 
+                        group='FTKPattGenRoot')
+    
+    parser.add_argument('--pconst_overlap', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Overlap removal: 0=disabled; 1=barrel-only, 2=everywhere', 
+                        group='FTKPattGenRoot')
+
+#    parser.add_argument('--smear', 
+#                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+#                        help='Boolean flag to set the smearing', 
+#                        group='FTKPattGenRoot')
+
+    parser.add_argument('--trials', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='Number of trials of the trackInvertion function', 
+                        group='FTKPattGenRoot')
+
+    # --- further options
+    parser.add_argument('--phi_min', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter phi min', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--phi_max', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter phi max', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--c_min', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter c min', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--c_max', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter c max', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--d0_min', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter d0 min', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--d0_max', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter d0 max', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--z0_min', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter z0 min', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--z0_max', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter z0 max', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--eta_min', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter eta min', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--eta_max', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='Slice parameter eta max', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--d0_alpha', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='exponent for d0 distribution', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--keep7of8', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='bit-mask of allowed missing planes for 7/8', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--tolerance7of8', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='tolerance for 7/8 option', 
+                        group='FTKPattGenRoot')
+    parser.add_argument('--beamspotX', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='beamspot (X)', 
+                        group='FTKPattGenRoot')
+    parser.add_argument('--beamspotY', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argFloat, runarg=True), 
+                        help='beamspot (Y)', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--ModuleGeometryFile', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+                        help='module positions for improving the slices', 
+                        group='FTKPattGenRoot')
+
+    parser.add_argument('--sectorSelection', 
+                        type=trfArgClasses.argFactory(trfArgClasses.argInt, runarg=True), 
+                        help='sector selection algorithm (0:loose .. 3:tight)', 
+                        group='FTKPattGenRoot')
+    
+#    parser.add_argument('--pattgenalgo', 
+#                        type=trfArgClasses.argFactory(trfArgClasses.argString, runarg=True), 
+#                        help='Algorithm type: 1=random sector selection; 2=weighted random sector selection; 3=all patterns of all sectors; 4=random pattern selection; 5=weighted random pattern selection', 
+#                        group='FTKPattGenRoot')
+    
+
+if __name__ == '__main__':
+    main()
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/FTKBankGen_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/FTKBankGen_joboptions.py
new file mode 100644
index 00000000000..3158cab53be
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/FTKBankGen_joboptions.py
@@ -0,0 +1,323 @@
+#-----------------------------------------------------------------------------
+# Athena imports
+#-----------------------------------------------------------------------------
+from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import theApp
+from AthenaCommon.AppMgr import ServiceMgr
+import AthenaPoolCnvSvc.ReadAthenaPool
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+OutputLevel = INFO
+doJiveXML       = False
+doVP1           = False
+doWriteESD      = False
+doWriteAOD      = False
+doReadBS        = False
+doAuditors      = True
+
+import os
+doEdmMonitor    = False
+doNameAuditor   = False
+
+#-----------------------------------------------------------------------------
+# Set output level threshold (2=DEBUG, 3=INFO, 4=WARNING, 5=ERROR, 6=FATAL )
+ServiceMgr.MessageSvc.OutputLevel = WARNING
+import AthenaServices
+AthenaServices.AthenaServicesConf.AthenaEventLoopMgr.OutputLevel = WARNING
+
+
+#-----------------------------------------------------------------------------
+# Input Datasets
+#-----------------------------------------------------------------------------
+
+ServiceMgr.EventSelector.InputCollections = ['rdo.pool.root']
+
+event=10000
+theApp.EvtMax = event # -1 means all events
+
+from InDetBeamSpotService.InDetBeamSpotServiceConf import BeamCondSvc
+ServiceMgr+=BeamCondSvc(useDB=False,
+                        posX=0.00,
+                        posY=0.00,
+                        posZ=0.00,
+                        sigmaX=0.000001,
+                        sigmaY=0.000001,
+                        sigmaZ=0.01,
+                        tiltX=0.0,
+                        tiltY=0.0
+# width average from run 161242 - 162347
+#                        sigmaX=0.0378,
+#                        sigmaY=0.0373,
+#                        sigmaZ=66.644,
+#                        tiltX=0.0,
+#                        tiltY=0.0
+#  for run #152166, except for angle info !!! wrong run number !!!
+#                        pqosX=-0.353,
+#                        pqosY=0.667,
+#                        pqosZ=3.05,
+#                        sigmaX=0.0444,
+#                        sigmaY=0.0757,
+#                        sigmaZ=25.6,
+#                        tiltX=0.0,
+#                        tiltY=-0.0
+#  for run #167776, except for angle info
+#                        posX=0.0776,
+#                        posY=1.13,
+#                        posZ=12.,
+#                        sigmaX=0.0395,
+#                        sigmaY=0.0394,
+#                        sigmaZ=0.000025,
+#                        tiltX=0.0,
+#                        tiltY=0.0
+                        )
+#
+
+# Reconstruction setup
+
+# DetDescrVersion = "ATLAS-GEO-16-00-00"
+# ConditionsTag = "OFLCOND-DR-BS7T-A100-04"
+#DetDescrVersion = "ATLAS-GEO-18-01-03"
+#ConditionsTag = "OFLCOND-SDR-BS14T-IBL-11"
+DetDescrVersion = "ATLAS-IBL-03-00-00"
+ConditionsTag = "OFLCOND-MC12-IBL-20-30-25"
+
+
+#ConditionsTag = "OFLCOND-SDR-BS14T-IBL-03"
+
+from AthenaCommon.GlobalFlags import globalflags
+globalflags.DetGeo = 'atlas'
+globalflags.DataSource = 'geant4'
+globalflags.InputFormat = 'pool'
+globalflags.DetDescrVersion = DetDescrVersion
+globalflags.ConditionsTag = ConditionsTag
+globalflags.print_JobProperties()
+from AthenaCommon.BeamFlags import jobproperties
+jobproperties.Beam.numberOfCollisions = 0.0  
+from CaloRec.CaloCellFlags import jobproperties
+jobproperties.CaloCellFlags.doLArCellEmMisCalib=False;
+
+if len(globalflags.ConditionsTag())!=0:
+   print 'DEBUG -- If statement entered (code=01234567)'
+   from IOVDbSvc.CondDB import conddb
+   conddb.setGlobalTag(globalflags.ConditionsTag()) 
+
+from RecExConfig.RecFlags import rec
+
+rec.doCalo=False
+rec.doInDet=True
+rec.doMuon=False
+rec.doJetMissingETTag=False
+rec.doEgamma=False
+rec.doMuonCombined=False
+rec.doTau=False
+rec.doTrigger=False
+
+rec.Commissioning.set_Value_and_Lock(True)
+
+from AthenaCommon.DetFlags import DetFlags 
+# --- switch on InnerDetector, turn off TRT
+DetFlags.ID_setOn()
+#DetFlags.makeRIO.pixel_setOff()
+#DetFlags.makeRIO.SCT_setOff()
+DetFlags.makeRIO.TRT_setOff()
+
+# --- and switch off all the rest
+DetFlags.Calo_setOff()
+DetFlags.Muon_setOff()
+# ---- switch parts of ID off/on as follows (always use both lines)
+#DetFlags.pixel_setOff()
+#DetFlags.detdescr.pixel_setOn()
+#DetFlags.SCT_setOff()
+#DetFlags.detdescr.SCT_setOn()
+DetFlags.TRT_setOff()
+DetFlags.detdescr.TRT_setOn()
+# --- printout
+DetFlags.Print()
+
+#--------------------------------------------------------------
+# Load InDet configuration
+#--------------------------------------------------------------
+
+# --- setup InDetJobProperties
+from InDetRecExample.InDetJobProperties import InDetFlags
+InDetFlags.doTruth       = True
+
+InDetFlags.doBackTracking.set_Value_and_Lock(True)
+InDetFlags.doTRTStandalone.set_Value_and_Lock(True)
+InDetFlags.doPixelClusterSplitting.set_Value_and_Lock(False)
+InDetFlags.writeRDOs.set_Value_and_Lock(True)
+from TriggerJobOpts.TriggerFlags import TriggerFlags
+TriggerFlags.doLVL2.set_Value_and_Lock(True)
+TriggerFlags.doEF.set_Value_and_Lock(True)
+
+# --- uncomment to change the default of one of the following options:
+#InDetFlags.doNewTracking  = False
+#InDetFlags.doLowPt        = True
+#InDetFlags.doBeamGas      = True
+#InDetFlags.doBeamHalo     = True
+#InDetFlags.doxKalman      = False
+#InDetFlags.doiPatRec      = False
+#InDetFlags.doBackTracking = False
+#InDetFlags.doTRTStandalone = False
+#InDetFlags.doSingleSpBackTracking = True
+
+# --- Turn off track slimming
+#InDetFlags.doSlimming = False
+
+# --- possibility to run tracking on subdetectors separately (and independent from each other)
+InDetFlags.doTrackSegmentsPixel = True
+InDetFlags.doTrackSegmentsSCT   = True
+InDetFlags.doTrackSegmentsTRT   = True
+
+# --- possibility to change the trackfitter
+#InDetFlags.trackFitterType = 'KalmanFitter'
+
+# --- activate monitorings
+InDetFlags.doMonitoringGlobal    = False
+InDetFlags.doMonitoringPixel     = False
+InDetFlags.doMonitoringSCT       = False
+InDetFlags.doMonitoringTRT       = False
+InDetFlags.doMonitoringAlignment = False
+
+# --- activate (memory/cpu) monitoring
+#InDetFlags.doPerfMon = True
+
+# --- activate ntuple writing for IDRecStat (if it is on)
+#InDetFlags.doStatNtuple    = True
+
+# --- activate creation of standard plots
+#InDetFlags.doStandardPlots  = True
+
+# --- produce various ntuples (all in one root file)
+#InDetFlags.doTrkNtuple      = True
+#InDetFlags.doPixelTrkNtuple = True
+#InDetFlags.doVtxNtuple      = True
+#InDetFlags.doConvVtxNtuple  = True
+
+# activate the print InDetXYZAlgorithm statements
+InDetFlags.doPrintConfigurables = True
+
+from IOVDbSvc.CondDB import conddb;
+conddb.addOverride("/PIXEL/PixMapOverlay","PixMapOverlay-IBL-PERFECT");
+conddb.addOverride("/SCT/DAQ/Configuration/Geog","SctDaqConfigurationGeog-PERFECT-Aug10-01");
+conddb.addOverride("/SCT/DAQ/Configuration/ROD","SctDaqConfigurationRod-PERFECT-Aug10-01");
+conddb.addOverride("/SCT/DAQ/Configuration/RODMUR","SctDaqConfigurationRodmur-PERFECT-Aug10-01");
+conddb.addOverride("/SCT/DAQ/Configuration/MUR","SctDaqConfigurationMur-PERFECT-Aug10-01");
+conddb.addOverride("/SCT/DAQ/Configuration/Module","SctDaqConfigurationModule-PERFECT-Aug10-01");
+conddb.addOverride("/SCT/DAQ/Configuration/Chip","SctDaqConfigurationChip-PERFECT-Aug10-01");
+conddb.addOverride("/SCT/DAQ/Calibration/NPtGainDefects","SctDaqCalibrationNPtGainDefects-NOMINAL");
+conddb.addOverride("/SCT/DAQ/Calibration/NoiseOccupancyDefects","SctDaqCalibrationNoiseOccupancyDefects-NOMINAL") 
+
+include("InDetIBL_Example/preInclude.IBL_Rec.py")
+include("InDetIBL_Example/NewLayerMaterial_03.py")
+include("InDetIBL_Example/preInclude.AllDetOn.py")
+
+# IMPORTANT NOTE: initialization of the flags and locking them is done in InDetRec_jobOptions.py!
+# This way RecExCommon just needs to import the properties without doing anything else!
+# DO NOT SET JOBPROPERTIES AFTER THIS LINE! The change will be ignored!
+include("InDetRecExample/InDetRec_all.py")
+
+include("InDetIBL_Example/postInclude.IBL_Rec.py")
+include("InDetIBL_Example/postInclude.IBL_NoAlign.py")
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for IBL
+FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_12Libl.pmap"
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIbl123.pmap"
+FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = False;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 64;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = True;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+#-----------------------------------------------------------------------------
+# save ROOT histograms and Tuple
+#-----------------------------------------------------------------------------
+#from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
+#Stream1 = AthenaPoolOutputStream( "Stream1" )
+#Stream1.OutputFile =   "SimplePoolFile_Complete.root"
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output = [ "MyNewPackage DATAFILE='testAug21.root' OPT='RECREATE'" ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/FTKCachedBankGen_jobOptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/FTKCachedBankGen_jobOptions.py
new file mode 100644
index 00000000000..5db2ea59b9c
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/FTKCachedBankGen_jobOptions.py
@@ -0,0 +1,63 @@
+#--------------------------------------------------------------
+# Full job is a list of algorithms
+#--------------------------------------------------------------
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# Enable monitoring
+#--------------------------------------------------------------
+from PerfMonComps.PerfMonFlags import jobproperties
+jobproperties.PerfMonFlags.doSemiDetailedMonitoring = True
+
+from AthenaCommon.AppMgr import ToolSvc
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#--------------------------------------------------------------
+# initialize algo(s)
+#--------------------------------------------------------------
+CachedBankGen = FTKCachedBankGenAlgo("CachedBankGen")
+
+#--------------------------------------------------------------
+# 
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import theApp
+# Number of events to be processed
+theApp.EvtMax = 1
+
+from AthenaCommon.AppMgr import ServiceMgr
+
+from GaudiSvc.GaudiSvcConf import THistSvc
+ServiceMgr += THistSvc()
+
+ServiceMgr.THistSvc.Output += ["outputHisto DATAFILE='outputHisto.root' OPT='RECREATE'"]
+
+#--------------------------------------------------------------
+# Set output level threshold (DEBUG, INFO, WARNING, ERROR, FATAL)
+#--------------------------------------------------------------
+CachedBankGen.OutputLevel = DEBUG
+
+
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+
+ConfigDir = "/nfs/dust/atlas/user/britzger/19.3.0/Trigger/TrigFTK/TrigFTKSim/config/"
+CachedBankGen.ssmapAM_path = ConfigDir + "ss_file/raw_30x32x72Ibl.ss"
+
+CachedBankGen.curreg = 24  ## is indeed specified by the inputbank_path
+
+CachedBankGen.maxpatt = 4096*4096
+
+CachedBankGen.infile = "/afs/desy.de/user/b/britzger/dust/19.3.0/test.root"
+CachedBankGen.ccacheOut = "test.ccache.root"
+CachedBankGen.pcacheOut = "test.pcache.root"
+CachedBankGen.nSub = 1
+CachedBankGen.iSub = 0
+
+alg += CachedBankGen
+#==============================================================
+#
+# End of job options file
+#
+###############################################################
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_FTK.py b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_FTK.py
new file mode 100644
index 00000000000..2799191e5f5
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_FTK.py
@@ -0,0 +1,17 @@
+evgenConfig.description = "Single muons with inv pt from 1 to 1000 GeV, |eta|<3 and special vertez"
+evgenConfig.keywords = ["singleparticle", "mu"]
+
+## Common setup for ParticleGenerator
+from ParticleGenerator.ParticleGeneratorConf import ParticleGenerator
+topAlg += ParticleGenerator()
+evgenConfig.generators = ["ParticleGenerator"]
+
+
+topAlg.ParticleGenerator.orders = [
+"PDGcode: sequence -13 13" ,
+  "invpt: flat 1.0e-6 1.3e-3",
+  "eta: flat -3.0 3.0",
+  "phi: flat -3.14159 3.14159",
+  "targetip: flat -2.2 2.2",
+  "vertZ: flat -120.0 120.0"
+  ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_x10_FTK.py b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_x10_FTK.py
new file mode 100644
index 00000000000..f758b682d7b
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_mu_Pt1to1000_Eta30_x10_FTK.py
@@ -0,0 +1,21 @@
+evgenConfig.description = "Single muons with inv pt from 1 to 1000 GeV, |eta|<3 and special vertez"
+evgenConfig.keywords = ["singleparticle", "mu"]
+
+## Common setup for ParticleGenerator
+from ParticleGenerator.ParticleGeneratorConf import ParticleGenerator
+topAlg += ParticleGenerator()
+evgenConfig.generators = ["ParticleGenerator"]
+
+#multi-particle event
+nparticles = 10
+
+topAlg.ParticleGenerator.orders = []
+for ipart in xrange(nparticles) :
+    topAlg.ParticleGenerator.orders += [
+        "PDGcode[%d]: sequence -13 13" % ipart,
+        "invpt[%d]: flat 1.0e-6 1.3e-3" % ipart,
+        "eta[%d]: flat -3.0 3.0" % ipart,
+        "phi[%d]: flat -3.14159 3.14159" % ipart,
+        "targetip[%d]: flat -2.2 2.2" % ipart,
+        "vertZ[%d]: flat -120.0 120.0" % ipart
+        ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_FTK.py b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_FTK.py
new file mode 100644
index 00000000000..722a9441fb5
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_FTK.py
@@ -0,0 +1,16 @@
+evgenConfig.description = "Single pions with inv pt from 1 to 1000 GeV, |eta|<3 and special vertez"
+evgenConfig.keywords = ["singleparticle", "pi"]
+
+i## Common setup for ParticleGenerator
+from ParticleGenerator.ParticleGeneratorConf import ParticleGenerator
+topAlg += ParticleGenerator()
+evgenConfig.generators = ["ParticleGenerator"]
+
+topAlg.ParticleGenerator.orders = [
+ "PDGcode: sequence -211 211",
+ "invpt: flat 1.0e-6 1.3e-3",
+ "eta: flat -3.0 3.0",
+ "phi: flat -3.14159 3.14159",
+ "targetip: flat -2.2 2.2",
+ "vertZ: flat -120.0 120.0"
+ ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_x10_FTK.py b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_x10_FTK.py
new file mode 100644
index 00000000000..722a9441fb5
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/MC12.184002.ParticleGenerator_pi_Pt1to1000_Eta30_x10_FTK.py
@@ -0,0 +1,16 @@
+evgenConfig.description = "Single pions with inv pt from 1 to 1000 GeV, |eta|<3 and special vertez"
+evgenConfig.keywords = ["singleparticle", "pi"]
+
+i## Common setup for ParticleGenerator
+from ParticleGenerator.ParticleGeneratorConf import ParticleGenerator
+topAlg += ParticleGenerator()
+evgenConfig.generators = ["ParticleGenerator"]
+
+topAlg.ParticleGenerator.orders = [
+ "PDGcode: sequence -211 211",
+ "invpt: flat 1.0e-6 1.3e-3",
+ "eta: flat -3.0 3.0",
+ "phi: flat -3.14159 3.14159",
+ "targetip: flat -2.2 2.2",
+ "vertZ: flat -120.0 120.0"
+ ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/PattMergeRoot_jobOptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/PattMergeRoot_jobOptions.py
new file mode 100644
index 00000000000..dc1b826ce75
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/PattMergeRoot_jobOptions.py
@@ -0,0 +1,85 @@
+# Full job is a list of algorithms
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+# Enable monitoring
+from PerfMonComps.PerfMonFlags import jobproperties
+jobproperties.PerfMonFlags.doSemiDetailedMonitoring = True
+
+from AthenaCommon.AppMgr import ToolSvc
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+PattMergeRoot = PattMergeRootAlgo("PattMergeRoot")
+
+from AthenaCommon.AppMgr import theApp
+# Number of events to be processed
+theApp.EvtMax = 1
+
+from AthenaCommon.AppMgr import ServiceMgr
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#
+#ServiceMgr.THistSvc.Output += ["outputHisto DATAFILE='outputHisto.root' OPT='RECREATE'"]
+
+#--------------------------------------------------------------
+# Set output level threshold (DEBUG, INFO, WARNING, ERROR, FATAL)
+#--------------------------------------------------------------
+
+# Output level for PattMergeRoot only
+PattMergeRoot.OutputLevel = INFO
+
+
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+
+# Specify in which step of the algorithm the merging is performed
+#   Possible options:
+#     - initialize
+#     - execute
+#     - finalize
+PattMergeRoot.WhereToRunMerging = "initialize"
+
+# cut on coverage, applied to MERGED_ROOTFILE and OUT_FILE
+PattMergeRoot.MinCoverage = 2
+
+# output file (root or compressed text)
+#  Specify output filename (must end with .root)
+#  If additional the patterns shall be written in ascii/text 
+#  format specify 'TextOutFile' (.bz2 is added automatically). 
+#  If TextOutFile is empty do not write patterns in text format.
+PattMergeRoot.RootOutFile  = "MergedPatterns.root"
+PattMergeRoot.TextOutFile  = ""   # e.g. "MergedPatterns"
+
+
+# temporary file, with all patterns, prior to merging
+#  if no file is given, construct name by appending .textImport.root
+#  to OUT_FILE
+PattMergeRoot.TextImportRootFile = ""
+
+# Do split output into NSub sub-regions
+PattMergeRoot.NSub = 0
+
+# Delete files after merging
+# (Deletes all specified .root-files)
+# If problem occured while importing text file, keep this text file
+PattMergeRoot.DeleteFilesAfterMerging = False
+
+# input files: various input formats can be mixed
+PattMergeRoot.InputFiles = [ 
+ "patterns_sub0.patt.bz2",
+ "patterns_sub1.patt.bz2",
+ "patterns_sub2.patt.bz2",
+ "patterns_sub3.root",
+ "patterns_sub4.root"
+]
+
+alg += PattMergeRoot
+
+
+#==============================================================
+#
+# End of job options file
+#
+###############################################################
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/bsub_find_extrapolation_relations.py b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/bsub_find_extrapolation_relations.py
new file mode 100755
index 00000000000..05b4b68168a
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/bsub_find_extrapolation_relations.py
@@ -0,0 +1,22 @@
+#!/bin/usr/python
+
+import os
+import sys
+
+for subregion in xrange(1):
+    for region in xrange(64):
+        line = ' > run_'+str(subregion)+'_'+str(region)+'.sh'
+        cmd = 'cd '+os.getcwd()
+        os.system('echo '+cmd+line)
+        #cmd = 'python ../bin/find_X11_relations.py sectors_raw_8L_4M_reg%s_sub%s.patt.bz2 4'% (region, subregion)
+        cmd = '"setupATLAS; localSetupROOT;'
+        #cmd += 'python ../bin/find_extrapolation_relations.py sectors_raw_8L_4M_reg%s_sub%s.patt.bz2 4"'% (region, subregion)
+        cmd = 'python ../make_conn/find_extrapolation_relations_v2.py sectors_raw_8L_reg%s.patt.bz2 1'% (region)
+        print cmd
+        #os.system( cmd )
+        line = ' >> run_'+str(subregion)+'_'+str(region)+'.sh'
+        os.system('echo '+cmd+line)
+        os.system('chmod 755 '+'run_'+str(subregion)+'_'+str(region)+'.sh')
+        os.system('sleep 2')
+        print subregion,region
+        os.system('bsub -q 1nh '+'run_'+str(subregion)+'_'+str(region)+'.sh')
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations.py b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations.py
new file mode 100755
index 00000000000..928ef6c2342
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations.py
@@ -0,0 +1,485 @@
+#!/usr/bin/python
+
+import ftkutils
+import sys
+import os.path
+
+#### OPTION ####
+###############
+XL='8'
+XL2nd = '12'
+Config8La = [0,1,2,3,4,   5,None,6,None,7,None]
+Config8Lb = [0,1,2,3,None,4,5,   6,None,7,None]
+Config8Lc = [0,1,2,3,None,4,None,5,6,   7,None]
+Config8Ld = [0,1,2,3,None,4,None,5,None,6,7   ]
+#Configge = [0,1,2,3,4   ,5,6   ,7,8   ,9,10  ]
+
+Config1stStage = Config8Lc  # CHOOSING 8Lc configuration
+
+# standard conversion map from 7L to 11L
+if XL2nd=='11':
+    if XL=='7':
+        convXLtoXL2nd = [0,1,2,3,None,4,None,5,None,6,None]
+    elif XL=='8':
+        convXLtoXL2nd = Config1stStage
+elif XL2nd=='12':
+    if XL=='7':
+        convXLtoXL2nd = [None,0,1,2,3,None,4,None,5,None,6,None]
+    elif XL=='8':
+        convXLtoXL2nd = [None] + Config1stStage
+###############
+
+
+
+
+
+###########################################################################
+# Print statement handler
+#--------------------------------------------------------------------------
+#
+def Print(arg):
+    print sys.argv[0],':   ', arg
+#--------------------------------------------------------------------------
+
+
+
+###########################################################################
+# Help
+#--------------------------------------------------------------------------
+def help():
+    print 'example of running the code'
+    print 'python %s sectors_raw_7L_16M_reg0_sub4.patt.bz2 16'%sys.argv[0]
+
+
+if len(sys.argv)<2:
+    help()
+    sys.exit()
+
+
+    
+
+###########################################################################
+# Passed argument handling
+#--------------------------------------------------------------------------
+
+
+# Standard arguments
+filename_XL_sector = sys.argv[1]          # filename of 7L sector e.g. sectors_raw_7L_16M_reg7_sub14.patt.bz2
+nsubregions        = int(sys.argv[2])     # number of subregions to be dealt with, 0-16
+
+# Output to a File? or STDOUT?
+try:
+    sys.argv[3]
+    output = open(sys.argv[3],'w')
+except:
+    output = sys.stdout
+#--------------------------------------------------------------------------
+
+
+
+
+#-----------------------------------
+# Probably Nothing
+#g = open('test.out','w')
+#count = 0
+
+#h = open('test_nonematch.out','w')
+#h1 = open('test_all.out','w')
+#-----------------------------------
+
+
+
+###########################################################################
+# Load PyROOT
+#--------------------------------------------------------------------------
+
+try:
+    import ROOT
+    hasROOT = True
+except ImportError :
+    Print('ROOT library not found, histogram book keeping disabled')
+    hasROOT = False
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Load 7L sector bank
+#--------------------------------------------------------------------------
+Print('Load sector in ' + filename_XL_sector)
+
+LX_sector_bank = ftkutils.PatternBank(filename_XL_sector)
+LX_sector_bank.LoadPatterns()
+
+# create a KD-Tree representation for this bank
+LX_kdtree_bank = LX_sector_bank.BuildKDTree()
+#--------------------------------------------------------------------------
+
+
+
+###########################################################################
+# Parse region ID and subregion ID from the 7L sector bank name
+#   e.g. from 1st passed arg: sectors_raw_7L_16M_reg'7'_sub'14'.patt.bz2
+#--------------------------------------------------------------------------
+
+regid = None
+subid = None
+
+filename_XL_sector_items = filename_XL_sector.split('_')
+
+for item in filename_XL_sector_items :
+
+    if item[0:3] == 'reg' :
+        regid = int(item.split('.')[0][3:])
+
+    elif item[0:3] == 'sub' :
+        subid = int(item.split('.')[0][3:])
+
+# Print
+Print('Region ' + str(regid))
+Print('Sub-region ' + str(subid))
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Set the output file
+#--------------------------------------------------------------------------
+
+# starting from the 7L sector name
+tmp = os.path.basename(filename_XL_sector)    #sectors_raw_7L_16M_reg'7'_sub'14'.patt.bz2
+
+# strip additional extension
+tmp = tmp.rstrip('.bz2')                      #sectors_raw_7L_16M_reg'7'_sub'14'.patt
+
+filename_conn = tmp.replace('.patt','.conn')  #sectors_raw_7L_16M_reg'7'_sub'14'.conn
+filename_otoc = tmp.replace('.patt','.otoc')  #sectors_raw_7L_16M_reg'7'_sub'14'.otoc
+
+tmp = tmp.replace('sectors','corrgen')
+tmp = tmp.replace('.patt','.gcon')
+
+filename_gcon = tmp.replace(XL+'L',XL+XL2nd+'L')      #corrgen_raw_711L_16M_reg'7'_sub'14'.gcon
+
+# Open up each output file
+file_conn = open(filename_conn,'w')
+file_otoc = open(filename_otoc,'w')
+file_gcon = open(filename_gcon,'w')
+
+# print
+Print('Output in: ' + filename_conn)
+Print('Output in: ' + filename_otoc)
+Print('Output in: ' + filename_gcon)
+#--------------------------------------------------------------------------
+
+###########################################################################
+# Set the output file
+#--------------------------------------------------------------------------
+if hasROOT :
+    if subid != None:
+        rootfile = ROOT.TFile.Open("relation_histo_reg%d_sub%d.root" % (regid,subid),"recreate")
+    else:
+        rootfile = ROOT.TFile.Open("relation_histo_reg%d.root" % (regid),"recreate")
+    histo_nrelations = ROOT.TH1F("histo_nrelations","Relations",
+                                8,-.5,7.5);
+    histo_nrelations.SetXTitle("# "+XL+"L #rightarrow "+XL2nd+"L relations")
+    histo_nrelations.SetYTitle("# "+XL+"L sectors")
+    histo_nrelsub = []
+    for i in xrange(nsubregions) :
+        histo_nrelsub.append(ROOT.TH1F("histo_nrelsub%d" % i, "Relations sub %d" % i, 8,-.5,7.5))
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Load sector and constants for 11 layer
+#--------------------------------------------------------------------------
+
+XL2nd_sector_banks = []
+XL2nd_kdtree_banks = []
+
+# Loop over all subregions (between 0-16 depending on the sys.argv[2])
+# then load all the 11L sector banks for finding relations
+for i_subreg in xrange(nsubregions) :
+
+    # Following creates sectors_raw_11L_16M_reg'7'_sub'i_subreg'.patt.bz2
+    tmp = filename_XL_sector.replace(XL+"L",XL2nd+"L")
+    if subid != None:
+        tmp = tmp.replace("sub%d" % subid,"sub%d" % i_subreg)
+    filename_XL2nd_sector = tmp
+
+    Print("Load sector in "+ filename_XL2nd_sector)
+
+    tmpbank = ftkutils.PatternBank(filename_XL2nd_sector)
+    tmpbank.LoadPatterns()
+
+    # append to the global sector bank list
+    XL2nd_sector_banks.append( tmpbank )
+
+    # create a KD-Tree representation for this bank
+    XL2nd_kdtree_banks.append( tmpbank.BuildKDTree() )
+
+# load constants from the constant files (11-layer constant)
+
+XL2nd_constant_banks = []
+
+for i in xrange(nsubregions) : 
+
+    # Following creates /path/to/my/bank/gcon/corrgen_raw_11L_16M_reg'7'_sub'i_subreg'.gcon.bz2
+    tmp = os.path.abspath(filename_XL_sector)
+    tmpbase = os.path.basename(tmp)
+    tmpdirpath = os.path.dirname(tmp)
+    tmpbase = tmpbase.replace(XL+"L",XL2nd+"L")
+    if subid != None:
+        tmpbase = tmpbase.replace("sub%d" % subid,"sub%d" % i)
+    tmpbase = tmpbase.replace(".patt",".gcon")
+    tmpbase = tmpbase.replace("sectors","corrgen")
+    tmpdirpath = tmpdirpath.replace("/patt","/gcon")
+    filename_XL2nd_sector_gcon = os.path.join(tmpdirpath, tmpbase)
+
+    Print("Load constant in "+filename_XL2nd_sector_gcon)
+
+    tmpbank = ftkutils.ConstantBank(filename_XL2nd_sector_gcon)
+    tmpbank.LoadConstants()
+
+    for i, constant in enumerate(tmpbank.constants):
+        if constant.pid != str(i):
+            print 'pid does not match the index', constant.pid, 
+
+    # Append to global constant bank list
+    XL2nd_constant_banks.append( tmpbank )
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Write header for gcon files
+#--------------------------------------------------------------------------
+file_gcon.write("! ***           RECONSTRUCTION GEOMETRY CONSTANTS               ***\n")
+file_gcon.write("\n")
+file_gcon.write("Version 2       ! File format version number\n")
+file_gcon.write("\n")
+file_gcon.write("! ***           PHI is now in GLOBAL coordinate system          ***\n")
+file_gcon.write(" NPLANES\n")
+file_gcon.write(" %s\n"%XL2nd)
+file_gcon.write(" NSECTORS\n")
+file_gcon.write(str(LX_sector_bank.npatterns) +"\n")
+file_gcon.write(" NDIM\n")
+file_gcon.write(" 2\n")
+#--------------------------------------------------------------------------
+
+
+
+
+###########################################################################
+# Heart of this file
+#--------------------------------------------------------------------------
+
+# deprecated__________________________
+#inversion_list = [4,6] # list of 7L layer that in 11L ECP map are stereo
+# deprecated__________________________
+
+# create the elements used to search the similar
+tocheck = ftkutils.Pattern(int(XL2nd))
+
+
+###########################################################################
+# Diagonosis plots
+#--------------------------------------------------------------------------
+
+if hasROOT:
+    h_n_conn = ROOT.TH1F('h_n_conn','h_n_conn',12,-.5,11.5);
+    h_coverage = ROOT.TH1F('h_coverage','h_coverage',11,0.5,11.5);
+
+
+# global counter of sector ID for new constant set
+counter = 0;
+gcon_counter = 0;
+
+# loop of the reference 7L bank
+for LX_pattern in LX_sector_bank.patterns :
+
+    # Print the current LX_pattern information (SSID, coverage)
+    # Looks like. "Check: ID 0 SSs  17007 30007 40007 25007 31007 37007 43007 in 0 cov 9661"
+    print ''
+    print ''
+    print 'Initial LX_pattern... : ',
+    LX_pattern.PrintToFile(output)
+
+
+    # ----------------------------------------------------------------
+    # expand the 7L in an 11L pattern
+    # Following for loop creates something like
+    # [SSID0,SSID1,SSID2,SSID3,-1,SSID4,-1,SSID5,-1,SSID6,-1]
+    #
+    for i in xrange(int(XL2nd)) :
+        if convXLtoXL2nd[i] == None :
+            tocheck.ssid[i] = -1
+        else :
+            tocheck.ssid[i] = LX_pattern.ssid[convXLtoXL2nd[i]]
+
+
+    if XL2nd=='11':
+        if XL=='7':
+            stereoID = [4,8,10]
+        elif XL=='8':
+            stereoID = [4,6,10]
+    else:
+        if XL=='7':
+            stereoID = [0,5,9,11]
+        elif XL=='8':
+            stereoID = [0,5,7,11]
+    stereoLayer_indices = [0,1,3]
+
+    # Printing
+    print "   |"
+    print "   processed into L%s_pattern"%XL2nd
+    print "   |"
+    print " Final L%s_pattern... "%XL2nd,
+    tocheck.PrintToFile(output)
+    print "Stereo layers:", stereoID
+
+    
+    # ----------------------------------------------------------------
+    # loop over all the subregions 11L banks
+    #
+    matched_XL2nd_sector_infos = []   # This will hold matched 11L sectors
+    for i_subreg in xrange(nsubregions) :
+
+        # return the list of similar patterns
+        matched_XL2nd_sector_infos_sub = XL2nd_kdtree_banks[i_subreg].FindNode(tocheck)
+
+
+        if hasROOT :
+            histo_nrelsub[i_subreg].Fill(len(matched_XL2nd_sector_infos_sub))
+            
+        # add the similar pattern in this sector in the global list
+        for node in matched_XL2nd_sector_infos_sub :
+            isin = False
+            for iold in xrange(len(matched_XL2nd_sector_infos)) :
+                if matched_XL2nd_sector_infos[iold][1].pattern.coverage < node.pattern.coverage :
+                    matched_XL2nd_sector_infos[iold:iold] = [[i_subreg,node]]
+                    isin = True
+                    break
+            if not isin :
+                matched_XL2nd_sector_infos.append([i_subreg,node])
+
+    if hasROOT :
+        histo_nrelations.Fill(len(matched_XL2nd_sector_infos))
+ 
+    # print the connecton for this 7L pattern
+    #file_conn.write("%d %d" % (LX_pattern.pid, len(matched_XL2nd_sector_infos)))   #for allowing multiple correspondence to be printed out in .conn file  ## deprecated
+
+
+    # ----------------------------------------------------------------
+    # Here we force so we only write only 1 matched pattern, so num_matched_XL2nd is always either 0 or 1
+    #
+    #num_matched_XL2nd = 0
+    #if len(matched_XL2nd_sector_infos) >=1:
+    #   num_matched_XL2nd = 1
+    num_matched_XL2nd = len(matched_XL2nd_sector_infos)
+
+    # Each line will start with LX_pattern_pid, and 0 or 1 always, 
+    file_conn.write("%d %d" % (LX_pattern.pid, num_matched_XL2nd))
+   
+
+
+    # ----------------------------------------------------------------
+    # Here we process each LX_pattern_pid and finish up writing the content
+    #
+    file_otoc.write("%d" % (LX_pattern.pid))
+
+    if hasROOT:
+        h_n_conn.Fill(len(matched_XL2nd_sector_infos))
+        for i in xrange(len(matched_XL2nd_sector_infos)):
+            print matched_XL2nd_sector_infos[i][1].pattern.coverage
+            h_coverage.Fill(i+1,matched_XL2nd_sector_infos[i][1].pattern.coverage)
+            #if i==0:
+            #    h_coverage.Fill(0,matched_XL2nd_sector_infos[i][1].pattern.coverage)
+            #else:
+            #    h_coverage.Fill(1,matched_XL2nd_sector_infos[i][1].pattern.coverage)
+
+    if len(matched_XL2nd_sector_infos)!=0:
+
+        for iconn in xrange(len(matched_XL2nd_sector_infos)):
+            # L11_sector with largest coverage is the first element of matched_XL2nd_sector_infos
+            XL2nd_info_lg_cov     = matched_XL2nd_sector_infos[iconn]
+            sub_id_lg_cov       = XL2nd_info_lg_cov[0]
+            matched_XL2nd_lg_cov  = XL2nd_info_lg_cov[1].pattern
+
+            # L11 info is written here.
+            file_otoc.write(" %d" % sub_id_lg_cov)
+            file_otoc.write(" %d" % matched_XL2nd_lg_cov.pid)
+
+            for i in matched_XL2nd_lg_cov.ssid:
+                    file_otoc.write(" "+str(i))
+
+            file_otoc.write(" %d" % XL2nd_info_lg_cov[1].pattern.coverage)
+            file_otoc.write("\n")
+
+
+            tmpcon = XL2nd_constant_banks[sub_id_lg_cov].FindConstant(matched_XL2nd_lg_cov.pid)
+            # DEBUG ----->
+            #if str(XL2nd_constant_banks[1].constants[5056].pid)!='5056':
+            #    print 'Montor this :', LX_pattern.pid, XL2nd_constant_banks[1].constants[5056].pid
+            #    sys.exit()
+            # DEBUG -----|
+            try:
+                #tmpcon.PrintToFile(file_gcon, LX_pattern.pid)
+                tmpcon.PrintToFile(file_gcon, gcon_counter)
+                gcon_counter+=1
+            except:
+                print matched_XL2nd_lg_cov.pid, sub_id_lg_cov
+                sys.exit()
+
+
+    else:
+        file_otoc.write("\n")
+        #ftkutils.Constant(int(XL2nd),LX_pattern.pid).PrintToFile(file_gcon)
+
+    for matched_XL2nd_sector_info in matched_XL2nd_sector_infos :
+        print "Find: ",
+        matched_XL2nd_sector_info[1].pattern.PrintToFile(output)
+        #file_conn.write(" %d %d" % (matched_XL2nd_sector_info[0],matched_XL2nd_sector_info[1].pattern.pid))
+        file_conn.write(" %d %d" % (matched_XL2nd_sector_info[0],counter))
+        counter+=1
+        for ip in xrange(len(stereoID)) :
+            file_conn.write(" "+str(matched_XL2nd_sector_info[1].pattern.ssid[stereoID[ip]]))
+        #break # force only one connection
+    file_conn.write("\n")
+    if gcon_counter != counter:
+        sys.exit("counters don't match")
+    #break #debug
+
+# Print final message
+Print('')
+Print('')
+Print('')
+Print('This find relations session has sucessfully ended')
+
+if hasROOT :
+    h_n_conn.Write()
+    h_coverage.Write()
+    rootfile.Write()
+    rootfile.Close()
+file_conn.close()
+
+# Fix the total number of sectors
+print "fixing"
+file_gcon_copy = open(filename_gcon,'r')
+lines = file_gcon_copy.readlines()
+file_gcon = open(filename_gcon,'w')
+for i, line in enumerate(lines):
+    if i==8:
+        file_gcon.write("%d\n"%(gcon_counter-1));
+    else:
+        file_gcon.write(line);
+
+#eof
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations_v2.py b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations_v2.py
new file mode 100755
index 00000000000..d020c3ee96a
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/find_extrapolation_relations_v2.py
@@ -0,0 +1,429 @@
+#!/usr/bin/python
+
+import ftkutils
+import sys
+import os.path
+
+#### OPTION ####
+###############
+XL='8'
+XL2nd = '12'
+Config1stStage = [0,1,2,3,None,4,None,5,6,   7,None]
+
+# standard conversion map from 1st stage to 2nd stage
+convXLtoXL2nd = [None] + Config1stStage
+###############
+
+
+
+
+
+###########################################################################
+# Print statement handler
+#--------------------------------------------------------------------------
+#
+def Print(arg):
+    print sys.argv[0],':   ', arg
+#--------------------------------------------------------------------------
+
+
+
+###########################################################################
+# Help
+#--------------------------------------------------------------------------
+def help():
+    print 'example of running the code'
+    print 'python %s sectors_raw_8L_16M_reg0_sub4.patt.bz2 16'%sys.argv[0]
+
+
+if len(sys.argv)<2:
+    help()
+    sys.exit()
+
+
+    
+
+###########################################################################
+# Passed argument handling
+#--------------------------------------------------------------------------
+
+
+# Standard arguments
+filename_XL_sector = sys.argv[1]          # filename of 8L sector e.g. sectors_raw_8L_16M_reg7_sub14.patt.bz2
+nsubregions        = int(sys.argv[2])     # number of subregions to be dealt with, 0-16
+
+# Output to a File? or STDOUT?
+try:
+    sys.argv[3]
+    output = open(sys.argv[3],'w')
+except:
+    output = sys.stdout
+#--------------------------------------------------------------------------
+
+
+
+###########################################################################
+# Load PyROOT
+#--------------------------------------------------------------------------
+
+try:
+    import ROOT
+    hasROOT = True
+except ImportError :
+    Print('ROOT library not found, histogram book keeping disabled')
+    hasROOT = False
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Load 8L sector bank
+#--------------------------------------------------------------------------
+Print('Load sector in ' + filename_XL_sector)
+
+LX_sector_bank = ftkutils.PatternBank(filename_XL_sector)
+LX_sector_bank.LoadPatterns()
+
+# create a KD-Tree representation for this bank
+LX_kdtree_bank = LX_sector_bank.BuildKDTree()
+#--------------------------------------------------------------------------
+
+
+
+###########################################################################
+# Parse region ID and subregion ID from the 8L sector bank name
+#   e.g. from 1st passed arg: sectors_raw_8L_16M_reg'7'_sub'14'.patt.bz2
+#--------------------------------------------------------------------------
+
+regid = None
+subid = None
+
+filename_XL_sector_items = filename_XL_sector.split('_')
+
+for item in filename_XL_sector_items :
+
+    if item[0:3] == 'reg' :
+        regid = int(item.split('.')[0][3:])
+
+    elif item[0:3] == 'sub' :
+        subid = int(item.split('.')[0][3:])
+
+# Print
+Print('Region ' + str(regid))
+Print('Sub-region ' + str(subid))
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Set the output file
+#--------------------------------------------------------------------------
+
+# starting from the 8L sector name
+tmp = os.path.basename(filename_XL_sector)    #sectors_raw_8L_16M_reg'7'_sub'14'.patt.bz2
+
+# strip additional extension
+tmp = tmp.rstrip('.bz2')                      #sectors_raw_8L_16M_reg'7'_sub'14'.patt
+
+filename_conn = tmp.replace('.patt','.conn')  #sectors_raw_8L_16M_reg'7'_sub'14'.conn
+filename_otoc = tmp.replace('.patt','.otoc')  #sectors_raw_8L_16M_reg'7'_sub'14'.otoc
+
+tmp = tmp.replace('sectors','corrgen')
+tmp = tmp.replace('.patt','.gcon')
+
+filename_gcon = tmp.replace(XL+'L',XL+XL2nd+'L')      #corrgen_raw_712L_16M_reg'7'_sub'14'.gcon
+
+# Open up each output file
+file_conn = open(filename_conn,'w')
+file_otoc = open(filename_otoc,'w')
+file_gcon = open(filename_gcon,'w')
+
+# print
+Print('Output in: ' + filename_conn)
+Print('Output in: ' + filename_otoc)
+Print('Output in: ' + filename_gcon)
+#--------------------------------------------------------------------------
+
+
+
+
+###########################################################################
+# Set the output file
+#--------------------------------------------------------------------------
+if hasROOT :
+    if subid != None:
+        rootfile = ROOT.TFile.Open("relation_histo_reg%d_sub%d.root" % (regid,subid),"recreate")
+    else:
+        rootfile = ROOT.TFile.Open("relation_histo_reg%d.root" % (regid),"recreate")
+    histo_nrelations = ROOT.TH1F("histo_nrelations","Relations",
+                                8,-.5,7.5);
+    histo_nrelations.SetXTitle("# "+XL+"L #rightarrow "+XL2nd+"L relations")
+    histo_nrelations.SetYTitle("# "+XL+"L sectors")
+    histo_nrelsub = []
+    for i in xrange(nsubregions) :
+        histo_nrelsub.append(ROOT.TH1F("histo_nrelsub%d" % i, "Relations sub %d" % i, 8,-.5,7.5))
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Load sector and constants for 12 layer
+#--------------------------------------------------------------------------
+
+XL2nd_sector_banks = []
+XL2nd_kdtree_banks = []
+
+# Loop over all subregions (between 0-16 depending on the sys.argv[2])
+# then load all the 12L sector banks for finding relations
+for i_subreg in xrange(nsubregions) :
+
+    # Following creates sectors_raw_12L_16M_reg'7'_sub'i_subreg'.patt.bz2
+    tmp = filename_XL_sector.replace(XL+"L",XL2nd+"L")
+    if subid != None:
+        tmp = tmp.replace("sub%d" % subid,"sub%d" % i_subreg)
+    filename_XL2nd_sector = tmp
+
+    Print("Load sector in "+ filename_XL2nd_sector)
+
+    tmpbank = ftkutils.PatternBank(filename_XL2nd_sector)
+    tmpbank.LoadPatterns()
+
+    # append to the global sector bank list
+    XL2nd_sector_banks.append( tmpbank )
+
+    # create a KD-Tree representation for this bank
+    XL2nd_kdtree_banks.append( tmpbank.BuildKDTree() )
+
+# load constants from the constant files (12-layer constant)
+
+XL2nd_constant_banks = []
+
+for i in xrange(nsubregions) : 
+
+    # Following creates /path/to/my/bank/gcon/corrgen_raw_12L_16M_reg'7'_sub'i_subreg'.gcon.bz2
+    tmp = os.path.abspath(filename_XL_sector)
+    tmpbase = os.path.basename(tmp)
+    tmpdirpath = os.path.dirname(tmp)
+    tmpbase = tmpbase.replace(XL+"L",XL2nd+"L")
+    if subid != None:
+        tmpbase = tmpbase.replace("sub%d" % subid,"sub%d" % i)
+    tmpbase = tmpbase.replace(".patt",".gcon")
+    tmpbase = tmpbase.replace("sectors","corrgen")
+    tmpdirpath = tmpdirpath.replace("/patt","/gcon")
+    filename_XL2nd_sector_gcon = os.path.join(tmpdirpath, tmpbase)
+
+    Print("Load constant in "+filename_XL2nd_sector_gcon)
+
+    tmpbank = ftkutils.ConstantBank(filename_XL2nd_sector_gcon)
+    tmpbank.LoadConstants()
+
+    for i, constant in enumerate(tmpbank.constants):
+        if constant.pid != str(i):
+            print 'pid does not match the index', constant.pid, 
+
+    # Append to global constant bank list
+    XL2nd_constant_banks.append( tmpbank )
+#--------------------------------------------------------------------------
+
+
+
+
+
+###########################################################################
+# Write header for gcon files
+#--------------------------------------------------------------------------
+file_gcon.write("! ***           RECONSTRUCTION GEOMETRY CONSTANTS               ***\n")
+file_gcon.write("\n")
+file_gcon.write("Version 2       ! File format version number\n")
+file_gcon.write("\n")
+file_gcon.write("! ***           PHI is now in GLOBAL coordinate system          ***\n")
+file_gcon.write(" NPLANES\n")
+file_gcon.write(" %s\n"%XL2nd)
+file_gcon.write(" NSECTORS\n")
+file_gcon.write(str(LX_sector_bank.npatterns) +"\n")
+file_gcon.write(" NDIM\n")
+file_gcon.write(" 2\n")
+#--------------------------------------------------------------------------
+
+
+
+
+###########################################################################
+# Heart of this file
+#--------------------------------------------------------------------------
+
+# deprecated__________________________
+#inversion_list = [4,6] # list of 8L layer that in 11L ECP map are stereo
+# deprecated__________________________
+
+# create the elements used to search the similar
+tocheck = ftkutils.Pattern(int(XL2nd))
+
+
+###########################################################################
+# Diagonosis plots
+#--------------------------------------------------------------------------
+
+if hasROOT:
+    h_n_conn = ROOT.TH1F('h_n_conn','h_n_conn',12,-.5,11.5);
+    h_coverage = ROOT.TH1F('h_coverage','h_coverage',11,0.5,11.5);
+
+
+# global counter of sector ID for new constant set
+counter = 0;
+gcon_counter = 0;
+
+# loop of the reference 8L bank
+for LX_pattern in LX_sector_bank.patterns :
+
+    # Print the current LX_pattern information (SSID, coverage)
+    # Looks like. "Check: ID 0 SSs  17007 30007 40007 25007 31007 37007 43007 in 0 cov 9661"
+    print ''
+    print ''
+    print 'Initial LX_pattern... : ',
+    LX_pattern.PrintToFile(output)
+
+
+    # ----------------------------------------------------------------
+    # expand the 8L in an 12L pattern
+    # Following for loop creates something like
+    # [SSID0,SSID1,SSID2,SSID3,-1,SSID4,-1,SSID5,-1,SSID6,-1]
+    #
+    for i in xrange(int(XL2nd)) :
+        if convXLtoXL2nd[i] == None :
+            tocheck.ssid[i] = -1
+        else :
+            tocheck.ssid[i] = LX_pattern.ssid[convXLtoXL2nd[i]]
+
+    stereoID = [0,5,7,11]
+    stereoLayer_indices = [0,1,3]
+
+    # Printing
+    print "   |"
+    print "   processed into L%s_pattern"%XL2nd
+    print "   |"
+    print " Final L%s_pattern... "%XL2nd,
+    tocheck.PrintToFile(output)
+    print "Stereo layers:", stereoID
+
+    
+    # ----------------------------------------------------------------
+    # loop over all the subregions 12L banks
+    #
+    matched_XL2nd_sector_infos = []   # This will hold matched 12L sectors
+    for i_subreg in xrange(nsubregions) :
+
+        # return the list of similar patterns
+        matched_XL2nd_sector_infos_sub = XL2nd_kdtree_banks[i_subreg].FindNode(tocheck)
+
+        if hasROOT :
+            histo_nrelsub[i_subreg].Fill(len(matched_XL2nd_sector_infos_sub))
+            
+        # add the similar pattern in this sector in the global list
+        for node in matched_XL2nd_sector_infos_sub :
+            isin = False
+            for iold in xrange(len(matched_XL2nd_sector_infos)) :
+                if matched_XL2nd_sector_infos[iold][1].pattern.coverage < node.pattern.coverage :
+                    matched_XL2nd_sector_infos[iold:iold] = [[i_subreg,node]]
+                    isin = True
+                    break
+            if not isin :
+                matched_XL2nd_sector_infos.append([i_subreg,node])
+
+    if hasROOT :
+        histo_nrelations.Fill(len(matched_XL2nd_sector_infos))
+ 
+    # Start the line for the connection file "SECTORID NCONN"
+    num_matched_XL2nd = len(matched_XL2nd_sector_infos)
+    file_conn.write("%d %d" % (LX_pattern.pid, num_matched_XL2nd))
+   
+
+    # ----------------------------------------------------------------
+    # Here we process each LX_pattern_pid and finish up writing the content
+    #
+    file_otoc.write("%d" % (LX_pattern.pid))
+
+    if hasROOT:
+        h_n_conn.Fill(len(matched_XL2nd_sector_infos))
+        for i in xrange(len(matched_XL2nd_sector_infos)):
+            #print matched_XL2nd_sector_infos[i][1].pattern.coverage
+            h_coverage.Fill(i+1,matched_XL2nd_sector_infos[i][1].pattern.coverage)
+
+    # If we have connections
+    if len(matched_XL2nd_sector_infos)!=0:
+        # loop over connection
+        for iconn in xrange(len(matched_XL2nd_sector_infos)):
+            # L12_sector with largest coverage is the first element of matched_XL2nd_sector_infos
+            XL2nd_info_lg_cov     = matched_XL2nd_sector_infos[iconn]
+            sub_id_lg_cov         = XL2nd_info_lg_cov[0]
+            matched_XL2nd_lg_cov  = XL2nd_info_lg_cov[1].pattern
+
+            # L12 info is written here.
+            file_otoc.write(" %d" % sub_id_lg_cov)
+            file_otoc.write(" %d" % matched_XL2nd_lg_cov.pid)
+
+            for i in matched_XL2nd_lg_cov.ssid:
+                    file_otoc.write(" "+str(i))
+
+            file_otoc.write(" %d" % XL2nd_info_lg_cov[1].pattern.coverage)
+            file_otoc.write("\n")
+
+
+            tmpcon = XL2nd_constant_banks[sub_id_lg_cov].FindConstant(matched_XL2nd_lg_cov.pid)
+            # DEBUG ----->
+            #if str(XL2nd_constant_banks[1].constants[5056].pid)!='5056':
+            #    print 'Montor this :', LX_pattern.pid, XL2nd_constant_banks[1].constants[5056].pid
+            #    sys.exit()
+            # DEBUG -----|
+            try:
+                tmpcon.PrintToFile(file_gcon, gcon_counter)
+                gcon_counter+=1
+            except:
+                print matched_XL2nd_lg_cov.pid, sub_id_lg_cov
+                sys.exit()
+
+    else:
+        file_otoc.write("\n")
+
+    for matched_XL2nd_sector_info in matched_XL2nd_sector_infos :
+        print "Find: ",
+        matched_XL2nd_sector_info[1].pattern.PrintToFile(output)
+        file_conn.write(" %d %d" % (matched_XL2nd_sector_info[0],counter))
+        counter+=1
+        for ip in xrange(len(stereoID)) :
+            file_conn.write(" "+str(matched_XL2nd_sector_info[1].pattern.ssid[stereoID[ip]]))
+    file_conn.write("\n")
+    if gcon_counter != counter:
+        sys.exit("counters don't match")
+
+# Print final message
+Print('')
+Print('')
+Print('')
+Print('This find relations session has sucessfully ended')
+
+if hasROOT :
+    h_n_conn.Write()
+    h_coverage.Write()
+    rootfile.Write()
+    rootfile.Close()
+file_conn.close()
+
+# Fix the total number of sectors
+print "fixing"
+file_gcon_copy = open(filename_gcon,'r')
+lines = file_gcon_copy.readlines()
+file_gcon = open(filename_gcon,'w')
+for i, line in enumerate(lines):
+    if i==8:
+        file_gcon.write("%d\n"%(gcon_counter-1));
+    else:
+        file_gcon.write(line);
+
+#eof
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/ftkutils.py b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/ftkutils.py
new file mode 100644
index 00000000000..d996fa26570
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/ftkutils.py
@@ -0,0 +1,809 @@
+import sys
+import bz2, gzip
+from math import sqrt, atan, atan2, tan, log
+
+if __name__ == "__main__" :
+    print "Why are you using this code interactively?"
+    sys.exit(1)
+
+class FTKPlaneSection :
+    """This class contains the details on each detector plane"""
+    def __init__(self) :
+        return None
+
+class FTKPlaneMap :
+    """This class stores a summary of the plane map"""
+    def __init__(self,fname) :
+        pmapfile = open(fname,"r")
+        # form on the next structur
+        # [Ecp: [Pxl[layer],Sct[Layers], Barrel: ...]
+        self.data = [[{},{}],[{},{}]]
+        
+
+        nPXLBar = 0
+        nPXLEcp = 0
+        nSCTBar = 0
+        nSCTEcp = 0
+        NMaxLayer = 0
+        for i, line in enumerate(pmapfile) :
+            vals = line.split()
+
+            if i<4 : # first 4 lines are an header
+                print line[:-1]
+                if i == 0 :
+                    nPXLBar = int(vals[0])
+                elif i == 1 :
+                    nPXLEcp = int(vals[0])
+                elif i == 2:
+                    nSCTBar = int(vals[0])
+                elif i == 3 :
+                    nSCTEcp = int(vals[0])                
+                continue 
+
+            # for each layer stores the relative logical layer ID
+            if vals[0]=='pixel' : # is a PXL
+                nlayer = int(vals[7])
+                if nlayer>NMaxLayer :
+                    NMaxLayer = nlayer
+                self.data[1][int(vals[1])][int(vals[3])] = int(vals[7]) 
+            elif vals[0]=='SCT' : # is an SCT
+                nlayer = int(vals[9])
+                if nlayer > NMaxLayer :
+                    NMaxLayer = nlayer
+                self.data[0][int(vals[1])][int(vals[3])] = nlayer
+        self.NLogicalLayers = NMaxLayer+1
+        print self.data
+        print "Number of layers:", self.NLogicalLayers
+        return None 
+
+class Pattern :
+    """This class define a pattern or a sector"""
+    def __init__(self,nplanes,pid=-1) :
+        """Create the pattern, passing the number of planes and its ID"""
+        # set number of planes
+        self.nplanes = nplanes
+        # set the Pattern-ID
+        self.pid = pid
+        # set the id of Super-Strips in this pattern, -1 means uninitialized
+        self.ssid = [-1]*nplanes
+        # set the PID of the onwer sector, valid only for patterns
+        self.sector = -1
+        self.coverage = -1
+        return None
+
+    def Clone(self) :
+        """Clone this pattern"""
+        newpatt = Pattern(self.nplanes,self.pid)
+        for i in xrange(self.nplanes) :
+            newpatt.ssid[i] = self.ssid[i]
+        newpatt.sector = self.sector
+        newpatt.coverage = self.coverage
+        return newpatt
+
+    def SetNPlanes(self,nplanes) :
+        """Set the number of plane and sizes the internal structures"""
+        self.nplanes = nplanes
+        self.ssid = [-1]*nplanes
+        return None
+
+    def ReadFromFile(self,fdesc) :
+        """Read the next line of a file as the description of a pattern"""
+        #print "Read from file"
+        line = fdesc.readline()
+        #print "line"
+        return self.ReadFromLine(line)
+        
+    def ReadFromLine(self,line) :
+        vals = line.split()
+        if len(vals)!=self.nplanes+3 :
+            print "*** wrong number of arguments for a", self.nplanes, "pattern:"
+            print ">", line
+        else :
+            # set the values
+            if self.pid!=-1 :
+                if self.pid != int(vals[0]) :
+                    print "*** mismatch reading Pattern", int(vals[0]), "in pattern", self.pid, "->", self.ssid
+            else :
+                self.pid = int(vals[0])
+            for ip in xrange(self.nplanes) :
+                self.ssid[ip] = int(vals[ip+1])
+            self.sector = int(vals[self.nplanes+1])
+            self.coverage = int(vals[self.nplanes+2])
+        return self.pid
+
+    def getXmin(self,plane,isPixel,moduleID,ssmap) :
+        """Return the minimum coordinates for a SS"""
+        if isPixel :
+            phioff = 200
+        else :
+            phioff = 100
+        phimod = moduleID/1000
+        if moduleID%100 < 20 : # is barrel
+            return self.ssid[plane]/phioff*ssmap.ss_data[0][isPixel][0]-(ssmap.ss_data[0][isPixel][1]-ssmap.ss_data[0][isPixel][1]%ssmap.ss_data[0][isPixel][0]+ssmap.ss_data[0][isPixel][0])*phimod
+               
+    def PrintToFile(self,stream) :
+        """Print the Pattern content into a file"""
+        line = "ID "+str(self.pid)
+        line += " SSs "
+        for i in xrange(self.nplanes) :
+            line += " "+str(self.ssid[i])
+        line += " in "+str(self.sector)+" cov "+str(self.coverage)
+        line += "\n"
+        stream.write(line)
+        return None
+
+    def IsEqual(self,other) :
+        """Return True if a given pattern is equal to this. All the elements are compared, the ones with -1 are ignored"""
+        for i in xrange(self.nplanes) :
+            if other.ssid[i] == -1:
+                continue
+
+            if self.ssid[i]!=other.ssid[i] :
+                return False
+
+        if other.sector != -1 and other.sector != self.sector :
+            return False
+
+        if other.coverage != -1 and other.coverage != self.coverage :
+            return  False
+        return True
+
+class PatternKDTree :
+    """This class represents a node, ora tree, using kd-tree convention"""
+    def __init__(self,pattern,depth) :
+        # set the object related to this node
+        self.pattern = pattern
+        # node depth
+        self.depth = depth
+        # select the dimension splitted by this level
+        self.split = self.depth % pattern.nplanes
+        self.left = None
+        self.right = None
+        return None
+
+    def AddNode(self,pattern) :
+        """Add a node into the KD-Tree"""
+        newnode = None
+        # test if is greater
+        if self.pattern.ssid[self.split] > pattern.ssid[self.split] :
+            if self.right == None :
+                # create a new right node
+                self.right = PatternKDTree(pattern,self.depth+1)
+                newnode = self.right
+            else :
+                # continue the search
+                newnode = self.right.AddNode(pattern)
+        else : # place on the left
+            if self.left == None :
+                # create a new left node
+                self.left = PatternKDTree(pattern,self.depth+1)
+                newnode = self.left
+            else :
+                # continue the search
+                newnode = self.left.AddNode(pattern)
+        return newnode
+
+    def FindNode(self,pattern) :
+        """Find the correspondent node, return None if doesn't exist. If pattern fields with -1 are used, to look for multiple matches, only the first is returned."""
+        # ntuple to accumulate the similare
+        res = []
+        # check for this node
+        if self.pattern.IsEqual(pattern) :
+            res.append(self)
+
+        # continue the search if greater or is a not partitioning plane
+        if self.pattern.ssid[self.split] > pattern.ssid[self.split] or pattern.ssid[self.split] == -1:
+            if self.right != None :
+                res += self.right.FindNode(pattern)
+        if self.pattern.ssid[self.split] <= pattern.ssid[self.split] or pattern.ssid[self.split] == -1:
+            if self.left != None :
+                res += self.left.FindNode(pattern)
+        return res
+
+class PatternBank :
+    def __init__(self,path,mode="r",nplanes=-1) :
+        self.mode = mode
+        self.stream = None
+        if path[-3:] == "bz2" :
+            print "INFO: Read bz2 compressed pattern bank",
+            self.stream = bz2.BZ2File(path,mode)
+            print "Done"
+        elif path[-2:] == "gz" : 
+            print "INFO: Read  gzip compressed pattern bank",
+            self.stream = bz2.GzipFile(path,mode)
+            print "Done"
+        else :
+            self.stream = open(path,mode)
+
+        if mode.find("r")>-1 :
+            # read the header of the nank
+            line = self.stream.readline()
+            vals = line.split()
+            # set the global attributes fro the bank
+            self.npatterns = int(vals[0])
+            self.nplanes = int(vals[1])
+            self.patterns = []
+        else :
+            self.npatterns = 0
+            self.nplanes = nplanes
+            self.patterns = []
+        return None
+
+    def LoadPatterns(self,maxpatt=-1,pattmask=None) :
+        """Load patterns from the given files. "maxpatt" argument, if >-1, limit the number of patterns to read, "pattmask" is pattern and pattern equal to it are loaded, to build this pattern mask read the Pattern.IsEqual documentation"""
+        # load the patterns
+        ntoread = maxpatt
+        if ntoread ==-1 :
+            ntoread = self.npatterns
+        fraction = ntoread/20
+        print "Load %d pattens" % ntoread
+        for i in xrange(ntoread) :
+            if i % fraction == 0 :
+                print i
+            newpatt = Pattern(self.nplanes,i)
+            newpatt.ReadFromFile(self.stream)
+            if pattmask == None :
+                self.patterns.append(newpatt)
+            elif newpatt.IsEqual(pattmask) :
+                self.patterns.append(newpatt)
+                
+        #i = 0
+        # for line in self.stream :
+        #     if i % fraction == 0:
+        #         print i
+        #     newpatt = Pattern(self.nplanes,i)
+        #     newpatt.ReadFromLine(line)
+        #     self.patterns.append(newpatt)
+        #     i += 1
+        print "Done"
+        return None
+
+    def FindPatterns(self,pattern) :
+        """Search, using a linear algorithm, if exist an equal pattern. Because the -1 fields are interpreted as "any" multiple matches are possible, the method retuns a list"""
+        res = []
+        for patt in self.patterns :
+            if patt.IsEqual(pattern) :
+                res.append(patt)
+        return res
+
+    def BuildKDTree(self) :
+        """Build a KD-Tree representation of the patterns"""
+        kdtree = PatternKDTree(self.patterns[0],0)
+        for node in self.patterns[1:] :
+            kdtree.AddNode(node)
+        return kdtree
+
+
+class FTKHit :
+    """this class describe the content of a single hit reading the format of the FTK wrapper"""
+    def __init__(self,raw_elements) :
+        # global position of the hit
+        self.x = float(raw_elements[0])
+        self.y = float(raw_elements[1])
+        self.z = float(raw_elements[2])
+        # type of the detector: 1 pxl, 0 SCT
+        self.type = int(raw_elements[3])
+        # detector position: 0 bar
+        self.BarEcp = int(raw_elements[4])
+        # modul layer number, phi and eta position
+        self.layer = int(raw_elements[5])
+        self.phi_module = int(raw_elements[6])
+        self.eta_module = int(raw_elements[7])
+        # for SCT side, PXL phi position of the channel
+        self.side = int(raw_elements[8])
+        # SCT number of strip, PXL eta position
+        self.strip = int(raw_elements[9])
+        # PXL ToT, SCT number of strips
+        self.num_strips = int(raw_elements[10])
+        # event number of the associated track
+        self.event = int(raw_elements[11])
+        # barcode of the associated track
+        self.barcode = int(raw_elements[12])
+        # pt of the associated track
+        self.barcode_pt = float(raw_elements[13])
+        # fraction of the association
+        self.barcode_frac = float(raw_elements[14])
+
+        if self.type != 0 :
+            return None
+        layer_offset = 0 # 3 if you focus on the barrel and after don't use the plane map
+        # here elaborate SCT ID for barrel
+        if self.BarEcp == 0 :
+            if self.layer==0 and self.side == 1 :
+                self.layer = 0 + layer_offset
+            elif self.layer==0 and self.side == 0 :
+                self.layer = 1 + layer_offset
+            elif self.layer==1 and self.side == 0 :
+                self.layer = 2 + layer_offset
+            elif self.layer==1 and self.side == 1 :
+                self.layer = 3 + layer_offset
+            elif self.layer==2 and self.side == 1 :
+                self.layer = 4 + layer_offset
+            elif self.layer==2 and self.side == 0 :
+                self.layer = 5 + layer_offset
+            elif self.layer==3 and self.side == 0 :
+                self.layer = 6 + layer_offset
+            elif self.layer==3 and self.side == 1 :
+                self.layer = 7 + layer_offset
+        else : # endcap part, look FTKPMap.cxx for further details
+            outside = 0
+            inner_ring = 0;
+            if self.eta_module > 0 :
+                inner_ring = 1
+
+            if (self.eta_module == 0 or self.eta_module == 2) and self.side == 1 :
+                outside = 1
+
+            if self.eta_module == 1 and self.side == 0 :
+                outside = 1
+    
+            # /* disk 8 flipped: special case */
+            if self.layer == 8 and self.side == 1 :
+                outside = 0
+            if self.layer == 8 and self.side == 0 :
+                outside = 1
+    
+            # /* split the disks up by inner/outer, and by side */
+            self.layer = 4*self.layer + 2*inner_ring + outside;
+    
+            # /* aaaaand fix eta index */
+            if inner_ring:
+                self.eta_module = self.eta_module - 1;
+
+            
+        return None
+
+class FTKOffline :
+    """This class summarize the content of the offline tracks as stored in the wrapper files"""
+    def __init__(self,params) :
+        # perigee parameters
+        self.d0 = float(params[0])
+        self.z0 = float(params[1])
+        # direction
+        self.phi0 = float(params[2])
+        self.ctheta = float(params[3])
+        self.eta = -log(tan(atan2(1.0,self.ctheta)/2.))
+        self.qpt = float(params[4])
+        self.curv = 1./self.qpt/2000.0  #offline tracks are in MeV
+        # truth association
+        self.evtidx = int(params[5])
+        self.barcode = int(params[6])
+        self.barcode_frac = float(params[7])
+        return None
+
+class FTKTruth :
+    def __init__(self,params) :
+        """FTKTruth is described in the files produced by the wrapper using 8 values, here the value are converted in the ones used in FTK"""
+        # get the raw parameter
+        self.x0 = float(params[0])
+        self.y0 = float(params[1])
+        self.z0 = float(params[2])
+        self.charge = float(params[3])
+        self.px = float(params[4])
+        self.py = float(params[5])
+        self.pz = float(params[6])
+        self.pdgcode = int(params[7])
+        self.assoc = int(params[8])
+        self.barcode_frac = float(params[9])
+        self.evtindex = int(params[10])
+        self.barcode = int(params[11])
+        #print self.barcode
+        self.parentID = int(params[12])
+        self.isfiducial = int(params[13])
+
+        self.pt = sqrt(self.px**2+self.py**2)
+        self.ctheta = self.pz/self.pt
+        if self.charge >= 0 :
+            signcharge = 1.0
+        else :
+            signcharge = -1.0
+            
+        # evaluate the derived parameters
+        x = self.x0-self.charge*self.py
+        y = self.y0+self.charge*self.px
+        self.curv = self.charge/sqrt(self.px**2+self.py**2)
+        try :
+            self.d0 = sqrt(x**2+y**2)*signcharge-1./self.curv
+        except ZeroDivisionError:
+            # print "Warning: 0 curvature"
+            self.d0 = 0
+        self.phi0 = atan2(-x*signcharge,y*signcharge)
+        self.curv /= 2.
+        thetaOver2 = (self.ctheta**2-1)/(2*self.ctheta)
+        try :
+            theta = atan2(self.pt,self.pz)
+            self.eta = -log(tan(theta/2.))
+        except :
+            self.eta = 0
+        return None
+
+    def Print(self) :
+        print "(curv,phi0,d0,ctheta,z0)=(%f,%f,%f,%f,%f)" % (self.curv, self.phi0, self.d0, self.ctheta, self.z0), "(assoc,barcode,evtID,parentID)=(%d,%d,%d,%d)" % (self.assoc,self.barcode,self.evtindex,self.parentID), "pdg=%d" % self.pdgcode
+        return None
+
+class FTKEventStreamer :
+    def __init__(self,outFile) :
+        # Class to handle event outputing
+        self.thisEvent = ""
+        self.outFile = outFile
+
+    def clear(self):
+        # Clear data for next event
+        self.thisEvent = ""
+
+    def addLine(self,line):
+        # Clear data for next event
+        self.thisEvent += line 
+
+    def write(self, roads=None):
+        # output data for next event
+        self.outFile.write(self.thisEvent)
+        if roads:
+            self.writeRoads(roads)
+        
+    def writeRoads(self,roads):
+
+        for region in roads:        
+            if not region:
+                continue
+            
+            for road in region:
+                if not road:
+                    continue
+                self.outFile.write("D\t"+str(road[0])+"\t"+str(road[1])+"\t"+str(road[2])+"\t"+str(road[3])+"\n")
+
+
+class FTKEvent :
+    def __init__(self, outFile=None) :
+        # member to store event information
+        self.run = -1
+        self.event = -1;
+        self.raw_hits = []
+        self.truth_tracks = []
+        self.off_tracks = []
+        # flag to control how the events are parsed
+        self.ignoreHits = False
+        self.ignoreOffline = False
+        self.ignoreTruth = False
+
+        # flag to enable caching of input event
+        if outFile:
+            self.EventStreamer = FTKEventStreamer(outFile)
+        else:
+            self.EventStreamer = None
+            
+        return None
+
+    def Reset(self) :
+        self.run = -1
+        self.event = -1;
+        self.raw_hits = []
+        self.truth_tracks = []
+        self.off_tracks = []
+        return None
+
+    
+    def ReadFromFile(self,stream) :
+        """Read the event from an ascii encoded file"""
+        inEvent = False
+
+        if self.EventStreamer:
+            self.EventStreamer.clear()
+
+        for line in stream :
+
+            if self.EventStreamer:
+                self.EventStreamer.addLine(line)
+            
+            #elements = line.split()
+            if line[0] == "R" :
+                self.run = int(line.split()[1])
+            elif line[0] == "F" :
+                #print self.event
+                self.event = int(line.split()[1])
+                inEvent = True
+            elif line[0] == "S" :
+                if not self.ignoreHits :
+                    self.raw_hits.append(FTKHit(line.split()[1:]))
+            elif line[0] == "E" :
+                if not self.ignoreOffline :
+                    self.off_tracks.append(FTKOffline(line.split()[1:]))
+            elif line[0] == "T" :
+                if not self.ignoreTruth :
+                    self.truth_tracks.append(FTKTruth(line.split()[1:]))
+            elif line[0] == "L" :
+                break
+        return inEvent
+
+    def WriteToFile(self,roads=None) :
+        """Write event to an ascii encoded file"""
+        self.EventStreamer.write(roads)
+
+    def filterHitsBarcode(self,barcode) :
+        """This function fitlers the hits by barcode"""
+        newHitList = []
+        for ihit in self.raw_hits : # hits loop
+            if ihit.barcode == barcode :
+                newHitList.append(ihit)
+            #end hits loop
+        self.raw_hits = newHitList
+        return len(self.raw_hits)
+
+    def IsBarrel(self) :
+        """Return True if all the hits are in the barrel"""
+        isBarrel = True
+        for hit in self.raw_hits :
+            if hit.BarEcp != 0 :
+                isBarrel = False
+                break
+        return isBarrel
+
+    def GroupHits(self) :
+        """Return the number of planes with hits"""
+        plane_list = {}
+        for hit in self.raw_hits :
+            if hit.layer in plane_list :
+                plane_list[hit.layer] += [hit]
+            else :
+                plane_list[hit.layer] = [hit]
+        return plane_list
+
+    def PrintTruthTracks(self) :
+        """Print the list of the truth tracks"""
+        for track in self.truth_tracks :
+            track.Print()
+            
+class FTKFileChain :
+    def __init__(self,filelist,outFile=None) :
+        self.filelist = filelist
+        self.nfiles = len(filelist)
+        self.currentID = -1
+        self.event = -1
+        self.localevent = -1
+        self.doWriteOutput = False
+        self.outFile = outFile
+        self.FTKEvent = FTKEvent(self.outFile)
+
+        return None
+
+    def open_helper(self,path) :
+        print "Open", path
+        if path[-3:] == "bz2" :
+            print "INFO: Read bz2 compressed data file",
+            self.stream = bz2.BZ2File(path,"r")
+            print "Done"
+        elif path[-2:] == "gz" : 
+            print "INFO: Read  gzip compressed data file",
+            self.stream = bz2.GzipFile(path,"r")
+            print "Done"
+        else :
+            self.stream = open(path,"r")
+        return None
+
+    def nextevent(self) :
+        if self.currentID == -1 :
+            self.currentID += 1
+            print "Opening ", self.filelist[0]
+            self.open_helper(self.filelist[0])
+        self.FTKEvent.Reset()
+        while not self.FTKEvent.ReadFromFile(self.stream) :
+            self.currentID += 1
+            if self.currentID == self.nfiles :
+                print "All wrapper events read", self.filelist
+                self.FTKEvent.Reset()
+                return False
+            self.stream.close()
+            self.open_helper(self.filelist[self.currentID])
+            self.localevent = -1
+        # increment the event counter
+        self.event += 1
+        self.localevent += 1
+        return True
+
+class Constant :
+    """This class defines constant"""
+    def __init__(self,nplanes,pid=-1) :
+        """Create the pattern, passing the number of planes and its ID"""
+        # set number of planes
+        self.nplanes = nplanes
+        if int(nplanes) == 11:
+            self.ncoords = 14
+        elif int(nplanes) == 12:
+            self.ncoords = 16
+        # set the Constant-ID
+        self.pid = pid
+        # set the initial values in the constants
+        self.Vc  = [0]*self.ncoords
+        self.Vd  = [0]*self.ncoords
+        self.Vf  = [0]*self.ncoords
+        self.Vz0 = [0]*self.ncoords
+        self.Vo  = [0]*self.ncoords
+        self.kaverages = [0]*(self.ncoords-5)
+        self.kernel = [0]*(self.ncoords-5)*self.ncoords
+        self.Cc  = 0
+        self.Cd  = 0
+        self.Cf  = 0
+        self.Cz0 = 0
+        self.Co  = 0
+        return None
+
+    def SetNPlanes(self,nplanes) :
+        """Set the number of plane and sizes the internal structures"""
+        self.nplanes = nplanes
+        self.ssid = [-1]*nplanes
+        return None
+
+    def ReadFromFile(self,fdesc) :
+      while self.Co==0:
+        line = fdesc.readline()        
+        if line.find("sector")!=-1 :
+            value = fdesc.readline()
+            self.pid = value.split()[0]
+        if line.find("Vc")!=-1 :
+            for i in xrange(self.ncoords):
+                value = fdesc.readline()
+                self.Vc[i] = value.split()[0]
+        if line.find("Vd")!=-1 :
+            for i in xrange(self.ncoords):
+                value = fdesc.readline()
+                self.Vd[i] = value.split()[0]
+        if line.find("Vf")!=-1 :
+            for i in xrange(self.ncoords):
+                value = fdesc.readline()
+                self.Vf[i] = value.split()[0]
+        if line.find("Vz0")!=-1 :
+            for i in xrange(self.ncoords):
+                value = fdesc.readline()
+                self.Vz0[i] = value.split()[0]
+        if line.find("Vo")!=-1 :
+            for i in xrange(self.ncoords):
+                value = fdesc.readline()
+                self.Vo[i] = value.split()[0]
+        if line.find("kaverages")!=-1 :
+            for i in xrange(self.ncoords-5):
+                value = fdesc.readline()
+                self.kaverages[i] = value.split()[0]
+        if line.find("kernel")!=-1 :
+            for i in xrange((self.ncoords-5)*self.ncoords):
+                value = fdesc.readline()
+                self.kernel[i] = value.split()[0]
+        if line.find("Cc")!=-1 :
+            value = fdesc.readline()
+            self.Cc = value.split()[0]
+        if line.find("Cd")!=-1 :
+            value = fdesc.readline()
+            self.Cd = value.split()[0]
+        if line.find("Cf")!=-1 :
+            value = fdesc.readline()
+            self.Cf = value.split()[0]
+        if line.find("Cz0")!=-1 :
+            value = fdesc.readline()
+            self.Cz0 = value.split()[0]
+        if line.find("Co")!=-1 :
+            value = fdesc.readline()
+            self.Co = value.split()[0]
+      return self.pid
+
+    def PrintToFile(self,stream,newpid='') :
+        stream.flush()
+        """Print the constant content into a file"""
+        stream.write("sectors\n")
+        # newpid is for when writing into 7_11 connections so that the 7-11L synchronziation is done
+        if newpid!='':
+          stream.write(str(newpid)+"\n")
+        else:
+          stream.write(str(self.pid)+"\n")
+        stream.write(" Vc\n")
+        for i in self.Vc:
+            stream.write(str(i)+"\n")
+        stream.write(" Vd\n")
+        for i in self.Vd:
+            stream.write(str(i)+"\n") 
+        stream.write(" Vf\n")
+        for i in self.Vf:
+            stream.write(str(i)+"\n") 
+        stream.write(" Vz0\n")
+        for i in self.Vz0:
+            stream.write(str(i)+"\n") 
+        stream.write(" Vo\n")
+        for i in self.Vo:
+            stream.write(str(i)+"\n") 
+        stream.write(" kaverages\n")
+        for i in self.kaverages:
+            stream.write(str(i)+"\n") 
+        stream.write(" kernel\n")
+        for i in self.kernel:
+            stream.write(str(i)+"\n") 
+        stream.write(" Cc\n")
+        stream.write(str(self.Cc)+"\n")
+        stream.write(" Cd\n")
+        stream.write(str(self.Cd)+"\n")
+        stream.write(" Cf\n")
+        stream.write(str(self.Cf)+"\n")
+        stream.write(" Cz0\n")
+        stream.write(str(self.Cz0)+"\n")
+        stream.write(" Co\n")
+        stream.write(str(self.Co)+"\n")
+
+class ConstantBank :
+    def __init__(self,path,mode="r",nplanes=-1) :
+        self.mode = mode
+        self.stream = None
+        self.path = path
+        if path[-3:] == "bz2" :
+            print "INFO: Read bz2 compressed pattern bank",
+            self.stream = bz2.BZ2File(path,mode)
+            print "Done"
+        elif path[-2:] == "gz" :
+            print "INFO: Read  gzip compressed pattern bank",
+            self.stream = bz2.GzipFile(path,mode)
+            print "Done"
+        else :
+            self.stream = open(path,mode)
+
+        if mode.find("r")>-1 :
+            # read the header of the bank
+            line = ""
+            while line.find("NPLANES")==-1:
+                line = self.stream.readline()
+                print " 1",line
+            line = self.stream.readline()
+            print "2",line
+            self.nplanes = line.split()[0]
+            while line.find("NSECTORS")==-1:
+                line = self.stream.readline()
+                print "3",line
+            line = self.stream.readline()
+            print "4",line
+            self.nconstants = int(line.split()[0])
+            while line.find("NDIM")==-1:
+                line = self.stream.readline()
+            line = self.stream.readline()
+            self.ndim = line.split()[0]
+            self.constants=[]
+        else :
+            self.nplanes = nplanes
+            self.nconstants = 0
+            self.ndims = 0
+            self.patterns = []
+        return None
+
+    def LoadConstants(self,maxgcon=-1,gconmask=None) :
+        """Load constants from the given files. "maxgcon" argument, if >-1, limit the number of constants to read, "gconmask" is constant and constant equal to it are loaded, to build this constant mask read the Constant.IsEqual documentation"""
+        # load the constants
+        ntoread = maxgcon
+        if ntoread ==-1 :
+            ntoread = self.nconstants
+        fraction = ntoread/20
+        print "Load %d constants" % ntoread
+        for i in xrange(ntoread) :
+            if i % fraction == 0 :
+                print i
+            newgcon = Constant(self.nplanes,i)
+            newgcon.ReadFromFile(self.stream)
+            self.constants.append(newgcon)
+            if str(newgcon.pid) != str( i ):
+                print 'Check do they match: ? ',newgcon.pid, i
+
+        #i = 0
+        # for line in self.stream :
+        #     if i % fraction == 0:
+        #         print i
+        #     newpatt = Pattern(self.nplanes,i)
+        #     newpatt.ReadFromLine(line)
+        #     self.patterns.append(newpatt)
+        #     i += 1
+        print "Done"
+        return None
+
+    def FindConstant(self,pid) :
+        """Search, using a linear algorithm, if exist an equal pattern. Because the -1 fields are interpreted as "any" multiple matches are possible, the method retuns a list"""
+        res = []
+        for gcon in self.constants :
+            if str(gcon.pid) == str(pid) :
+                return gcon
+        print 'NOT found!! ??? ? !', pid,self.path,self.constants[int(pid)].pid
+
+
+        # if not found
+        return -1
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_connection_prod.sh b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_connection_prod.sh
new file mode 100644
index 00000000000..44384bea07c
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_connection_prod.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+source $DIR/utils.sh
+
+usage() {
+  echo "Usage -"
+  echo ""
+  echo "   $0 [DATASET_FIRSTSTAGE] [DATASET_SECONDSTAGE]"
+  echo ""
+  echo ""
+  echo ""
+  echo "  for more information consult : https://twiki.cern.ch/twiki/bin/viewauth/Atlas/FTKSimShortTutorial#Generating_connection_files"
+  exit
+}
+
+echo
+e_header "Prepping first stage banks for second stage bank generation"
+echo
+echo
+
+e_underline "Checking arguments ... "
+if [ -z $1 ]; then
+  e_error "Must provide a path to Dataset containing first stage banks"
+  usage
+else
+  DSPATH_1=$1;
+  e_success "Recognized first stage bank datapath as "$DSPATH_1
+fi
+
+if [ -z $2 ]; then
+  e_error "Must provide a path to Dataset containing second stage banks"
+  usage
+else
+  DSPATH_2=$2;
+  e_success "Recognized second stage bank datapath as "$DSPATH_2
+fi
+
+shift; shift;
+
+echo
+e_underline "Checking $DSPATH_1 for first stage constants"
+
+FOUND=0
+for FILE in $(ls $DSPATH_1); do
+  TMP_STR=$(echo $FILE | grep "sectors_raw_8L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    e_success "Recognized a file that looks like a 8L sector. Assume the dataset is correct and proceed"
+    e_note "file recognized : $FILE"
+    FOUND=1
+    break
+  fi
+done
+
+if [ $FOUND -eq 0 ]; then
+  e_error "Could not find 8L sector matching a string 'sectors_raw_8L_reg' in the dataset $DSPATH_1"
+  exit
+fi
+
+echo
+e_underline "Checking $DSPATH_2 for second stage constants"
+
+FOUND=0
+for FILE in $(ls $DSPATH_2); do
+  TMP_STR=$(echo $FILE | grep "sectors_raw_12L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    e_success "Recognized a file that looks like a 12L sector. Assume the dataset is correct and proceed"
+    e_note "file recognized : $FILE"
+    FOUND=1
+    break
+  fi
+done
+
+if [ $FOUND -eq 0 ]; then
+  e_error "Could not find 8L sector matching a string 'sectors_raw_8L_reg' in the dataset $DSPATH_2"
+  exit
+fi
+
+echo
+e_underline "Creating directory"
+
+e_arrow "create patt/"
+mkdir -p patt
+e_arrow "create gcon/"
+mkdir -p gcon
+
+echo
+e_underline "Linking files ..."
+
+extract_nicename() {
+  TMP_STR=$1
+  PATTERN=$2
+  echo ${TMP_STR##*$PATTERN}
+  #$(expr match "$TMP_STR" "$PATTERN")
+  #for i in $(seq 1 5); do
+  #  INDEX=$(expr index $TMP_STR ".")
+  #  TMP_STR=${TMP_STR:$INDEX}
+  #done
+  #echo $TMP_STR
+}
+
+for FILE in $(ls $DSPATH_1); do
+  TMP_STR=$(echo $FILE | grep "sectors_raw_8L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd patt/
+    NICENAME=$(extract_nicename $TMP_STR sectors)
+    ln -sfv ../$DSPATH_1/$FILE sectors$NICENAME
+    cd ../
+  fi
+  TMP_STR=$(echo $FILE | grep "corrgen_raw_8L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd gcon/
+    NICENAME=$(extract_nicename $TMP_STR corrgen)
+    ln -sfv ../$DSPATH_1/$FILE corrgen$NICENAME
+    cd ../
+  fi
+done
+
+
+for FILE in $(ls $DSPATH_2); do
+  TMP_STR=$(echo $FILE | grep "sectors_raw_12L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd patt/
+    NICENAME=$(extract_nicename $TMP_STR sectors)
+    ln -sfv ../$DSPATH_2/$FILE sectors$NICENAME
+    cd ../
+  fi
+  TMP_STR=$(echo $FILE | grep "corrgen_raw_12L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd gcon/
+    NICENAME=$(extract_nicename $TMP_STR corrgen)
+    ln -sfv ../$DSPATH_2/$FILE corrgen$NICENAME
+    cd ../
+  fi
+done
+
+echo
+e_success "DONE"
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_simulation.sh b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_simulation.sh
new file mode 100644
index 00000000000..1be929f2590
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/prep_banks_for_simulation.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+source $DIR/utils.sh
+
+usage() {
+  echo "Usage -"
+  echo ""
+  echo "   $0 [DATASET_FIRSTSTAGE] [DATASET_SECONDSTAGE]"
+  echo ""
+  echo ""
+  echo ""
+  echo "  for more information consult : https://twiki.cern.ch/twiki/bin/viewauth/Atlas/FTKSimShortTutorial#Generating_connection_files"
+  exit
+}
+
+echo
+e_header "Prepping first stage banks for second stage bank generation"
+echo
+echo
+
+e_underline "Checking arguments ... "
+if [ -z $1 ]; then
+  e_error "Must provide a path to Dataset containing first stage banks"
+  usage
+else
+  DSPATH_1=$1;
+  e_success "Recognized first stage bank datapath as "$DSPATH_1
+fi
+
+if [ -z $2 ]; then
+  e_error "Must provide a path to Dataset containing second stage banks"
+  usage
+else
+  DSPATH_2=$2;
+  e_success "Recognized second stage bank datapath as "$DSPATH_2
+fi
+
+shift; shift;
+
+echo
+e_underline "Checking $DSPATH_1 for first stage constants"
+
+FOUND=0
+for FILE in $(ls $DSPATH_1); do
+  TMP_STR=$(echo $FILE | grep "corrgen_raw_8L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    e_success "Recognized a file that looks like a 8L sector. Assume the dataset is correct and proceed"
+    e_note "file recognized : $FILE"
+    FOUND=1
+    break
+  fi
+done
+
+if [ $FOUND -eq 0 ]; then
+  e_error "Could not find 8L sector matching a string 'corrgen_raw_8L_reg' in the dataset $DSPATH_1"
+  exit
+fi
+
+echo
+e_underline "Checking $DSPATH_2 for second stage constants"
+
+FOUND=0
+for FILE in $(ls $DSPATH_2); do
+  TMP_STR=$(echo $FILE | grep "corrgen_raw_11L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    e_success "Recognized a file that looks like a 12L sector. Assume the dataset is correct and proceed"
+    e_note "file recognized : $FILE"
+    FOUND=1
+    break
+  fi
+done
+
+if [ $FOUND -eq 0 ]; then
+  e_error "Could not find 8L sector matching a string 'corrgen_raw_11L_reg' in the dataset $DSPATH_2"
+  exit
+fi
+
+echo
+e_underline "Creating directory"
+
+e_arrow "create patt/"
+mkdir -p patt
+e_arrow "create gcon/"
+mkdir -p gcon
+
+echo
+e_underline "Linking files ..."
+
+extract_nicename() {
+  TMP_STR=$1
+  PATTERN=$2
+  echo ${TMP_STR##*$PATTERN}
+  #$(expr match "$TMP_STR" "$PATTERN")
+  #for i in $(seq 1 5); do
+  #  INDEX=$(expr index $TMP_STR ".")
+  #  TMP_STR=${TMP_STR:$INDEX}
+  #done
+  #echo $TMP_STR
+}
+
+for FILE in $(ls $DSPATH_1); do
+  TMP_STR=$(echo $FILE | grep "sectors_raw_8L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd patt/
+    NICENAME=$(extract_nicename $TMP_STR sectors)
+    ln -sfv ../$DSPATH_1/$FILE sectors$NICENAME
+    cd ../
+  fi
+  TMP_STR=$(echo $FILE | grep "corrgen_raw_8L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd gcon/
+    NICENAME=$(extract_nicename $TMP_STR corrgen)
+    ln -sfv ../$DSPATH_1/$FILE corrgen$NICENAME
+    cd ../
+  fi
+done
+
+
+for FILE in $(ls $DSPATH_2); do
+  TMP_STR=$(echo $FILE | grep "sectors_raw_8L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd patt/
+    NICENAME=$(extract_nicename $TMP_STR sectors)
+    ln -sfv ../$DSPATH_2/$FILE sectors$NICENAME
+    cd ../
+  fi
+  TMP_STR=$(echo $FILE | grep "corrgen_raw_11L_reg")
+  if [ -n "${TMP_STR}" ]; then
+    cd gcon/
+    NICENAME=$(extract_nicename $TMP_STR corrgen)
+    ln -sfv ../$DSPATH_2/$FILE corrgen$NICENAME
+    cd ../
+  fi
+done
+
+echo
+e_success "DONE"
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/process_conn.sh b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/process_conn.sh
new file mode 100644
index 00000000000..2f40b3e9d3d
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/process_conn.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+##############################################################################
+#
+#
+# Process a single connection file for single region
+#
+#
+##############################################################################
+
+EOSCOMMAND="/afs/cern.ch/project/eos/installation/0.2.31/bin/eos.select"
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+# Help
+usage()
+{
+  echo "ERROR - Usage:"
+  echo
+  echo "put both 8L and 12L, .gcon.bz2 and .patt.bz2 files in the same directory. then..."
+  echo "      sh $(basename $0) OPTIONSTRINGS ..."
+  echo
+  echo "Options with arguments:"
+  echo "  -h    Help                   (Display this message)"
+  echo "  -d    bankdir                (e.g. -d /path/to/bank/dir/)"
+  echo "  -r    Region                 (e.g. -r 16)"
+  echo ""
+  echo "  e.g."
+  echo "  sh generate_connection/make_conn/process_conn.sh -d ./sector_const -r 0"
+  echo ""
+  echo "  for more information consult : https://twiki.cern.ch/twiki/bin/viewauth/Atlas/FTKSimShortTutorial#Generating_connection_files"
+  echo
+  exit
+}
+
+# Command-line opts
+while getopts ":d:r:h" OPTION; do
+  case $OPTION in
+    r) REGION=${OPTARG};;
+    d) BANKDIR=${OPTARG};;
+    h) usage;;
+    :) usage;;
+  esac
+done
+
+if [ -z ${REGION} ]; then usage; fi
+if [ -z ${BANKDIR} ]; then usage; fi
+
+# Verbose
+date
+echo "================================================"
+echo "$(basename $0) $*"
+echo "$(basename $0) $*" >> $DIR/.$(basename $0).history
+echo "------------------------------------------------"
+echo "REGION         : ${REGION}"
+echo "BANKDIR        : ${BANKDIR}"
+echo "================================================"
+
+#
+#
+# function
+#
+#
+
+# check if it's a number
+function is_number() {
+  re='^[0-9]+$'
+  if [[ $1 =~ $re ]]; then echo 1; else echo 0; fi
+}
+
+#cd $BANKDIR/patt
+cd $BANKDIR
+mkdir -p make_connection_log/
+LOG="make_connection_log/region_${REGION}.log"
+python $DIR/find_extrapolation_relations_v2.py sectors_raw_8L_reg${REGION}.patt.bz2 1 &> $LOG
+IS_SUCCESS=$(tail $LOG | grep "sucess")
+echo $IS_SUCCESS
+echo ""
+echo ""
+if [ -n "$IS_SUCCESS" ]; then
+  echo "The run was sucessful. The logfile is outputted : " $DIR/$LOG
+else
+  echo "Something went wrong in the process check the log file: " $DIR/$LOG
+fi
+
+
+#eof
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/tar_extrapolated_gcon.sh b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/tar_extrapolated_gcon.sh
new file mode 100644
index 00000000000..e22af79f07e
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/tar_extrapolated_gcon.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+source $DIR/utils.sh
+
+e_header "tarring newly generated gcon files"
+
+echo
+
+e_underline "checking arguments ..."
+
+if [ -z $1 ]; then
+  e_error "you must provide the path to the directory containing newly generated .gcon files"
+  exit
+else
+  DIRPATH=$1; shift;
+  e_success "argument recognized : DIRPATH="$DIRPATH
+fi
+
+FOUND=0
+for FILE in $(ls $DIRPATH); do
+  TMP_STR=$(echo $FILE | grep ".gcon" | grep -v "bz2")
+  if [ -n "${TMP_STR}" ]; then
+    e_success "Recognized a file that looks like a newly generated gcon file. Assume the dataset is correct and proceed"
+    e_note "file recognized : $FILE"
+    FOUND=1
+    break
+  fi
+done
+
+if [ $FOUND -eq 0 ]; then
+  e_error "Could not find file that match 'gcon' in the directory $DIRPATH"
+  exit
+fi
+
+
+e_arrow "Linking gcon files"
+for FILE in $(ls $DIRPATH); do
+  TMP_STR=$(echo $FILE | grep "gcon")
+  if [ -n "${TMP_STR}" ]; then
+    CHECK_BZIPPED=$(echo ${TMP_STR} | grep "bz2")
+    if [ -z ${CHECK_BZIPPED} ]; then
+      e_arrow "bzipping" $DIRPATH/$FILE
+      bzip2 $DIRPATH/$FILE
+      FILE=$FILE.bz2
+    fi
+    NEWFILENAME=${FILE//812L/11L}
+    cd $DIRPATH/../gcon/
+    ln -sfv ../patt/$FILE $NEWFILENAME
+    cd ..
+  fi
+done
+
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/utils.sh b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/utils.sh
new file mode 100644
index 00000000000..1d13ba88de0
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/generate_connection/make_conn/utils.sh
@@ -0,0 +1,153 @@
+#!/bin/bash
+
+#
+# Set Colors
+#
+
+bold=$(tput bold)
+underline=$(tput sgr 0 1)
+reset=$(tput sgr0)
+
+purple=$(tput setaf 171)
+red=$(tput setaf 1)
+green=$(tput setaf 76)
+tan=$(tput setaf 3)
+blue=$(tput setaf 38)
+
+#
+# Headers and  Logging
+#
+
+e_header() { printf "\n${bold}${purple}==========  %s  ==========${reset}\n" "$@"
+}
+e_arrow() { printf "➜ $@\n"
+}
+e_success() { printf "${green}✔ %s${reset}\n" "$@"
+}
+e_error() { printf "${red}✖ %s${reset}\n" "$@"
+}
+e_warning() { printf "${tan}➜ %s${reset}\n" "$@"
+}
+e_underline() { printf "${underline}${bold}%s${reset}\n" "$@"
+}
+e_bold() { printf "${bold}%s${reset}\n" "$@"
+}
+e_note() { printf "${underline}${bold}${blue}Note:${reset}  ${blue}%s${reset}\n" "$@"
+}
+
+#
+# USAGE FOR SEEKING CONFIRMATION
+# seek_confirmation "Ask a question"
+# Credt: https://github.com/kevva/dotfiles
+#
+# if is_confirmed; then
+#   some action
+# else
+#   some other action
+# fi
+#
+
+seek_confirmation() {
+  printf "\n${bold}$@${reset}"
+  read -p " (y/n) " -n 1
+  printf "\n"
+}
+
+# underlined
+seek_confirmation_head() {
+  printf "\n${underline}${bold}$@${reset}"
+  read -p "${underline}${bold} (y/n)${reset} " -n 1
+  printf "\n"
+}
+
+# Test whether the result of an 'ask' is a confirmation
+is_confirmed() {
+if [[ "$REPLY" =~ ^[Yy]$ ]]; then
+  return 0
+fi
+return 1
+}
+
+#
+# Test whether a command exists
+# $1 = cmd to test
+# Usage:
+# if type_exists 'git'; then
+#   some action
+# else
+#   some other action
+# fi
+#
+
+type_exists() {
+if [ $(type -P $1) ]; then
+  return 0
+fi
+return 1
+}
+
+#
+# Test which OS the user runs
+# $1 = OS to test
+# Usage: if is_os 'darwin'; then
+#
+
+is_os() {
+if [[ "${OSTYPE}" == $1* ]]; then
+  return 0
+fi
+return 1
+}
+
+#
+# Pushover Notifications
+# Usage: pushover "Title Goes Here" "Message Goes Here"
+# Credit: http://ryonsherman.blogspot.com/2012/10/shell-script-to-send-pushover.html
+#
+
+pushover () {
+    PUSHOVERURL="https://api.pushover.net/1/messages.json"
+    API_KEY="your-api-here"
+    USER_KEY="your-user-key-here"
+    DEVICE=""
+
+    TITLE="${1}"
+    MESSAGE="${2}"
+
+    curl \
+    -F "token=${API_KEY}" \
+    -F "user=${USER_KEY}" \
+    -F "device=${DEVICE}" \
+    -F "title=${TITLE}" \
+    -F "message=${MESSAGE}" \
+    "${PUSHOVERURL}" > /dev/null 2>&1
+}
+
+##
+## Given a list of desired items and installed items, return a list
+## of uninstalled items. Arrays in bash are insane (not in a good way).
+## Credit: https://github.com/cowboy/dotfiles
+##
+#
+#function to_install() {
+#  local debug desired installed i desired_s installed_s remain
+#  if [[ "$1" == 1 ]]; then debug=1; shift; fi
+#    # Convert args to arrays, handling both space- and newline-separated lists.
+#    read -ra desired < <(echo "$1" | tr '\n' ' ')
+#    read -ra installed < <(echo "$2" | tr '\n' ' ')
+#    # Sort desired and installed arrays.
+#    unset i; while read -r; do desired_s[i++]=$REPLY; done < <(
+#      printf "%s\n" "${desired[@]}" | sort
+#    )
+#    unset i; while read -r; do installed_s[i++]=$REPLY; done < <(
+#      printf "%s\n" "${installed[@]}" | sort
+#    )
+#    # Get the difference. comm is awesome.
+#    unset i; while read -r; do remain[i++]=$REPLY; done < <(
+#      comm -13 <(printf "%s\n" "${installed_s[@]}") <(printf "%s\n" "${desired_s[@]}")
+#  )
+#  [[ "$debug" ]] && for v in desired desired_s installed installed_s remain; do
+#    echo "$v ($(eval echo "\${#$v[*]}")) $(eval echo "\${$v[*]}")"
+#  done
+#  echo "${remain[@]}"
+#}
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_HWMode2_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_HWMode2_joboptions.py
new file mode 100644
index 00000000000..9fcdbb0a32e
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_HWMode2_joboptions.py
@@ -0,0 +1,109 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+from PyJobTransforms.trfUtils import findFile
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12LiblHW.pmap')
+print "Using PMAP:", pmap_path
+rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl32TmodB.tmap')
+print "Using RMAP:", rmap_path
+
+#MC11 for IBL
+FTKBankGen.pmap_path = pmap_path
+FTKBankGen.rmap_path = rmap_path
+FTKBankGen.IBLMode = 1
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = True;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+#FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 64;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = True;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+#-----------------------------------------------------------------------------
+# save ROOT histograms and Tuple
+#-----------------------------------------------------------------------------
+#from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
+#Stream1 = AthenaPoolOutputStream( "Stream1" )
+#Stream1.OutputFile =   "SimplePoolFile_Complete.root"
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output = [ "MyNewPackage DATAFILE='testAug21.root' OPT='RECREATE'" ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_joboptions.py
new file mode 100644
index 00000000000..42144409982
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_32TModB_joboptions.py
@@ -0,0 +1,109 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+from PyJobTransforms.trfUtils import findFile
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12LiblHW.pmap')
+print "Using PMAP:", pmap_path
+rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl32TmodB.tmap')
+print "Using RMAP:", rmap_path
+
+#MC11 for IBL
+FTKBankGen.pmap_path = pmap_path
+FTKBankGen.rmap_path = rmap_path
+FTKBankGen.IBLMode = 1
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = True;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+#FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 32;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = False;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+#-----------------------------------------------------------------------------
+# save ROOT histograms and Tuple
+#-----------------------------------------------------------------------------
+#from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
+#Stream1 = AthenaPoolOutputStream( "Stream1" )
+#Stream1.OutputFile =   "SimplePoolFile_Complete.root"
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output = [ "MyNewPackage DATAFILE='testAug21.root' OPT='RECREATE'" ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_HWMode2_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_HWMode2_joboptions.py
new file mode 100644
index 00000000000..74ce9e2aa56
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_HWMode2_joboptions.py
@@ -0,0 +1,109 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+from PyJobTransforms.trfUtils import findFile
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12LiblHW.pmap')
+print "Using PMAP:", pmap_path
+rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl64TmodB.tmap')
+print "Using RMAP:", rmap_path
+
+#MC11 for IBL
+FTKBankGen.pmap_path = pmap_path
+FTKBankGen.rmap_path = rmap_path
+FTKBankGen.IBLMode = 1
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = True;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+#FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 64;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = True;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+#-----------------------------------------------------------------------------
+# save ROOT histograms and Tuple
+#-----------------------------------------------------------------------------
+#from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
+#Stream1 = AthenaPoolOutputStream( "Stream1" )
+#Stream1.OutputFile =   "SimplePoolFile_Complete.root"
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output = [ "MyNewPackage DATAFILE='testAug21.root' OPT='RECREATE'" ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_joboptions.py
new file mode 100644
index 00000000000..3562b5009ab
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_64TModB_joboptions.py
@@ -0,0 +1,109 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+from PyJobTransforms.trfUtils import findFile
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12LiblHW.pmap')
+print "Using PMAP:", pmap_path
+rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl64TmodB.tmap')
+print "Using RMAP:", rmap_path
+
+#MC11 for IBL
+FTKBankGen.pmap_path = pmap_path
+FTKBankGen.rmap_path = rmap_path
+FTKBankGen.IBLMode = 1
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = True;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+#FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 64;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = False;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+#-----------------------------------------------------------------------------
+# save ROOT histograms and Tuple
+#-----------------------------------------------------------------------------
+#from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
+#Stream1 = AthenaPoolOutputStream( "Stream1" )
+#Stream1.OutputFile =   "SimplePoolFile_Complete.root"
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output = [ "MyNewPackage DATAFILE='testAug21.root' OPT='RECREATE'" ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_HWMode2_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_HWMode2_joboptions.py
new file mode 100644
index 00000000000..a25e80e147a
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_HWMode2_joboptions.py
@@ -0,0 +1,98 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+from PyJobTransforms.trfUtils import findFile
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12LiblHW.pmap')
+print "Using PMAP:", pmap_path
+rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl.tmap')
+print "Using RMAP:", rmap_path
+
+#MC11 for IBL
+FTKBankGen.pmap_path = pmap_path
+FTKBankGen.rmap_path = rmap_path
+FTKBankGen.IBLMode = 1
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = False;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+#FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 64;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = True;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_Run2GEO_32TModB_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_Run2GEO_32TModB_joboptions.py
new file mode 100644
index 00000000000..7fa0e9ac42c
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_Run2GEO_32TModB_joboptions.py
@@ -0,0 +1,111 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+from PyJobTransforms.trfUtils import findFile
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12LiblHW3D.pmap')
+print "Using PMAP:", pmap_path
+rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl32TmodB_3D_t13.tmap')
+#rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl64TmodB_3D_t13.tmap')
+#rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl64TmodB_3D_t1.tmap')
+print "Using RMAP:", rmap_path
+
+#MC11 for IBL
+FTKBankGen.pmap_path = pmap_path
+FTKBankGen.rmap_path = rmap_path
+FTKBankGen.IBLMode = 2
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = True;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+#FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 32;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = True;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+#-----------------------------------------------------------------------------
+# save ROOT histograms and Tuple
+#-----------------------------------------------------------------------------
+#from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
+#Stream1 = AthenaPoolOutputStream( "Stream1" )
+#Stream1.OutputFile =   "SimplePoolFile_Complete.root"
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output = [ "MyNewPackage DATAFILE='testAug21.root' OPT='RECREATE'" ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_joboptions.py
new file mode 100644
index 00000000000..fd35eacb5a7
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenIBL_joboptions.py
@@ -0,0 +1,50 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from PyJobTransforms.trfUtils import findFile
+from TrigFTKSim.TrigFTKSimConf import *
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+FTKBankGen.const_test_mode = False;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8; # GeV
+FTKBankGen.TRAIN_PDG = 13; # muon ID
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenITk_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenITk_joboptions.py
new file mode 100644
index 00000000000..6d48addfdae
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGenITk_joboptions.py
@@ -0,0 +1,67 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc
+from PyJobTransforms.trfUtils import findFile
+from TrigFTKSim.TrigFTKSimConf import *
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks  = True
+FTKSGHit.OutputLevel      = INFO # DEBUG
+FTKSGHit.DoOutFileRawHits = True
+ToolSvc += FTKSGHit
+
+FTKBankGen = FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen.pmap_path = findFile( os.environ['DATAPATH'] , "ftk_configuration/map_files/raw_ITkExample.pmap" )
+FTKBankGen.rmap_path = findFile( os.environ['DATAPATH'] , "ftk_configuration/map_files/raw_ITkExample.tmap" )
+FTKBankGen.IBLMode   = 0
+FTKBankGen.ITkMode   = True
+
+FTKBankGen.const_test_mode          = False;
+FTKBankGen.Clustering               = False;
+FTKBankGen.SaveClusterContent       = False;
+FTKBankGen.DiagClustering           = True;
+FTKBankGen.PixelClusteringMode      = 0;
+FTKBankGen.DuplicateGanged          = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 4.0; # GeV
+FTKBankGen.TRAIN_PDG = 13; # Traing samples particle ID  
+#FTKBankGen.NEvent = event; # Event number
+FTKBankGen.NBanks = 96;
+FTKBankGen.BarrelOnly = True;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = False;
+
+FTKBankGen.par_c_max=0.000125;
+FTKBankGen.par_c_min=-0.000125;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=0.159155; # 0.5 / Pi
+FTKBankGen.par_phi_min=0.095493; # 0.3 / Pi
+FTKBankGen.par_phi_slices=10;
+
+FTKBankGen.par_d0_max=2.0;
+FTKBankGen.par_d0_min=-2.0;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=150;
+FTKBankGen.par_z0_min=-150;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=0.3;
+FTKBankGen.par_eta_min=0.1;
+FTKBankGen.par_eta_slices=10;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+# For debugging FPE bugs
+#from RecExConfig.RecFlags import rec
+#rec.doFloatingPointException=True
+
+
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGen_joboptions.py b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGen_joboptions.py
new file mode 100644
index 00000000000..0888cb8fe6a
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/r2e_FTKBankGen_joboptions.py
@@ -0,0 +1,108 @@
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# FTK algorithm inclusions
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import ToolSvc 
+from TrigFTKSim.TrigFTKSimConf import *
+
+
+print "Add FTK_SGHitInput tool"
+FTKSGHit = FTK_SGHitInput()
+FTKSGHit.ReadTruthTracks=True
+ToolSvc += FTKSGHit
+
+
+#FTKSGHit.OutputLevel=DEBUG
+# print "Add FTKDetector tool"
+# FTKDet = FTKDetectorTool()
+# FTKDet.doBadModuleMap = False # True to produce or False to read an existing one
+# FTKDet.useBadModuleMap = False # may disable the use of dead modules mapping
+# #FTKDet.BadSSMapPath = "badSSmap.bmap"
+# #FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+# #FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+# ToolSvc += FTKDet
+# #FTKDet.OutputLevel=DEBUG
+
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+#FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=DEBUG)
+FTKBankGen= FTKBankGenAlgo("FTKBankGenAlgo", OutputLevel=FATAL)
+#MC11 for 8L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8Lc.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+#MC11 for 11L
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.tmap"
+
+from PyJobTransforms.trfUtils import findFile
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl.pmap')
+print "Using PMAP:", pmap_path
+rmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12Libl.tmap')
+print "Using RMAP:", rmap_path
+
+#MC11 for IBL
+FTKBankGen.pmap_path = pmap_path
+FTKBankGen.rmap_path = rmap_path
+
+#MC12 for IBL
+#FTKBankGen.pmap_path = "../../../TrigFTKSim/config/map_file/raw_8LcIblEXPtoIBL.pmap"
+#FTKBankGen.rmap_path = "../../../TrigFTKSim/config/map_file/raw_11L.imap2"
+
+FTKBankGen.const_test_mode = False;
+#FTKBankGen.const_test_mode = True;
+#FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+#FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/my_const_11L"
+FTKBankGen.sector_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+FTKBankGen.gcon_dir_path = "/afs/cern.ch/work/t/tomoya/public/user.tompkins.tdaqtdr_base_8LcIbl123_20130805"
+
+FTKBankGen.Clustering = False;
+FTKBankGen.SaveClusterContent = False;
+FTKBankGen.DiagClustering = True;
+#FTKBankGen.SctClustering = False;
+FTKBankGen.PixelClusteringMode = 1;
+FTKBankGen.DuplicateGanged = True;
+FTKBankGen.GangedPatternRecognition = False;
+
+FTKBankGen.PT_THRESHOLD = 0.8;#GeV
+FTKBankGen.TRAIN_PDG = 13;#Traing samples particle ID  
+#FTKBankGen.NEvent = event;#event number
+FTKBankGen.NBanks = 64;
+FTKBankGen.BarrelOnly = False;
+FTKBankGen.rawMode = 1;
+FTKBankGen.UseIdentifierHash = True;
+
+FTKBankGen.par_c_max=0.0007;
+FTKBankGen.par_c_min=-0.0007;
+FTKBankGen.par_c_slices=250;
+
+FTKBankGen.par_phi_max=1;
+FTKBankGen.par_phi_min=-1;
+FTKBankGen.par_phi_slices=100;
+
+FTKBankGen.par_d0_max=2.2;
+FTKBankGen.par_d0_min=-2.2;
+FTKBankGen.par_d0_slices=250;
+
+FTKBankGen.par_z0_max=120;
+FTKBankGen.par_z0_min=-120;
+FTKBankGen.par_z0_slices=100;
+
+FTKBankGen.par_eta_max=3;
+FTKBankGen.par_eta_min=-3;
+FTKBankGen.par_eta_slices=100;
+
+alg += FTKBankGen  # 1 alg, named "MyNewPackage"
+
+#-----------------------------------------------------------------------------
+# save ROOT histograms and Tuple
+#-----------------------------------------------------------------------------
+#from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
+#Stream1 = AthenaPoolOutputStream( "Stream1" )
+#Stream1.OutputFile =   "SimplePoolFile_Complete.root"
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output = [ "MyNewPackage DATAFILE='testAug21.root' OPT='RECREATE'" ]
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKCachedBankGen.py b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKCachedBankGen.py
new file mode 100644
index 00000000000..ff3f5da387a
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKCachedBankGen.py
@@ -0,0 +1,91 @@
+#--------------------------------------------------------------
+# Full job is a list of algorithms
+#--------------------------------------------------------------
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+#--------------------------------------------------------------
+# Enable monitoring
+#--------------------------------------------------------------
+from PerfMonComps.PerfMonFlags import jobproperties
+jobproperties.PerfMonFlags.doSemiDetailedMonitoring = True
+
+from AthenaCommon.AppMgr import ToolSvc
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+
+#--------------------------------------------------------------
+# initialize algo(s)
+#--------------------------------------------------------------
+CachedBankGen = FTKCachedBankGenAlgo("CachedBankGen")
+
+
+#--------------------------------------------------------------
+# 
+#--------------------------------------------------------------
+from AthenaCommon.AppMgr import theApp
+theApp.EvtMax = 1 # Number of events to be processed
+
+from AthenaCommon.AppMgr import ServiceMgr
+
+from GaudiSvc.GaudiSvcConf import THistSvc
+ServiceMgr += THistSvc()
+
+ServiceMgr.THistSvc.Output += ["outputHisto DATAFILE='outputHisto.root' OPT='RECREATE'"]
+
+#--------------------------------------------------------------
+# Set output level threshold (DEBUG, INFO, WARNING, ERROR, FATAL)
+#--------------------------------------------------------------
+CachedBankGen.OutputLevel = DEBUG
+
+
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+
+# --- 'fixed arguments'
+
+# --- mandatory runArgs
+runArgsFromTrfMandatory = ['pmap_path', 'rmap_path', 'ssmapTSP_path', 'ssmapAM_path',
+                           'curreg','cursubreg','infile','outfile','IBLMode','hwmodeid_tsp']
+
+
+# --- Check that the arguments in the mandatory list are set
+for mandArg in runArgsFromTrfMandatory:
+    print "Seeking mandArg: " + mandArg
+    if not hasattr(runArgs, mandArg):
+        raise RuntimeError, 'Failed to find mandatory runtime argument for transform: ' + mandArg
+    else:
+        attr = getattr(runArgs, mandArg)
+        print "Setting mandArg: " + mandArg
+        setattr(CachedBankGen, mandArg, getattr(runArgs, mandArg))
+
+
+# --- optional arguments
+TSPBankGen.maxpatt = -1
+
+runArgsFromTrfOptional = { 'maxpatt': -1 # IBLMode, hwmodeid_ccache, hwmodeid_pcache
+                           }
+skipArgs = []
+
+# --- Set the PattBankGenRoot properties
+for runArgName in runArgsFromTrfOptional.keys():
+	print 'Setting FTKCachedBankGen argument'+runArgName
+	if runArgName in skipArgs:
+		print 'Skipping ' + runArgName
+		continue
+	if hasattr(runArgs, runArgName):
+		print "if " + runArgName
+		setattr(CachedBankGen, runArgName, getattr(runArgs, runArgName))
+	else:
+		print "else " + runArgName
+		setattr(CachedBankGen, runArgName, runArgsFromTrfOptional[runArgName])
+
+
+#--------------------------------------------------------------
+# Add algo
+#--------------------------------------------------------------
+alg += CachedBankGen
+
+#--------------------------------------------------------------
+
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKConstantGen.py b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKConstantGen.py
new file mode 100644
index 00000000000..3232e8a442d
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKConstantGen.py
@@ -0,0 +1,46 @@
+#-----------------------------------------------------------------------------
+# Athena imports
+#-----------------------------------------------------------------------------
+from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import theApp
+from AthenaCommon.AppMgr import ServiceMgr
+#import AthenaPoolCnvSvc.ReadAthenaPool
+
+from PerfMonComps.PerfMonFlags import jobproperties as pmjp
+pmjp.PerfMonFlags.doSemiDetailedMonitoring = True # to enable monitoring
+
+from AthenaCommon.AlgSequence import AlgSequence
+job = AlgSequence()
+
+from AthenaCommon.Logging import logging
+ftkLog = logging.getLogger('FTKConstantGen')
+
+# force the maximum number of events to 0
+theApp.EvtMax = 0 # -1 means all events
+
+import glob
+#-----------------------------------------------------------------------------
+# Algorithms
+#-----------------------------------------------------------------------------
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+FTKConstGenAlgo = FTKConstGenAlgo('FTKConstGenAlgo', OutputLevel = INFO)
+
+if not hasattr(runArgs, "genconst") :
+    setattr(runArgs, "genconst", True)
+FTKConstGenAlgo.genconst= runArgs.genconst
+
+FTKConstGenAlgo.nbank=runArgs.NBanks
+
+# if not hasattr(runArgs, "allregions") :
+#     setattr(runArgs, "allregions", False)
+# FTKConstGenAlgo.allregion = runArgs.allregions 
+
+if not hasattr(runArgs, "bankregion") :
+    setattr(runArgs, "bankregion", 0)
+FTKConstGenAlgo.region=runArgs.bankregion # if the previous option is True this line is not important
+
+FTKConstGenAlgo.merged_file_path=runArgs.inputFTKMatrixFile[0]
+#FTKConstGenAlgo.OutputFileName = runArgs.outputFTKGoodMatrixFile
+job += FTKConstGenAlgo
+#-----------------------------------------------------------------------------
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixMerge.py b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixMerge.py
new file mode 100644
index 00000000000..3684347fbce
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixMerge.py
@@ -0,0 +1,48 @@
+#-----------------------------------------------------------------------------
+# Athena imports
+#-----------------------------------------------------------------------------
+from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import theApp
+from AthenaCommon.AppMgr import ServiceMgr
+#import AthenaPoolCnvSvc.ReadAthenaPool
+
+from PerfMonComps.PerfMonFlags import jobproperties as pmjp
+pmjp.PerfMonFlags.doSemiDetailedMonitoring = True # to enable monitoring
+
+from AthenaCommon.AlgSequence import AlgSequence
+job = AlgSequence()
+
+from AthenaCommon.Logging import logging
+ftkLog = logging.getLogger('FTKMatrixMerge')
+
+# force the maximum number of events to 0
+theApp.EvtMax = 0 # -1 means all events
+
+import glob
+#-----------------------------------------------------------------------------
+# Algorithms
+#-----------------------------------------------------------------------------
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+FTKConstGenAlgo = FTKConstGenAlgo('FTKConstGenAlgo', OutputLevel = INFO)
+FTKConstGenAlgo.merging=True
+if not hasattr(runArgs, "genconst") :
+    setattr(runArgs, "genconst", False)
+FTKConstGenAlgo.genconst= runArgs.genconst
+FTKConstGenAlgo.nbank=runArgs.NBanks
+if not hasattr(runArgs, "allregions") :
+    setattr(runArgs, "allregions", False)
+FTKConstGenAlgo.allregion = runArgs.allregions 
+if not hasattr(runArgs, "bankregion") :
+    setattr(runArgs, "bankregion", 0)
+FTKConstGenAlgo.region=runArgs.bankregion # if the previous option is True this line is not important
+if hasattr(runArgs,'FTKMatrixFileRegEx') :
+    if hasattr(runArgs,'MaxInputFiles'):
+        FTKConstGenAlgo.file_path = glob.glob(runArgs.FTKMatrixFileRegEx)[:runArgs.MaxInputFiles]
+    else:
+        FTKConstGenAlgo.file_path = glob.glob(runArgs.FTKMatrixFileRegEx)
+else :
+  FTKConstGenAlgo.file_path=runArgs.inputFTKMatrixFile
+FTKConstGenAlgo.OutputFileName = runArgs.outputMergedFTKMatrixFile
+job += FTKConstGenAlgo
+#-----------------------------------------------------------------------------
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixReduction.py b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixReduction.py
new file mode 100644
index 00000000000..c5303250b7e
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKMatrixReduction.py
@@ -0,0 +1,59 @@
+#-----------------------------------------------------------------------------
+# Athena imports
+#-----------------------------------------------------------------------------
+from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import theApp
+from AthenaCommon.AppMgr import ServiceMgr
+#import AthenaPoolCnvSvc.ReadAthenaPool
+
+from PerfMonComps.PerfMonFlags import jobproperties as pmjp
+pmjp.PerfMonFlags.doSemiDetailedMonitoring = True # to enable monitoring
+
+from AthenaCommon.AlgSequence import AlgSequence
+job = AlgSequence()
+
+from AthenaCommon.Logging import logging
+ftkLog = logging.getLogger('FTKMatrixReduction')
+
+# force the maximum number of events to 0
+theApp.EvtMax = 0 # -1 means all events
+
+import glob
+#-----------------------------------------------------------------------------
+# Algorithms
+#-----------------------------------------------------------------------------
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+FTKConstGenAlgo = FTKConstGenAlgo('FTKConstGenAlgo', OutputLevel = INFO)
+
+if not hasattr(runArgs, "eightLayer") :
+    setattr(runArgs, "eightLayer", True)
+FTKConstGenAlgo.eightLayer= runArgs.eightLayer
+
+FTKConstGenAlgo.nbank=runArgs.NBanks
+
+if not hasattr(runArgs, "allregions") :
+    setattr(runArgs, "allregions", False)
+FTKConstGenAlgo.allregion = runArgs.allregions 
+
+if not hasattr(runArgs, "bankregion") :
+    setattr(runArgs, "bankregion", 0)
+FTKConstGenAlgo.region=runArgs.bankregion # if the previous option is True this line is not important
+
+from PyJobTransforms.trfUtils import findFile
+
+pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/' + runArgs.pmap_12L)# 12L pmap for OfflineID
+#pmap_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_12LiblHW.pmap')# 12L pmap for HWlikeID
+print "Using PMAP 12L:", pmap_path
+
+pmap_8L_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/' + runArgs.pmap_8L)# 8L pmap for OfflineID
+#pmap_8L_path = findFile(os.environ['DATAPATH'], 'ftk_configuration/map_files/raw_8LcIbl123.pmap')# 8L pmap for HWlikeID
+print "Using PMAP 8L :", pmap_8L_path
+
+FTKConstGenAlgo.pmap_path=pmap_path;
+FTKConstGenAlgo.pmap_8L_path=pmap_8L_path;
+
+FTKConstGenAlgo.LayerChange_path=runArgs.inputFTKMatrixFile[0]
+#FTKConstGenAlgo.OutputFileName = runArgs.outputFTKGoodMatrixFile
+job += FTKConstGenAlgo
+#-----------------------------------------------------------------------------
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKPattBankGenRoot.py b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKPattBankGenRoot.py
new file mode 100644
index 00000000000..e05a401ccb7
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/share/skeleton.FTKPattBankGenRoot.py
@@ -0,0 +1,192 @@
+#--------------------------------------------------------------
+# Full job is a list of algorithms
+#--------------------------------------------------------------
+from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import theApp
+from AthenaCommon.AppMgr import ServiceMgr
+
+#--------------------------------------------------------------
+# Enable monitoring
+#--------------------------------------------------------------
+from PerfMonComps.PerfMonFlags import jobproperties
+jobproperties.PerfMonFlags.doSemiDetailedMonitoring = True
+
+from AthenaCommon.AlgSequence import AlgSequence
+alg = AlgSequence()
+
+from AthenaCommon.Logging import logging
+ftkLog = logging.getLogger('FTKPattGen')
+
+
+from AthenaCommon.AppMgr import ToolSvc
+from TrigFTKBankGen.TrigFTKBankGenConf import *
+
+
+## uncommet the following lines of DEBUG_BEAMSPOT is selected
+#IOVDbSvc = Service("IOVDbSvc")
+#IOVDbSvc.GlobalTag="OFLCOND-SDR-BS14T-IBL-CORR-06-02"
+#import MagFieldServices.SetupField
+
+
+#--------------------------------------------------------------
+# initialize algo(s)
+#--------------------------------------------------------------
+PattBankGenRoot = FTKPattGenRootAlgo("FTKPattGenRootAlgo")
+
+
+#--------------------------------------------------------------
+# 
+#--------------------------------------------------------------
+
+
+# Number of events to be processed
+#theApp.EvtMax = 1
+if hasattr(runArgs,"maxEvents") :
+	theApp.EvtMax = runArgs.maxEvents
+else :
+	theApp.EvtMax = 1
+
+
+#from GaudiSvc.GaudiSvcConf import THistSvc
+from AthenaServices.AthenaServicesConf import AtRanluxGenSvc
+
+ServiceMgr += AtRanluxGenSvc()
+rndstream="RANDOM"
+seed1=1
+seed2=1
+if hasattr(runArgs, 'rndStreamName'):
+        rndstream=runArgs.rndStreamName
+
+if hasattr(runArgs, 'seed'):
+        seed1=runArgs.seed
+
+if hasattr(runArgs, 'seed2'):
+        seed2=runArgs.seed2
+
+ServiceMgr.AtRanluxGenSvc.Seeds= [ rndstream+" %d %d" %(seed1,seed2) ]
+
+ServiceMgr.AtRanluxGenSvc.EventReseeding = False
+
+#ServiceMgr += THistSvc()
+#ServiceMgr.THistSvc.Output += ["outputHisto DATAFILE='outputHisto.root' OPT='RECREATE'"]
+
+#--------------------------------------------------------------
+# Set output level threshold (DEBUG, INFO, WARNING, ERROR, FATAL)
+#--------------------------------------------------------------
+
+# Output level for PattBankGenAlgo only
+PattBankGenRoot.OutputLevel = INFO
+
+
+
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+
+# --- mandatory runArgs
+#runArgsFromTrfMandatory = ['fitconstants_path', 'slices_path', 'sectors_path']
+runArgsFromTrfMandatory = ['pmap_path', 'rmap_path', 'ssmap_path','curreg','hwmodeid','trials','IBLMode',
+			   'fitconsts', 'slices', 'sectors']
+
+# Maps' path
+from PyJobTransforms.trfUtils import findFile
+import os.path
+
+# pmap
+if hasattr(runArgs, 'pmap_path'):
+	if os.path.exists(runArgs.pmap_path):
+		PattBankGenRoot.pmap_path = runArgs.pmap_path
+	else:
+		print "Cannot find file: "+runArgs.pmap_path
+		raise RuntimeError, "RMAP path seems not to exist. Abort"
+else:
+	raise RuntimeError, "PMAP was not set. Abort"
+
+# rmap
+if hasattr(runArgs, 'rmap_path'):
+	if os.path.exists(runArgs.rmap_path):
+		PattBankGenRoot.rmap_path = runArgs.rmap_path
+	else:
+		print "Cannot find file: "+runArgs.rmap_path
+		raise RuntimeError, "RMAP path seems not to exist. Abort"
+else:
+	raise RuntimeError, "RMAP was not set. Abort"
+
+# ssmap
+if hasattr(runArgs, 'ssmap_path'):
+	if os.path.exists(runArgs.ssmap_path):
+		print "ssmap_path " + runArgs.ssmap_path
+		PattBankGenRoot.ssmap_path = runArgs.ssmap_path
+	else:
+		print "Cannot find file: "+runArgs.ssmap_path
+		raise RuntimeError, "SSMAP path seems not to exist. Abort."
+else:
+	raise RuntimeError, "SSMAP was not set. Abort"
+
+
+# --- Check that the arguments in the mandatory list are set
+for mandArg in runArgsFromTrfMandatory:
+	print "mandArg " + mandArg
+	if not hasattr(runArgs, mandArg):
+		raise RuntimeError, 'Failed to find mandatory runtime argument for transform: ' + mandArg
+	else:
+		attr = getattr(runArgs, mandArg)
+		print attr
+		setattr(PattBankGenRoot, mandArg, getattr(runArgs, mandArg))
+
+
+# --- optional arguments
+runArgsFromTrfOptional = {'curreg': 32,
+#			  'seed': 0,                     #Seed of random generator
+                          'rndStreamName': "RANDOM",    #athena name of random stream 
+#			  'smear': True, 
+			  'hwmodeid': 0,
+			  'ModuleLUTPath': "",
+			  'IBLMode': 1,
+                          'FixEndcapL0' : 0,
+			  'pconst_overlap': 2,
+			  'trials': 100000,              # Number of trials of the trackInvertion function
+			  'phi_min': -999,
+			  'phi_max': 999,
+			  'c_min': -0.00104,
+			  'c_max': 0.00104,
+			  'd0_min': -999,
+			  'd0_max': 999,
+			  'z0_min': -999,
+			  'z0_max': 999,
+			  'eta_min': -999,
+			  'eta_max': 999,
+			  'd0_alpha': 0.0,
+			  'beamspotX': 0.0,
+			  'beamspotY': 0.0,
+                          'ITkMode': False,
+                          'keep7of8': 0,
+                          'tolerance7of8': 0.1,
+
+                          'OutputFile': "patterns.root",  # output file (should end with .root)
+                          'ModuleGeometryFile': "none",
+                          'sectorSelection' : 1
+			  }
+skipArgs = []
+
+
+# --- Set the PattBankGenRoot properties
+for runArgName in runArgsFromTrfOptional.keys():
+	print 'Setting PattBankGenRoot argument'+runArgName
+	if runArgName in skipArgs:
+		print 'Skipping ' + runArgName
+		continue
+
+	if hasattr(runArgs, runArgName):
+		print "if " + runArgName
+		setattr(PattBankGenRoot, runArgName, getattr(runArgs, runArgName))
+	else:
+		print "else " + runArgName
+		setattr(PattBankGenRoot, runArgName, runArgsFromTrfOptional[runArgName])
+
+
+alg += PattBankGenRoot
+
+#==============================================================
+# End of job options file
+#==============================================================
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/FTKBankGenAlgo.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKBankGenAlgo.cxx
new file mode 100644
index 00000000000..2524898f61d
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKBankGenAlgo.cxx
@@ -0,0 +1,1460 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigFTKBankGen/FTKBankGenAlgo.h"
+#include "TrigFTKBankGen/FTKPattKDTree.h"
+#include "TrigFTKSim/FTKSetup.h"
+#include "TrigFTKSim/FTK_SGHitInput.h"
+#include "TrigFTKSim/atlClustering.h"
+
+#include "GaudiKernel/MsgStream.h"
+
+#include "GaudiKernel/ITHistSvc.h"
+#include "TH1.h"
+#include "TH2.h"
+#include "TTree.h"
+#include "TROOT.h"
+
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <cmath>
+#include <stdio.h>
+#include <math.h>
+
+// SET THIS TO 1 TO ENABLE VERBOSE DEBUGGING OF REGION ASSIGNMENT
+#define RMAP_DEBUG_PRINT 0
+
+#define NEWTOWERASSIGN
+
+using namespace std;
+/////////////////////////////////////////////////////////////////////////////
+FTKBankGenAlgo::FTKBankGenAlgo(const std::string& name, ISvcLocator* pSvcLocator) :
+  AthAlgorithm(name, pSvcLocator), 
+  m_hitInputTool("FTK_SGHitInput/FTK_SGHitInput"),
+  m_nevent(0),m_nbanks(0), m_nsubregions(1),  
+  m_verbosity(0),
+  m_BarrelOnly(false),
+  m_rawMode(1),
+  m_IBLMode(1), // flag to change the IBLMode
+  m_fixEndcapL0(false), 
+  m_ITkMode(false), // flag to use ITk geometry
+  m_pmap(0x0),
+  m_rmap(0x0),
+  m_pmap_path(),
+  m_rmap_path(),
+  m_Clustering(true),
+  m_SaveClusterContent(false),
+  m_DiagClustering(true),
+  m_SctClustering(false),
+  m_PixelClusteringMode(1),
+  m_DuplicateGanged(true),
+  m_GangedPatternRecognition(false),
+  m_UseIdentifierHash(false),
+  m_sector_dir_path(),
+  m_gcon_dir_path(),
+  m_par_c_min(0),
+  m_par_c_slices(0),
+  m_par_phi_max(0),
+  m_par_phi_min(0),
+  m_par_phi_slices(0),
+  m_par_d0_max(0),
+  m_par_d0_min(0),
+  m_par_d0_slices(0),
+  m_par_z0_max(0),
+  m_par_z0_min(0),
+  m_par_z0_slices(0),
+  m_par_eta_max(0),
+  m_par_eta_min(0),
+  m_par_eta_slices(0),
+  m_PT_THRESHOLD(0),
+  m_TRAIN_PDG(0),
+  m_constant(0),
+  m_const_test_mode(false),
+  m_compsecbitmask()
+{
+  declareProperty("NEvent",m_nevent);
+  // number of banks
+  declareProperty("NBanks",m_nbanks);
+  declareProperty("NSubRegions",m_nsubregions);
+  declareProperty("BarrelOnly",m_BarrelOnly);
+  declareProperty("rawMode",m_rawMode);
+  declareProperty("pmap_path",m_pmap_path);
+  declareProperty("rmap_path",m_rmap_path);
+  declareProperty("const_test_mode",m_const_test_mode);
+  declareProperty("sector_dir_path",m_sector_dir_path);
+  declareProperty("gcon_dir_path",m_gcon_dir_path);
+  // slice option
+  declareProperty("par_c_max",m_par_c_max);
+  declareProperty("par_c_min",m_par_c_min);
+  declareProperty("par_c_slices",m_par_c_slices);
+  declareProperty("par_phi_max",m_par_phi_max);
+  declareProperty("par_phi_min",m_par_phi_min);
+  declareProperty("par_phi_slices",m_par_phi_slices);
+  declareProperty("par_d0_max",m_par_d0_max);
+  declareProperty("par_d0_min",m_par_d0_min);
+  declareProperty("par_d0_slices",m_par_d0_slices);
+  declareProperty("par_z0_max",m_par_z0_max);
+  declareProperty("par_z0_min",m_par_z0_min);
+  declareProperty("par_z0_slices",m_par_z0_slices);
+  declareProperty("par_eta_max",m_par_eta_max);
+  declareProperty("par_eta_min",m_par_eta_min);
+  declareProperty("par_eta_slices",m_par_eta_slices);
+  // slice option
+  declareProperty("PT_THRESHOLD",m_PT_THRESHOLD);
+  declareProperty("TRAIN_PDG",m_TRAIN_PDG);
+
+  //clustering option 20140219
+  declareProperty("Clustering",m_Clustering);
+  declareProperty("SaveClusterContent",m_SaveClusterContent);
+  declareProperty("DiagClustering",m_DiagClustering);
+  declareProperty("SctClustering",m_SctClustering);
+  declareProperty("PixelClusteringMode",m_PixelClusteringMode);
+  declareProperty("DuplicateGanged",m_DuplicateGanged);
+  declareProperty("GangedPatternRecognition",m_GangedPatternRecognition);
+
+  declareProperty("UseIdentifierHash",m_UseIdentifierHash);
+
+  declareProperty("IBLMode",m_IBLMode);
+  declareProperty("FixEndcapL0",m_fixEndcapL0);
+  declareProperty("ITkMode",m_ITkMode);
+}
+FTKBankGenAlgo::~FTKBankGenAlgo()
+{
+  if (m_pmap) delete m_pmap;
+  if (m_rmap) delete m_rmap;
+
+  delete [] m_constant;
+
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+StatusCode FTKBankGenAlgo::initialize(){
+  // get the reference to the central standalone instance
+  FTKSetup &ftkset = FTKSetup::getFTKSetup();
+
+  // Set Option (temporaly way for checking standalone ver. -> should change to better way) //
+  ftkset.setBarrelOnly(m_BarrelOnly);
+  ftkset.setRawMode(m_rawMode);
+  ftkset.setVerbosity(m_verbosity);
+  ftkset.setIBLMode(m_IBLMode);
+  ftkset.setfixEndcapL0(m_fixEndcapL0);
+  ftkset.setITkMode(m_ITkMode);
+
+  MsgStream log(msgSvc(), name());
+  log << MSG::INFO << "FTKBankGenAlgo::initialize()" << endmsg;
+
+  StatusCode sc;
+  sc = service("THistSvc", m_thistSvc);
+  if(sc.isFailure()) {
+    log << MSG::FATAL <<("Unable to retrieve THistSvc")<< endmsg;
+    return StatusCode::FAILURE;
+  }
+  
+  sc = m_hitInputTool.retrieve();
+  if (sc.isFailure()) {
+    log << MSG::FATAL << "Could not retrieve FTK_SGHitInput tool" << endmsg;
+    return StatusCode::FAILURE;
+  }
+  else {
+    log << MSG::INFO << "Setting FTK_SGHitInput tool" << endmsg;
+  }
+
+  log << MSG::INFO << "Read the logical layer definitions" << endmsg;
+  // Look for the main plane-map
+  if (m_pmap_path.empty()) {
+    log << MSG::FATAL << "Main plane map definition missing" << endmsg;
+    return StatusCode::FAILURE;
+  }
+  else {
+    m_pmap = new FTKPlaneMap(m_pmap_path.c_str());
+    if (!(*m_pmap)) {
+      log << MSG::FATAL << "Error using plane map: " << m_pmap_path << endmsg;
+      return StatusCode::FAILURE;
+    }
+  }
+
+  // set the pmap address to FTKDataInput to use in processEvent
+  FTKDataInput *hitinput = m_hitInputTool->reference();
+  hitinput->setPlaneMaps(m_pmap,0x0);
+ 
+  // Create the region map objects
+  if (m_rmap_path.empty()) {
+    log << MSG::FATAL << "Region map file needed" << endmsg;
+    return StatusCode::FAILURE;
+  }
+  else {
+    log << MSG::INFO << "Creating region map" << endmsg;
+    m_rmap = new FTKRegionMap(m_pmap, m_rmap_path.c_str());
+    if (!(*m_rmap)) {
+      log << MSG::FATAL << "Error creating region map from: " << m_rmap_path.c_str() << endmsg;
+      return StatusCode::FAILURE;
+    }
+  }
+
+  /* initialize the clustering global variables, decalred in TrigFTKSim/atlClusteringLNF.h */
+  //hitinput->setClustering(m_Clustering);
+  hitinput->setPixelClusteringMode(m_PixelClusteringMode);
+  hitinput->setSctClustering(m_SctClustering);
+  /*
+  SAVE_CLUSTER_CONTENT = m_SaveClusterContent;
+  DIAG_CLUSTERING = m_DiagClustering;
+  //  SCT_CLUSTERING = m_SctClustering;
+  PIXEL_CLUSTERING_MODE = m_PixelClusteringMode;
+  DUPLICATE_GANGED = m_DuplicateGanged;
+  GANGED_PATTERN_RECOGNITION = m_GangedPatternRecognition;
+*/
+  hitinput->init();
+
+  // get detector configurations
+  m_nplanes=m_pmap->getNPlanes();
+  m_nregions = m_rmap->getNumRegions();  
+  TotalDim=m_pmap->getTotalDim();
+  initPattTree(m_nbanks, m_nplanes+1,TotalDim);
+  
+  log << MSG::INFO << "get dim" << TotalDim <<endmsg;
+    
+  TotalDim2=TotalDim*TotalDim;
+  
+  m_sectorID =(int *) calloc(m_nplanes,sizeof(int));
+  m_hashID =(int *) calloc(m_nplanes,sizeof(int));
+  m_tmpVec = (double *) calloc(TotalDim,sizeof(double));    
+  m_tmpxC = (double *) calloc(TotalDim,sizeof(double));
+  m_tmpxD = (double *) calloc(TotalDim,sizeof(double));
+  m_tmpxPhi  = (double *) calloc(TotalDim,sizeof(double));
+  m_tmpxCoto  =  (double *) calloc(TotalDim,sizeof(double));
+  m_tmpxZ  =(double *) calloc(TotalDim,sizeof(double));
+  m_tmpcovx = (double *) calloc(TotalDim*TotalDim,sizeof(double));
+
+  npatterns =(int *) calloc(m_nbanks,sizeof(int));
+  ntracks =(int *) calloc(m_nbanks,sizeof(int));
+    
+  p_ss = (int *) calloc(m_nplanes+1,sizeof(int));
+  p_hashss = (int *) calloc(m_nplanes+1,sizeof(int));
+  tmphitc = (double *) calloc(TotalDim,sizeof(double));    
+  tmpxC = (double *) calloc(TotalDim,sizeof(double));
+  tmpxD = (double *) calloc(TotalDim,sizeof(double));
+  tmpxPhi  = (double *) calloc(TotalDim,sizeof(double));
+  tmpxCoto  =  (double *) calloc(TotalDim,sizeof(double));
+  tmpxZ  =(double *) calloc(TotalDim,sizeof(double));
+  tmpcovx = (double *) calloc(TotalDim*TotalDim,sizeof(double));
+  for(int i=0;i<m_nbanks;i++){
+    ntracks[i]=0;
+    npatterns[i]=0;
+  }
+
+  if(m_const_test_mode){
+
+    count_pass_filter = 0;
+    count_match = 0;
+    coverage = 0;
+
+    strcpy(c_sector_dir_path, m_sector_dir_path.c_str());
+    strcpy(c_gcon_dir_path, m_gcon_dir_path.c_str());
+
+    //sector file
+    //TODO tmp_SSID.resize(m_nplanes); to check
+    tmp_ssID = (int *) calloc(m_nplanes+1,sizeof(int));
+    tmp_hashID = (int *) calloc(m_nplanes+1,sizeof(int));
+
+    for(int ibank=0;ibank<m_nbanks;ibank++){
+      sprintf(str_sector_file_name,"%s/sectors_raw_%dL_reg%d.patt",c_sector_dir_path,m_nplanes,ibank);
+      
+      ifstream sector_file(str_sector_file_name);
+      if(!sector_file){
+    	log << MSG::FATAL << str_sector_file_name << " not found!!" << endmsg;
+	return StatusCode::FAILURE;
+      }
+
+      //read header
+      for(int i=0;i<2;i++)sector_file >> header[i];
+    
+      while(!sector_file.eof()){
+
+	addPattReturnCode=0;      
+
+    	//read sector
+    	sector_file >> tmp_sectorID;
+      
+    	for(int i=0;i<m_nplanes;i++) sector_file >> tmp_ssID[i];
+	tmp_ssID[m_nplanes]=tmp_sectorID;
+    	sector_file >> dummy;
+    	sector_file >> dummy;
+	
+	int_c.clear();
+	int_phi.clear();
+	int_d0.clear();
+	int_z0.clear();
+	int_eta.clear();
+
+	int_c.resize(1);
+	int_phi.resize(1);
+	int_d0.resize(1);
+	int_z0.resize(1);
+	int_eta.resize(1);
+  
+	Mtmp.nhit=1;
+	addPattReturnCode=addKDPattern(ibank, m_const_test_mode, tmp_ssID, tmp_hashID, 1,Mtmp,tmphitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+				       int_c,int_phi,int_d0,int_z0,int_eta);
+
+      }//sector_file.eof
+      log << MSG::INFO << "sector:region " << ibank << " loaded." << endmsg;
+      
+    }
+
+    m_constant = new FTKConstantBank*[m_nbanks];
+    for (int i=0;i<m_nbanks;++i)m_constant[i]= 0;
+
+    //setBank function
+    for(int ibank=0;ibank<m_nbanks;ibank++){
+      sprintf(str_gcon_file_name,"%s/corrgen_raw_%dL_reg%d.gcon",c_gcon_dir_path,m_nplanes,ibank);
+      ifstream gcon_file(str_gcon_file_name);
+      if(!gcon_file){
+      	log << MSG::FATAL << str_gcon_file_name << " not found!!" << endmsg;
+	return StatusCode::FAILURE;
+      }
+
+      gcon_path = str_gcon_file_name;
+      log << MSG::INFO << "gcon file =  " << gcon_path << endmsg;
+      m_constant[ibank] = new FTKConstantBank(TotalDim,gcon_path.c_str());
+      log << MSG::INFO << "constant:region " << ibank << " loaded." << endmsg;
+    }
+
+    base_trk.setNCoords(TotalDim);
+    base_trk.setNPlanes(m_nplanes);
+    base_trk.setNMissing(0);
+
+    char filename_coverage[30];
+    sprintf(filename_coverage,"coverage.txt");
+    file_coverage.open(filename_coverage);
+
+    char filename_truthpar[30];
+    sprintf(filename_truthpar,"truthpar.txt");
+    file_truthpar.open(filename_truthpar);
+
+    char filename_recpar[30];
+    sprintf(filename_recpar,"recpar.txt");
+    file_recpar.open(filename_recpar);
+
+    char filename_resolution[30];
+    sprintf(filename_resolution,"resolution.txt");
+    file_resolution.open(filename_resolution);
+
+    file_resolution << "dC dD dPhi dZ0 dCoto Chi2" << endl;
+
+  }else{//const test mode
+
+    char filename[30];
+  
+    sprintf(filename,"matrix_%dL_%dDim.root",m_nplanes,TotalDim);
+  
+    file = new TFile(filename,"recreate");
+    gROOT->cd();
+  
+    char name[5];
+    char title[20];
+
+    for(int i = 0; i < m_nregions; ++i){
+    
+      sprintf(name,"am%d",i);
+      sprintf(title,"Ambank %d para",i); 
+
+      m_tree[i] = new TTree(name, title);
+    }
+
+    m_montree = new TTree("montree", "monitor tree");
+    m_montree->Branch("monval", m_monval, "m_monval[100]/l");
+    for(int i=0;i<100;i++){
+      m_monval[i]=0;
+    }// for i                                                                    
+
+    m_slicetree=new TTree("slice", "slice para");
+  
+    for(int i = 0; i < m_nregions; ++i){
+      m_tree[i]->Branch("ndim",&TotalDim,"ndim/I");
+      m_tree[i]->Branch("ndim2",&TotalDim2,"ndim2/I");
+      m_tree[i]->Branch("Vec", m_tmpVec,"Vec[ndim]/D");
+      m_tree[i]->Branch("nplanes",&m_nplanes,"nplanes/I");
+      m_tree[i]->Branch("sectorID", m_sectorID,"sectorID[nplanes]/I");
+      m_tree[i]->Branch("hashID", m_hashID,"hashID[nplanes]/I");
+      m_tree[i]->Branch("nhit", &m_nhit,"nhit/F");
+      m_tree[i]->Branch("tmpC", &m_tmpC,"tmpC/D");
+      m_tree[i]->Branch("tmpD", &m_tmpD,"tmpD/D");
+      m_tree[i]->Branch("tmpPhi", &m_tmpPhi,"tmpPhi/D");
+      m_tree[i]->Branch("tmpCoto", &m_tmpCoto,"tmpCoto/D");
+      m_tree[i]->Branch("tmpZ", &m_tmpZ,"tmpZ/D");
+      m_tree[i]->Branch("tmpxC", m_tmpxC,"tmpxC[ndim]/D");
+      m_tree[i]->Branch("tmpxD", m_tmpxD,"tmpxD[ndim]/D");
+      m_tree[i]->Branch("tmpxPhi", m_tmpxPhi,"tmpxPhi[ndim]/D");
+      m_tree[i]->Branch("tmpxCoto", m_tmpxCoto,"tmpxCoto[ndim]/D");
+      m_tree[i]->Branch("tmpxZ", m_tmpxZ,"tmpxZ[ndim]/D");
+      m_tree[i]->Branch("tmpcovx", m_tmpcovx,"tmpcovx[ndim2]/D");
+    
+      m_intc= new std::vector<short>;
+      m_intphi= new std::vector<short>;
+      m_intd0= new std::vector<short>;
+      m_intz0= new std::vector<short>;
+      m_inteta= new std::vector<short>;
+
+      m_tree[i]->Branch("tmpintc", &m_intc);
+      m_tree[i]->Branch("tmpintphi", &m_intphi);
+      m_tree[i]->Branch("tmpintd0", &m_intd0);
+      m_tree[i]->Branch("tmpintz0", &m_intz0);
+      m_tree[i]->Branch("tmpinteta", &m_inteta);
+          
+      m_tree[i]->Print();
+    }
+    m_slicetree->Branch("c_max",&m_par_c_max);
+    m_slicetree->Branch("phi_max",&m_par_phi_max);
+    m_slicetree->Branch("d0_max",&m_par_d0_max);
+    m_slicetree->Branch("z0_max",&m_par_z0_max);
+    m_slicetree->Branch("eta_max",&m_par_eta_max);
+  
+    m_slicetree->Branch("c_min",&m_par_c_min);
+    m_slicetree->Branch("phi_min",&m_par_phi_min);
+    m_slicetree->Branch("d0_min",&m_par_d0_min);
+    m_slicetree->Branch("z0_min",&m_par_z0_min);
+    m_slicetree->Branch("eta_min",&m_par_eta_min);
+  
+    m_slicetree->Branch("c_slices",&m_par_c_slices);
+    m_slicetree->Branch("phi_slices",&m_par_phi_slices);
+    m_slicetree->Branch("d0_slices",&m_par_d0_slices);
+    m_slicetree->Branch("z0_slices",&m_par_z0_slices); 
+    m_slicetree->Branch("eta_slices",&m_par_eta_slices);
+
+  }//const test mode
+
+  return StatusCode::SUCCESS;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+StatusCode FTKBankGenAlgo::execute() {
+  MsgStream log(msgSvc(), name());
+  log << MSG::INFO << "FTKBankGenAlgo::execute() start" << endmsg;
+  
+  // clear array of variables
+  m_hitInputTool->reference()->clearRawHits(); 
+  m_hitInputTool->reference()->clearTruthTrack();  
+  hitslist.clear();
+  m_trainingtracks.clear();
+
+  int_c.clear();
+  int_phi.clear();
+  int_d0.clear();
+  int_z0.clear();
+  int_eta.clear();
+  
+  // event difinitions
+  doPattgen = true;
+  GoodTrack = true;
+  
+  /////////////////////////////////////////////////////
+  // track validation part (copied from th_rd.c)    //
+  ////////////////////////////////////////////////////
+  //hits & truth track is get from SGHitInput
+  m_hitInputTool->reference()->readData();  
+  truth_track = m_hitInputTool->reference()->getTruthTrack();
+
+  // clustering hits
+  m_hitInputTool->reference()->processEvent(false);
+  nhits =  m_hitInputTool->reference()->getNHits(); 
+  hitslist = m_hitInputTool->reference()->getHitsList();
+
+  nmuon = 0;
+  eta = 0;
+  pt =0;
+  truth_phi = 0;
+
+  // reset the hits of maps
+  m_maphits.clear();
+
+  for(unsigned int i=0;i<truth_track.size();++i){
+    c = truth_track[i].getQ()/(sqrt(truth_track[i].getPX()*truth_track[i].getPX()+truth_track[i].getPY()*truth_track[i].getPY()));
+    c=(c)/2.;
+    pt = TMath::Sqrt(truth_track[i].getPX()*truth_track[i].getPX()+truth_track[i].getPY()*truth_track[i].getPY())/1000;
+    eta = TMath::ASinH(truth_track[i].getPZ()/TMath::Sqrt(truth_track[i].getPX()*truth_track[i].getPX()+truth_track[i].getPY()*truth_track[i].getPY()));
+    truth_phi = TMath::ATan2(truth_track[i].getPY(),truth_track[i].getPX());
+    log << MSG::DEBUG << "i pt = "<<i<< " " <<pt<<endmsg;
+    log << MSG::DEBUG << "i c = "<<i<< " " <<c<<endmsg;
+    log << MSG::DEBUG << "i eta = "<<i<<" "<<eta<<endmsg;
+    log << MSG::DEBUG << "i phi = "<<i<<" "<<truth_phi<<endmsg;
+    log << MSG::DEBUG << "i pdgcode = "<<i<<" "<<truth_track[i].getPDGCode()<<endmsg;
+
+    m_monval[0]++;
+    if(truth_track[i].getBarcode() >= 1000000 || (abs(truth_track[i].getPDGCode())!=m_TRAIN_PDG))continue;
+
+    m_monval[1]++;
+
+    //    if(truth_track[i].getBarcode() >= 100000)continue;
+    if(pt>m_PT_THRESHOLD && abs(truth_track[i].getPDGCode())==m_TRAIN_PDG){//GoodTrack!!
+      // add the track to the list of good tracks
+      m_trainingtracks.push_back(truth_track[i]);
+      // prepare the entry in the map of hits
+      m_maphits[truth_track[i].getBarcode()] = vector<FTKHit>();
+
+      m_monval[2]++;
+    }
+  }
+
+  // get the number of tracks
+  nmuon = m_trainingtracks.size();
+
+  for(unsigned int j=0;j<hitslist.size();j++){ // loop over the hits
+    // get the predominant barcode for the current hit
+    int hitbarcode = hitslist[j].getTruth().best_barcode();
+    // check if the barcode is associated to a good muon
+    map<int, vector<FTKHit> >::iterator ilist = m_maphits.find(hitbarcode);
+
+    // skip the hits if not associated to a good truth tracks
+    if(ilist==m_maphits.end()) continue;
+
+    // add hit to the list
+    (*ilist).second.push_back(hitslist[j]);
+  } // end loop over the hits
+
+  if(0==nmuon) GoodTrack=false;
+
+  ///////////////////////////////////////////////////////
+  //////   make sector                             //////
+  ///////////////////////////////////////////////////////
+  
+  if(!GoodTrack){log << MSG::DEBUG << " bad track event " << endmsg;}
+  else{ // there are good tracks
+
+    //****************************************************************//
+    //****   pattgen copied and modfied from  TrigFTKLib      ********// 
+    //***************************************************************//
+
+
+    for(int nTruth=0;nTruth<nmuon;nTruth++){ // loop over the tracks
+      m_monval[3]++;
+      doPattgen = true;
+
+      int sector=0,sector_HW=0,cur_plane=0,cur_sector=0,cur_sector_HW=0;
+      int phi_mod=0,eta_mod=0,section=0;
+      int cur_phi=0,cur_eta=0,cur_section=0;
+      int sdiff=0,ediff=0,pdiff=0;
+      int rmax=0;
+
+      std::vector<filterSecHit> sechit(m_nplanes);//initialize truth by truth
+      for (int ilayer=0; ilayer!=m_nplanes; ++ilayer) {
+        // enforce the initialization of the sechit elements
+        sechit[ilayer].count = 0; // it is enough to just set the layer counter to 0
+      }
+      // this block works on the hit related to this tracks
+      FTKTruthTrack &curtrack = m_trainingtracks[nTruth];
+
+      // list of hits associated to the current truth track
+      vector<FTKHit> &curhitlist = m_maphits[curtrack.getBarcode()]; // it has to exist, at least has empty list
+      for(unsigned int i=0;i<curhitlist.size();++i){ // loop over the hits
+
+        // point to the current
+        FTKHit &curhit = curhitlist[i];
+#define FHIT sechit[curhit.getPlane()] //filtered hit for the current logical layer
+
+        if(doPattgen && GoodTrack){//don't make pattern
+           //int plane= curhit.getPlane();
+           sector = curhit.getSector();
+           sector_HW = curhit.getIdentifierHash();
+
+          phi_mod = curhit.getPhiModule();
+
+          if(curhit.getIsBarrel()){//section and eta definition
+            eta_mod = curhit.getEtaModule();
+            section =0;
+          }else{
+            eta_mod = curhit.getEtaModule();
+            section = curhit.getSection();
+          }
+
+          log << MSG::DEBUG << "sector, phi_mod, eta_mod, section = " <<sector << " " << phi_mod << " " << eta_mod << " " << section << endmsg;
+
+          if(0==FHIT.count){ // initialize
+            FHIT.count++;
+            cur_plane = curhit.getPlane();
+            cur_sector = curhit.getSector();
+            cur_sector_HW = curhit.getIdentifierHash();
+
+            // copy the original hit, this should be the only required information
+            FHIT.originalhit =  curhit;
+
+            FHIT.plane = cur_plane;
+            FHIT.sector = cur_sector;
+            FHIT.sector_HW = cur_sector_HW;
+            FHIT.ndim = curhit.getDim();
+            FHIT.CSide = curhit.getCSide();
+            FHIT.ASide = curhit.getASide();
+
+            if(2==FHIT.ndim){
+              FHIT.dimx = curhit.getCoord()[0];
+              FHIT.dimy = curhit.getCoord()[1];
+            }else if(1==FHIT.ndim){
+              FHIT.dimx = curhit.getCoord()[0];
+              FHIT.dimy = 0;
+            }
+          }else if(1==FHIT.count){ // the position was already filled with an hit
+            cur_plane = FHIT.originalhit.getPlane();
+            cur_sector = FHIT.originalhit.getSector();
+            cur_phi = FHIT.originalhit.getPhiModule();;
+            cur_eta = FHIT.originalhit.getEtaModule();;
+            cur_section = FHIT.originalhit.getSection();
+
+            // check for overlap
+            FHIT.count++;
+
+            if(sector == cur_sector){
+              //	    if(sector_ref==FHIT.sector_ref){
+              log << MSG::DEBUG << "Two hits on same module, exiting filterHitsSec " <<endmsg;
+              doPattgen = false;
+	      m_monval[4]++;
+            }else {//not same sector
+              sdiff = cur_section-section;
+              pdiff = cur_phi-phi_mod;
+              ediff = cur_eta-eta_mod;
+
+              if(ediff==0 && sdiff==0){
+                section=cur_section;
+                //TODO why is this not a global declaration?
+                if(8==m_nregions){
+                  rmax=m_rmap->getRegionMapItem(m_nregions-1,curhit.getPlane(),section).getMax();
+                }else if(64==m_nregions || 32==m_nregions){
+                  rmax=m_rmap->getRegionMapItem(m_nregions-1,curhit.getPlane(),section).getTotMod();
+                }
+
+                if(pdiff == 1 || pdiff== -rmax ){
+                  // Do noting ,we got the right one
+                }else if(pdiff == -1 ||pdiff == rmax ){
+                  //swap hits, the new one is the right one
+                  FHIT.originalhit =  curhit;
+                  FHIT.sector =sector;
+                  FHIT.sector_HW =sector_HW;
+                  FHIT.ndim = curhit.getDim();
+                  if(2==FHIT.ndim){
+                    FHIT.dimx = curhit.getCoord()[0];
+                    FHIT.dimy = curhit.getCoord()[1];
+                  }else if(1==FHIT.ndim){
+                    FHIT.dimx = curhit.getCoord()[0];
+                    FHIT.dimy = 0;
+                  }
+                }else{
+                  //Not overlap, free and exit
+                  log << MSG::DEBUG << "Hits are too far away in phi, exiting filterHitsSec " <<endmsg;
+                  doPattgen =false;
+		  m_monval[5]++;
+                }
+
+                // sector overlap is a perfectly reasonable situation with forward disks
+                // eta and phi will differ in general in this case
+                // Take the lower-z hit preferentially (right thing to do? d0/pT tradeoff)
+                // But something fishy is going on if we've got two hits on the same disk.
+              }
+              else if (sdiff!=0){//ediff sdiff orig
+                // If one is barrel and one endcap, it's definitely OK, take the barrel hit
+                if(m_pmap->getPlane(curhit.getPlane(),cur_section).getIsEndcap()
+                    && !m_pmap->getPlane(curhit.getPlane(),section).getIsEndcap()){
+                  // Swap hits, the new one is the right one
+                  FHIT.originalhit = curhit;
+                  FHIT.sector=sector;
+                  FHIT.sector_HW=sector_HW;
+                  FHIT.ndim=curhit.getDim();
+                  if(2==FHIT.ndim){
+                    FHIT.dimx=curhit.getCoord()[0];
+                    FHIT.dimy=curhit.getCoord()[1];
+                  }else if(1==FHIT.ndim){
+                    FHIT.dimx=curhit.getCoord()[0];
+                    FHIT.dimy=0;
+                  }
+                  log << MSG::DEBUG << " Swapping to use barrel hit " <<endmsg;
+                }
+                else if (!m_pmap->getPlane(curhit.getPlane(),cur_section).getIsEndcap()
+                    && m_pmap->getPlane(curhit.getPlane(),cur_section).getIsEndcap()){
+
+                  log << MSG::DEBUG << " Fine, we've got the barrel hit " <<endmsg;
+                  // Two endcap hits : same disk: discard
+                }
+                else if (m_pmap->getPlane(curhit.getPlane(),cur_section).getPDisk()
+                    ==m_pmap->getPlane(curhit.getPlane(),section).getPDisk() ){
+                  log << MSG::DEBUG << "Two modules hit in same physical disk" <<m_pmap->getPlane(curhit.getPlane(),cur_section).getPDisk()<< "exiting filterHitsSec " <<endmsg;
+                  doPattgen=false;
+		  m_monval[6]++;
+                  //Two endcap hits on opposite sides makes no sense: discard
+                }
+                else if((FHIT.CSide && curhit.getASide())
+                    || (FHIT.ASide && curhit.getCSide())){
+
+                  log << MSG::DEBUG << " Endcap disks on opposite sides hit, exiting filterHitsSec " <<endmsg;
+
+                  doPattgen=false;
+		  m_monval[7]++;
+                  //Two endcap hits on same side: different disks: take the lower-z
+                }
+                else {
+
+                  log << MSG::DEBUG << " Keeping the lower-z of the two disks hit " <<endmsg;
+                  //If CURHIT disk is a lower number, we've got the right one
+
+                  if(m_pmap->getPlane(curhit.getPlane(),cur_section).getPDisk()
+                      >m_pmap->getPlane(curhit.getPlane(),section).getPDisk()){
+                    // Swap hits, the new one is the right one
+                    FHIT.originalhit = curhit;
+                    FHIT.sector=sector;
+                    FHIT.sector_HW=sector_HW;
+                    FHIT.ndim=curhit.getDim();
+                    if(2==FHIT.ndim){
+                      FHIT.dimx=curhit.getCoord()[0];
+                      FHIT.dimy=curhit.getCoord()[1];
+                    }else if(1==FHIT.ndim){
+                      FHIT.dimx=curhit.getCoord()[0];
+                      FHIT.dimy=0;
+                    }
+                  }
+                  log << MSG::DEBUG << "\t\t\t...Kept " <<endmsg;
+                }
+
+
+              }
+              else{//ediff != 0: Different eta idx is no good, free and exit
+                log << MSG::DEBUG << "Hits are in different eta, exiting filterHitsSec " <<endmsg;
+                doPattgen=false;
+		m_monval[8]++;
+              }
+            }//not same sector
+          }
+          else if(FHIT.count>1) {
+
+            log << MSG::DEBUG << "Too many hits on a plane, exiting filterHitsSec " <<endmsg;
+            doPattgen = false;
+	    m_monval[9]++;
+          } // How many do hits exist in same plane.
+          log << MSG::DEBUG << " gethittype "<<FHIT.hittype <<endmsg;
+          log << MSG::DEBUG << " getdim "<<FHIT.ndim <<endmsg;
+        }//do pattgen
+      } // end loop over the hits
+
+      curhitlist.clear();
+
+      if(doPattgen && GoodTrack){
+        for(int i=0;i<m_nplanes;++i){
+          log << MSG::DEBUG << "getsector pre " <<sechit[i].sector<< endmsg;
+          if(0==sechit[i].count){
+            doPattgen = false;
+	    m_monval[10]++;
+            log << MSG::DEBUG << "Plane"<< i <<" has no hits, exiting filterHitsSec "<< endmsg;
+
+          }
+        }
+      }
+
+      /////////////////////////////////////////////////////////
+      /////            which regios?(old format)        /////
+      ///////////////////////////////////////////////////////
+
+      int nregion=-999;
+      if(!doPattgen){
+        log << MSG::INFO << "don't generate sector table " <<endmsg;
+        nregion=-999;
+      } else {
+
+        // use sectorID as Identifier Hash
+	/* tkaji
+        if (m_UseIdentifierHash){
+          for(int i=0;i<m_nplanes;++i) {
+            log << MSG::DEBUG << "getsector " <<sechit[i].sector_HW<< endmsg;
+            p_ss[i]=sechit[i].sector_HW;
+          }
+        }
+        else {
+          for(int i=0;i<m_nplanes;++i) {
+            log << MSG::DEBUG << "getsector " <<sechit[i].sector<< endmsg;
+            p_ss[i]=sechit[i].sector;
+          }
+        }
+	*/
+
+	for(int i=0;i<m_nplanes;i++){
+	  p_hashss[i] = sechit[i].sector_HW;
+	  p_ss[i] = sechit[i].sector;
+	}
+
+        p_hashss[m_nplanes]=0;//for sectors, we set it to zero.
+        p_ss[m_nplanes]=0;//for sectors, we set it to zero.
+	
+#ifdef NEWTOWERASSIGN
+        // the sector is set by the first hit, the following hits can only confirm it
+        m_compsecbitmask.set();// all towers are possible
+
+        for(int i=0;i<m_nplanes;++i) { // loop over the layer
+          for (int itwr=0;itwr!=m_nbanks;++itwr) { // loop over hte towers
+            if (!m_rmap->isHitInRegion(sechit[i].originalhit,itwr))
+              m_compsecbitmask.set(itwr,false); // switch off an impossible sector
+          } // end loop over the towers
+        } // end loop over the layers
+
+        /* At the end of the previous loop the compsecbitmask object is 1 for
+         * every tower that *is* compatible with the given sector, is 0 for
+         * every tower that *isn't* compatible with the given sector
+         */
+        nregion = -999;
+        for (int itwr=0;itwr!=m_nbanks;++itwr) { // loop over the towers
+          if (m_compsecbitmask.test(itwr)) { // good tower block
+            // when the previous test is true the current tower is compatible with the sector
+	    if (m_ITkMode) {
+	      // for now just give preference to lowest region index for simplicity
+	      nregion = itwr;
+	      break;
+	    }
+            else if (m_nbanks==64) { // 64 towers block case
+              if (nregion==-999) {
+                // initialize the tower selection variable
+                nregion = itwr;
+              }
+              else {
+                // assumes 64 towers in 4 barrels, with 16 phi slices each
+                const int curphi(itwr%16);
+                const int refphi(nregion%16);
+                const int cureta(itwr/16);
+                const int refeta(nregion/16);
+                if (cureta!=refeta){
+                  // central towers are preferred
+                  if (refeta==0&&cureta==1) nregion = itwr;
+                  else if (refeta==3&&cureta==2) nregion = itwr;
+                  // in case both towers are central, the last layer decides
+                  else if (refeta==1&&cureta==2&&sechit[m_nplanes-1].originalhit.getEtaCode()>=6) nregion = itwr;
+                }
+                else {
+                  /* If the the current and reference towers are in the same eta
+                   * region, the greater index is preferred. The exception is to
+                   * consider refphi=0 preferred to curphi=15, to restore the simmetry
+                   */
+                  if (refphi==0 && curphi==15) continue; // nothing to do
+                  else nregion = itwr; // normal case
+                }
+              }
+            }
+            else if (m_nbanks==32) { // 32 towers block case
+              if (nregion==-999) {
+                // initialize the tower selection variable
+                nregion = itwr;
+              }
+              else {
+                // assumes 64 towers in 4 barrels, with 16 phi slices each
+                const int curphi(itwr%8);
+                const int refphi(nregion%8);
+                const int cureta(itwr/8);
+                const int refeta(nregion/8);
+                if (cureta!=refeta){
+                  // central towers are preferred
+                  if (refeta==0&&cureta==1) nregion = itwr;
+                  else if (refeta==3&&cureta==2) nregion = itwr;
+                  // in case both towers are central, the last layer decides
+                  else if (refeta==1&&cureta==2&&sechit[m_nplanes-1].originalhit.getEtaCode()>=6) nregion = itwr;
+                }
+                else {
+                  /* If the the current and reference towers are in the same eta
+                   * region, the greater index is preferred. The exception is to
+                   * consider refphi=0 preferred to curphi=7, to restore the simmetry
+                   */
+                  if (refphi==0 && curphi==7) continue; // nothing to do
+                  else nregion = itwr; // normal case
+                }
+              }
+            }
+            else if (m_nbanks==8) {
+              nregion = itwr; // the bank with the lowest index wins
+              break;
+            }
+            else {
+              cerr << "Error" << endl;
+              return StatusCode::FAILURE;
+            }
+          } // end good tower block
+        }
+#else // OLD TOWER ASSIGNEMENT CODE, DEPRECATED
+#include "TrigFTKBankGen/decodeEtacode.h"
+        if(m_nbanks==8){
+
+          std::vector<int>result(m_nplanes);
+
+          for(int i=0;i<m_nplanes;++i) {
+            //	    log << MSG::DEBUG << "getsector " <<sechit[i].sector<< endmsg;
+            log << MSG::DEBUG << "getsector " <<sechit[i].sector<< endmsg;
+            log << MSG::DEBUG << "getplane " <<sechit[i].plane<< endmsg;
+
+            p_ss[m_nplanes]=0;//for sectors, we set it to zero.
+
+            //	    int phi = sechit[i].sector/1000;
+            int phi = sechit[i].sector/1000;
+            result[i]=0;
+
+            if(sechit[i].sector%1000<20){//section and eta definition
+              //	    if(sechit[i].sector_ref%1000<20){//section and eta definition
+              section=0;
+            }else{
+              section=sechit[i].sector%10;
+              //	      section=sechit[i].sector_ref%10;
+            }
+
+            //	 Region 0 is special: some negative phi indices
+            if((phi <= m_rmap->getRegionMapItem(0,i,section).getMax() ||
+                phi >= m_rmap->getRegionMapItem(m_nregions-1,i,section).getTotMod() +
+                m_rmap->getRegionMapItem(0,i,section).getMin()+1 )) {
+              result[i] += 1;
+            }
+
+            /* Check other regions */
+            for(int k = 1; k < m_nregions; ++k) {
+              if((phi <= m_rmap->getRegionMapItem(k,i,section).getMax()) &&
+                  (phi >= m_rmap->getRegionMapItem(k,i,section).getMin())) {
+                result[i] += 1 << k;
+              }
+            }
+          } // loop over planes
+
+          int region = result[0];
+
+          for(int k=1; k<m_nplanes; ++k)
+            region &= result[k];
+
+          if(!region){
+            nregion =-999;
+          }else if(region == (1 << (m_nbanks-1))+1){// 7 and 0, return 0
+            nregion=0;
+          }else{
+            nregion=0;
+            while((region >> nregion) != 1)
+              ++nregion;
+          }
+          result.clear();
+        }else if(m_nbanks==64){
+
+          ////////////////////////////////////////////
+          /////////  region for 64-tower  ////////////
+          ////////////////////////////////////////////
+
+          for(int i=0;i<m_nplanes;++i) {
+            log << MSG::DEBUG << "getsector " <<sechit[i].sector<< endmsg;
+            p_ss[i]=sechit[i].sector;
+            // log << MSG::DEBUG << "getsector " <<sechit[i].sector_ref<< endmsg;
+            // p_ss[i]=sechit[i].sector_ref;
+          }
+          p_ss[m_nplanes]=0;//for sectors, we set it to zero.
+
+          ////////////////////////////////////////////////////////
+          //   Eta (analogues to whichRegionEta of rmap_rd.c)   //
+          ////////////////////////////////////////////////////////
+
+          static int pM_eta[]={2,3,5,7};
+          static int *result_eta;
+          static int allocated_eta = 0;
+          int region_eta = -1;
+          // total tower id's where we switch tower-eta
+          const int t0 = 0;
+          const int t1 = m_rmap->getNumRegionsPhi()*1;
+          const int t2 = m_rmap->getNumRegionsPhi()*2;
+          const int t3 = m_rmap->getNumRegionsPhi()*3;
+          int i_eta,itower_eta;
+          int aside,cside,etamod;
+          int found_eta;
+          int tower1_OK;
+
+          if(!allocated_eta) {
+            allocated_eta = 1;
+            if((result_eta = (int *)calloc(m_nplanes,sizeof(int))) == NULL)
+              log << MSG::ERROR << "whichRegionAlt: could not allocate result space" << endmsg;
+          }
+          for(i_eta=0;i_eta<m_nplanes;++i_eta)
+            result_eta[i_eta] = 1;
+
+          for(i_eta=0;i_eta<m_nplanes;++i_eta) {
+            cside = CSIDE_INT(p_ss[i_eta]);
+            aside = ASIDE_INT(p_ss[i_eta]);
+            // endcap C-side
+            if(cside==1) {
+              result_eta[i_eta] *= pM_eta[0];
+              log << MSG::DEBUG << " ->eta: "<< sechit[i_eta].sector <<" - - -" << endmsg;
+              //	      log << MSG::DEBUG << " ->eta: "<< sechit[i_eta].sector_ref <<" - - -" << endmsg;
+            }
+            // endcap A-side
+            else if(aside==1) {
+              result_eta[i_eta] *= pM_eta[3];
+              log << MSG::DEBUG << " ->eta: - - - " <<sechit[i_eta].sector<< endmsg;
+              //	      log << MSG::DEBUG << " ->eta: - - - " <<sechit[i_eta].sector_ref<< endmsg;
+            }
+            // barrel
+            else {
+              etamod = ETA_MOD_INT(p_ss[i_eta]);
+              if(etamod >= m_rmap->getRegionMapItem(t0,i_eta,0).getEtaMin() && etamod<=m_rmap->getRegionMapItem(t0,i_eta,0).getEtaMax() ) {
+                result_eta[i_eta] *= pM_eta[0];
+              }
+              if(etamod >= m_rmap->getRegionMapItem(t1,i_eta,0).getEtaMin() && etamod<=m_rmap->getRegionMapItem(t1,i_eta,0).getEtaMax() ) {
+                result_eta[i_eta] *= pM_eta[1];
+              }
+              if(etamod >= m_rmap->getRegionMapItem(t2,i_eta,0).getEtaMin() && etamod<=m_rmap->getRegionMapItem(t2,i_eta,0).getEtaMax() ) {
+                result_eta[i_eta] *= pM_eta[2];
+              }
+              if(etamod >= m_rmap->getRegionMapItem(t3,i_eta,0).getEtaMin() && etamod<=m_rmap->getRegionMapItem(t3,i_eta,0).getEtaMax() ) {
+                result_eta[i_eta] *= pM_eta[3];
+              }
+            }
+          }
+
+          // now find intersection of result_eta[i_eta] arrays for all i
+          tower1_OK = 0;
+          for(itower_eta=0;itower_eta<4;itower_eta++) {
+            found_eta=1;
+            for(i_eta=0;i_eta<m_nplanes;++i_eta) {
+              if((result_eta[i_eta]%pM_eta[itower_eta])!=0) {found_eta = 0; break; }
+            }
+            if(found_eta==1) {
+              if(itower_eta==1) {
+                tower1_OK = 1;
+                continue;
+              }
+              else {
+                if(itower_eta==2 && tower1_OK==1) {
+                  if( ETA_MOD_INT(p_ss[m_nplanes-1]) <= 5 ) region_eta=1; else region_eta=2;
+                  break;
+                }
+                region_eta = itower_eta;
+                break;
+              }
+            }
+            else if(itower_eta==2 && tower1_OK==1){
+              region_eta=1;
+              break;
+            }
+          }
+
+          /////////////
+          //   Phi   //
+          /////////////
+
+          static int pM_phi[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
+          static int *result_phi;
+          static int allocated_phi = 0;
+          const int debug = RMAP_DEBUG_PRINT;
+          int region_phi = -1;
+          int i_phi,itow,itower_phi;
+          int phi,section_phi;
+          int found_phi;
+          int tow0_OK;
+          int j;
+
+          if(-1 != region_eta){//eta is defined
+            if(!allocated_phi) {
+              allocated_phi = 1;
+              if((result_phi = (int *)calloc(m_nplanes,sizeof(int))) == NULL)
+                log << MSG::ERROR << "whichRegionAlt: could not allocate result space" << endmsg;
+            }
+            for(i_phi=0;i_phi<m_nplanes;++i_phi)
+              result_phi[i_phi] = 1;
+
+            for(i_phi=0;i_phi<m_nplanes;++i_phi) {
+              phi = PHI_MOD_INT(p_ss[i_phi]);
+              section_phi = SECTION_INT(p_ss[i_phi]);
+              for(itow=0;itow<m_rmap->getNumRegionsPhi();itow++) {
+                itower_phi = m_rmap->getNumRegionsPhi()*region_eta + itow;
+                if( m_rmap->getRegionMapItem(itower_phi,i_phi,section_phi).getPhiMin() <= m_rmap->getRegionMapItem(itower_phi,i_phi,section_phi).getPhiMax() ) {
+                  if(phi >= m_rmap->getRegionMapItem(itower_phi,i_phi,section_phi).getPhiMin() && phi <= m_rmap->getRegionMapItem(itower_phi,i_phi,section_phi).getPhiMax() ) {
+                    result_phi[i_phi] *= pM_phi[itow];
+                  }
+                } else {
+                  if(phi >= m_rmap->getRegionMapItem(itower_phi,i_phi,section_phi).getPhiMin() || phi <= m_rmap->getRegionMapItem(itower_phi,i_phi,section_phi).getPhiMax() ) {
+                    result_phi[i_phi] *= pM_phi[itow];
+                  }
+                }
+
+              }
+              if(debug) {
+                printf(" ->phi: ");
+                for(j=0;j<m_rmap->getNumRegionsPhi();j++) printf("%s ", ((result_phi[i_phi]%pM_phi[j]==0)?"x":"-"));
+                printf("  phi=%d section=%d",phi,section_phi);
+                printf("\n");
+              }
+            }
+
+            // now find intersection of result_phi[i_phi] arrays for all i
+            tow0_OK = 1;
+            for(i_phi=0;i_phi<m_nplanes;++i_phi) {
+              if((result_phi[i_phi]%pM_phi[0])!=0) { tow0_OK = 0; break; }
+            }
+
+            for(itow=m_rmap->getNumRegionsPhi()-1;itow>=0;itow--) {
+              found_phi=1;
+              for(i_phi=0;i_phi<m_nplanes;++i_phi) {
+                if((result_phi[i_phi]%pM_phi[itow])!=0) {found_phi = 0; break; }
+              }
+              if(found_phi==1) {
+                if(itow==m_rmap->getNumRegionsPhi()-1 && tow0_OK==1) {
+                  region_phi = 0;
+                  break;
+                }
+                else {
+                  region_phi = itow;
+                  break;
+                }
+              }
+            }
+
+          }//eta is defined
+
+          /////////////////////
+          //  which region?? //
+          /////////////////////
+
+          if(region_eta==-1) {
+            nregion = -999;
+            log << MSG::DEBUG <<" bad eta!!!" <<endmsg;
+          }else if(region_phi==-1) {
+            nregion = -999;
+            log << MSG::DEBUG <<" bad phi!!!" <<endmsg;
+          } else {
+            nregion = region_eta * m_rmap->getNumRegionsPhi() + region_phi;
+          }
+        }//nbanks == 64
+#endif // END OLD TOWER ASSIGNEMENT CODE BLOCK
+      }//do pattgen
+
+      //cout << "REGION " << nregion << endl;
+
+      //ConstGenTest: check coverage
+      if(m_const_test_mode) {
+        addPattReturnCode=-1;
+        if(-999!=nregion){
+
+          count_pass_filter++;
+
+          int_c.resize(1);
+          int_phi.resize(1);
+          int_d0.resize(1);
+          int_z0.resize(1);
+          int_eta.resize(1);
+
+          Mtmp.nhit=5;
+          p_ss[m_nplanes]=std::numeric_limits<int>::max();
+          p_hashss[m_nplanes]=std::numeric_limits<int>::max();
+
+          addPattReturnCode=addKDPattern(nregion, m_const_test_mode, p_ss,p_hashss, 1,Mtmp,tmphitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+                                         int_c,int_phi,int_d0,int_z0,int_eta);
+
+          if(-1!=addPattReturnCode){//find sector
+            count_match++;
+            the_sectorID = addPattReturnCode;
+          }
+        }
+
+        coverage = double(count_match)/double(count_pass_filter);
+        log << MSG::INFO <<" count_pass_filter count_match= "<< count_pass_filter << " " << count_match <<endmsg;
+        log << MSG::INFO <<" coverage= "<< coverage <<endmsg;
+      }//const test mode
+
+
+      ///////////////////////////////////////////////////////////////////////////////
+      /////////////                   corrgen part                  ////////////////
+      //////////////////////////////////////////////////////////////////////////////
+      if(doPattgen==true){
+	m_monval[11]++;
+
+        int npixel=0,nsct=0;
+
+        ///////geopar.c
+        // This updated by JAA for new code to calculate d0
+        d = curtrack.getD0();
+        z0 =curtrack.getZ();
+
+        x0 = curtrack.getX() -(curtrack.getQ())*(curtrack.getPY()) ;
+        y0 = curtrack.getY() +(curtrack.getQ())*(curtrack.getPX()) ;
+        c = curtrack.getQ()/(sqrt(curtrack.getPX()*curtrack.getPX()+curtrack.getPY()*curtrack.getPY()));
+        c=(c)/2.;
+        phi = atan2(-x0*fabs(curtrack.getQ())/(curtrack.getQ()),y0*fabs(curtrack.getQ())/(curtrack.getQ()));
+        coto = curtrack.getPZ()/sqrt(curtrack.getPX()*curtrack.getPX()+curtrack.getPY()*curtrack.getPY());
+
+        // // //d = - 1/((c)*2.) + sqrt(x0*x0+y0*y0)*fabs(c)/(c);
+
+        // // //d0 is the distance of beam spot
+        // // double a,b;
+        // // //for NOMINAL
+        // // double beam_x=0;
+        // // double beam_y=0;
+        // //for data
+        // //     double beam_x=-0.324;
+        // //     double beam_y=0.628;
+        // double tmp_x = curtrack.getX() - beam_x;
+        // double tmp_y = curtrack.getY() - beam_y;
+
+        // a=curtrack.getPY()/curtrack.getPX();
+        // b=curtrack.getY()-a*curtrack.getX();
+        // d=fabs(-1*a*beam_x + beam_y - b )/sqrt(a*a + 1);
+
+        // if(tmp_x*curtrack.getPY() - tmp_y*curtrack.getPX() >= 0  ){
+        //   d = -1*d;
+        // }
+
+        ////////////////////////////////////////////////////////
+        ///////  slice file part           ////////////////////
+        ////////////////////////////////////////////////////////
+        int_c.resize(1);
+        int_phi.resize(1);
+        int_d0.resize(1);
+        int_z0.resize(1);
+        int_eta.resize(1);
+
+        int_c[0]=  (c-m_par_c_min)*m_par_c_slices/(m_par_c_max-m_par_c_min);
+        int_phi[0]=(phi-m_par_phi_min*M_PI)*m_par_phi_slices/((m_par_phi_max-m_par_phi_min)*M_PI);
+        int_d0[0]=(d-m_par_d0_min)*m_par_d0_slices/(m_par_d0_max-m_par_d0_min);
+        int_z0[0]=(z0-m_par_z0_min)*m_par_z0_slices/(m_par_z0_max-m_par_z0_min);
+        int_eta[0]=(coto-sinh(m_par_eta_min))*m_par_eta_slices/(sinh(m_par_eta_max)-sinh(m_par_eta_min));
+
+        log << MSG::DEBUG << "check 38 int region ntruth c d0 phi z0 coto = " << nregion << " " << nTruth << " " << int_c[0] << " " << int_d0[0] << " " << int_phi[0] << " " << int_z0[0] << " " << int_eta[0] << endmsg;
+
+        ////////////////////////////////// slice file part end
+
+        Mtmp.C=c;
+        Mtmp.D=d;
+        Mtmp.Coto=coto;
+        Mtmp.Z=z0;
+
+        // region = 3,4,5 (default). Testing: add in region 6!
+        if(!m_const_test_mode){
+          if(8==m_nbanks){
+            if (nregion>=3 && nregion <= 5) {
+              while(phi<0) phi += 2*M_PI;
+            }
+          }else if(64==m_nbanks){
+            if( nregion==9 || nregion==10 || nregion==25 || nregion==26 || nregion==41 || nregion==42 || nregion==57 || nregion==58 ) {
+              while(phi<0) phi += 2*M_PI;
+            }
+          }else if(32==m_nbanks){
+	    if( nregion%8==4 || nregion%8==5 ){
+	      if(phi<0) phi += 2*M_PI;
+	    }
+	  }
+	  if(m_ITkMode){
+	    // Play it safe for now since region map is not yet solidified
+	    while( phi < 0 ) phi += 2*M_PI;
+	  }
+        }
+
+        Mtmp.Phi=phi;
+
+        log << MSG::DEBUG << "check 35 region ntruth c d0 phi z0 coto = " << nregion << " " << nTruth << " " << c << " " << d << " " << phi << " " << z0 << " " << coto << endmsg;
+        
+        for(int i=0;i<m_nplanes;++i){
+          if(2==sechit[i].ndim){
+            npixel++;
+          }else if(1==sechit[i].ndim){
+            nsct++;
+          }
+        }
+        
+        log << MSG::DEBUG <<" npixel= "<<npixel<<"nsct= "<<nsct<<endmsg;
+
+        //check constant
+        if(m_const_test_mode){
+          if(-1!=addPattReturnCode){//if find same sector
+            base_trk.setSectorID(the_sectorID);
+
+            int ix,iy;
+
+            for(int j=0;j<npixel;j++){
+              ix = 2*j;
+              iy = 2*j+1;
+              base_trk.setCoord(ix,sechit[j].dimx);
+              base_trk.setCoord(iy,sechit[j].dimy);
+            }
+
+            for(int j=0;j<nsct;j++){
+              ix = 2*npixel+j;
+              base_trk.setCoord(ix,sechit[npixel+j].dimx);
+            }
+
+            FTKConstantBank *current_bank = m_constant[nregion];
+
+            if (!current_bank) { // no valid constants
+              log << MSG::FATAL << "*** Constants for region " << nregion << " - " << 1 << " don't exists" << endmsg;
+              return StatusCode::FAILURE;
+            }
+            /* Do the actual fit - see code in FTKConstantBank::linfit  */
+            current_bank->linfit(the_sectorID,base_trk);
+
+            log << MSG::INFO << "\t\t\tReconstructed parameters\n\t\t\t"	\
+                << 2.*base_trk.getHalfInvPt() << ' ' << base_trk.getIP()		\
+                << ' ' << base_trk.getPhi() << ' ' << base_trk.getZ0()	\
+                << ' ' << base_trk.getCotTheta() << endmsg;
+            log << MSG::INFO << "\t\t\tChi2 " << base_trk.getChi2() << endmsg;
+
+            file_resolution << Mtmp.C - 2.*base_trk.getHalfInvPt() << " " << Mtmp.D - base_trk.getIP() << " " << Mtmp.Phi - base_trk.getPhi() << " " << Mtmp.Z - base_trk.getZ0() << " " << Mtmp.Coto - base_trk.getCotTheta() << " " << base_trk.getChi2() << endl;
+            file_truthpar << nregion << " " << Mtmp.C << " " << Mtmp.D << " " << Mtmp.Phi << " " << Mtmp.Z << " " << Mtmp.Coto << endl;
+            file_recpar << nregion << " " << 2.*base_trk.getHalfInvPt() << " " << base_trk.getIP() << " " << base_trk.getPhi() << " " << base_trk.getZ0() << " " << base_trk.getCotTheta() << endl;
+
+          }
+
+        }else{
+          // add a sector to the map of sectors
+
+          std::vector<double> vec(TotalDim);
+
+          for(int j=0;j<npixel;j++){
+            vec[2*(j)]=sechit[j].dimx;
+            vec[2*(j)+1]=sechit[j].dimy;
+          }
+
+          for(int j=0;j<nsct;j++){
+            vec[2*npixel+j]=sechit[npixel+j].dimx;
+          }
+          log << MSG::DEBUG <<" x0= "<<x0<<"y0= "<<y0<<endmsg;
+          //	  log << MSG::DEBUG <<" c= "<<c<<"d= "<<d<<"phi= "<<phi<<"z0= "<<z0<<"coto= " <<coto<<endmsg;
+
+          for(int i=0;i<TotalDim;i++){
+            //      log << MSG::DEBUG <<" vec= "<<vec[i]<<endmsg;
+            tmphitc[i]=vec[i];
+
+            tmpxC[i]=Mtmp.C*vec[i];
+            tmpxD[i]=Mtmp.D*vec[i];
+            tmpxPhi[i]=Mtmp.Phi*vec[i];
+            tmpxCoto[i]=Mtmp.Coto*vec[i];
+            tmpxZ[i]=Mtmp.Z*vec[i];
+
+            for( int j = i; j < TotalDim; j++ ) {
+              tmpcovx[i*TotalDim+j]=vec[i]*vec[j];
+            }
+          }
+
+          if(-999!=nregion){
+	    m_monval[12]++;
+            Mtmp.nhit=1;
+
+            addPattReturnCode=addKDPattern(nregion, m_const_test_mode, p_ss, p_hashss, 1,
+                                           Mtmp,tmphitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+                                           int_c,int_phi,int_d0,int_z0,int_eta);
+
+            if(1==addPattReturnCode){
+              ++npatterns[nregion];
+            }else if(2==addPattReturnCode){
+              ++ntracks[nregion];
+            }
+            log << MSG::DEBUG <<"region is "<<nregion<<" #pattern= " <<npatterns[nregion]<<" #ntracks= "<<ntracks[nregion]<<endmsg;
+          }
+
+        }//const test mode
+        
+        //	sechit.clear();
+      }//do pattgen
+
+      sechit.clear();
+    }//nTruth
+  }//good track
+
+  log << MSG::INFO << "FTKBankGenAlgo::execute() end" << endmsg;
+  return StatusCode::SUCCESS;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+StatusCode FTKBankGenAlgo::finalize() {
+  MsgStream log(msgSvc(), name());
+  log << MSG::INFO << "finalize()" << endmsg;
+
+  ///////////////////////////////////////////
+  //sort function and tree                 //
+  //////////////////////////////////////////
+  if(m_const_test_mode){
+
+    file_coverage << "denominator numerator coverage" << endl;
+    file_coverage << count_pass_filter << " " << count_match << " " << coverage << endl;
+      
+    file_coverage.close();
+    file_resolution.close();
+
+  }else{//const test mode
+      
+    for(int b = 0; b<m_nbanks;b++){
+      log << MSG::DEBUG <<"bank= "<<b <<endmsg;
+      sortPatterns(b);
+      for(int i = 0; i<getNPatterns(b);i++){
+	m_intc->clear();
+	m_intphi->clear();
+	m_intd0->clear();
+	m_intz0->clear();
+	m_inteta->clear();	
+	
+	log << MSG::DEBUG <<"sector " <<i <<"  ";
+	for(int k=0;k<m_nplanes;k++){
+	  m_sectorID[k]=getPatternSS(b,i,k);
+	  m_hashID[k]=getPatthashID(b,i,k);
+	  log <<getPatternSS(b,i,k)<<" ";
+	}
+	log <<" "<<getPattNHits(b,i) <<endmsg;
+	m_nhit=getPattNHits(b,i);
+	m_tmpC=getPattC(b,i);
+	m_tmpD=getPattD(b,i);
+	m_tmpPhi=getPattPhi(b,i);
+	m_tmpCoto=getPattCoto(b,i);
+	m_tmpZ=getPattZ(b,i);
+	
+	for(int k=0;k<TotalDim;k++){
+	  m_tmpVec[k]=getPatthitc(b,i,k);
+	  m_tmpxC[k]=getPattxC(b,i,k);
+	  m_tmpxD[k]=getPattxD(b,i,k);
+	  m_tmpxPhi[k]=getPattxPhi(b,i,k);
+	  m_tmpxCoto[k]=getPattxCoto(b,i,k);
+	  m_tmpxZ[k]=getPattxZ(b,i,k);
+	  
+	  for(int l=0;l<TotalDim;l++){
+	    m_tmpcovx[k*TotalDim+l]=getPattcovx(b,i,k*TotalDim+l);
+	  }
+	  log <<getPatthitc(b,i,k)<<" ";
+	}
+	log <<"  "<<endmsg;
+			
+	log << MSG::DEBUG <<"b= "<< b <<" i= "<< i << endmsg;
+	log << MSG::DEBUG <<"C= "<< getPattC(b,i)   <<"D= "<< getPattD(b,i) <<"Phi= "<< getPattPhi(b,i)
+	    <<"Coto= "<< getPattCoto(b,i) <<"Z= "<< getPattZ(b,i)<<endmsg;
+	m_nsector=npatterns[b];
+	for(int m=0;m<m_nhit;m++){
+	  m_intc->push_back(getPattintc(b,i,m));
+	  m_intphi->push_back(getPattintphi(b,i,m));
+	  m_intd0->push_back(getPattintd0(b,i,m));
+	  m_intz0->push_back(getPattintz0(b,i,m));
+	  m_inteta->push_back(getPattinteta(b,i,m));
+	}
+	file->cd();
+	m_tree[b]->Fill();
+	gROOT->cd();
+      }
+
+      file->cd();
+      m_tree[b]->Write();   
+      gROOT->cd();
+      delete m_tree[b];
+      m_tree[b]=NULL;
+    }
+    
+    free(p_ss);
+    free(p_hashss);
+    free(tmphitc);
+    free(tmpxC);
+    free(tmpxD);
+    free(tmpxPhi);
+    free(tmpxCoto);
+    free(tmpxZ);
+    free(tmpcovx);
+
+    file->cd();
+    m_slicetree->Fill();
+    m_slicetree->Write();
+    m_montree->Fill();
+    m_montree->Write();
+    gROOT->cd();
+        
+    file->Close();
+    delete file;
+    file=NULL;
+    //  }
+  }//const test mode  
+  void finishPattTree();
+  // detach data input and output modules from ConfGen to avoid its deletion
+  return StatusCode::SUCCESS;
+}
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/FTKCachedBankGenAlgo.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKCachedBankGenAlgo.cxx
new file mode 100644
index 00000000000..44dd40b20ce
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKCachedBankGenAlgo.cxx
@@ -0,0 +1,355 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/FTKCachedBankGenAlgo.h"
+
+#include "GaudiKernel/MsgStream.h"
+
+#include "TrigFTKSim/FTK_CompressedAMBank.h"
+// #include "TrigFTKSim/ftk_dcap.h"
+#include "TrigFTKSim/FTKSetup.h"
+#include "TrigFTKSim/FTKRootFile.h"
+#include "TrigFTKSim/FTKSetup.h"
+
+#include <iostream>
+#include <fstream>
+
+#ifdef UNUSED
+#undef UNUSED
+#endif
+
+using namespace std;
+/////////////////////////////////////////////////////////////////////////////
+
+FTKCachedBankGenAlgo::FTKCachedBankGenAlgo(const std::string& name, ISvcLocator* pSvcLocator):
+   AthAlgorithm(name, pSvcLocator),
+   m_pmap_path(""),
+   m_rmap_path(""),
+   m_modulelut_path(""),
+   m_ssmapTSP_path(""),
+   m_ssmapAM_path(""),
+   m_in_bank_path(""),
+   m_in_cache_path(""),
+   m_out_ccache_path(""),
+   m_out_pcache_path(""),
+   m_hwmodeid_default(0), //! HWMODE input
+   m_hwmodeid_tspcc(-1),
+   m_hwmodeid_dc(-1),
+   m_curreg(0), //! Region of interest
+   m_nSubReg(0), //! number of subregions
+   m_iSubReg(0), //! current subregion
+   m_verbosity(1), //! for debugging
+   m_maxpatt(0), //! max. number of patterns
+   m_IBLMode(1), //! IBLMode
+   m_ITkMode(false), //! ITkMode
+   m_WhereToRun("initialize"),
+   m_flatFormat(0),
+   m_partitionList(""),
+   m_nSectorMax(-1),
+   m_nLamb(0),
+   m_ndcMax(-1),
+   m_wildcardPenalty(0)
+{
+   declareProperty("pmap_path", m_pmap_path);
+   declareProperty("rmap_path", m_rmap_path);
+   declareProperty("ModuleLUTPath",m_modulelut_path);
+   declareProperty("ssmapTSP_path", m_ssmapTSP_path);
+   declareProperty("ssmapAM_path", m_ssmapAM_path);
+
+   declareProperty("infile", m_in_bank_path);
+   declareProperty("cacheIn", m_in_cache_path);
+   declareProperty("pcacheOut", m_out_pcache_path);
+   declareProperty("ccacheOut", m_out_ccache_path);
+
+   declareProperty("sectordefHW0",m_sectordefHW0);
+   declareProperty("sectordefHW2",m_sectordefHW2);
+
+   declareProperty("hwmodeid_tspcc", m_hwmodeid_tspcc);
+   declareProperty("hwmodeid_dc", m_hwmodeid_dc);
+   declareProperty("curreg", m_curreg);
+   declareProperty("maxpatt", m_maxpatt);
+   declareProperty("verbosity", m_verbosity);
+   declareProperty("nSub", m_nSubReg);
+   declareProperty("iSub", m_iSubReg);
+   declareProperty("WhereToRun",m_WhereToRun);
+   declareProperty("IBLMode",m_IBLMode);
+   declareProperty("ITkMode",m_ITkMode);
+   declareProperty("hwmodeid_default",m_hwmodeid_default);
+   declareProperty("flatFormat",m_flatFormat);
+   declareProperty("partitionList",m_partitionList);
+   declareProperty("nSectorMax",m_nSectorMax);
+   declareProperty("nLamb",m_nLamb);
+   declareProperty("ndcMax",m_ndcMax);
+   declareProperty("ndcMaxPlane",m_ndcMaxPlane);
+   declareProperty("wildcardPenalty",m_wildcardPenalty);
+   declareProperty("wildcardPenaltyPlane",m_wildcardPenaltyPlane);
+
+   declareProperty("badmap_path",m_badmap_path);
+   declareProperty("badmap_path_for_hit",m_badmap_path2);
+}
+
+FTKCachedBankGenAlgo::~FTKCachedBankGenAlgo() {
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode FTKCachedBankGenAlgo::initialize() {
+
+   // where to run the pattern generation?
+   if ( !( TString(m_WhereToRun).BeginsWith("i",TString::kIgnoreCase) 
+	   || TString(m_WhereToRun).BeginsWith("f",TString::kIgnoreCase) 
+	   || TString(m_WhereToRun).BeginsWith("e",TString::kIgnoreCase)) ) {
+      ATH_MSG_WARNING("FTKPattGenRootAlgo() "<< "WhereToRun must start with 'i', 'e' or 'f' referring to the three steps of an athena algorithm (initialize, execute, finalize), but is: "<<m_WhereToRun);
+      return StatusCode::FAILURE;
+   }   
+
+
+   //ATH_MSG_INFO ("initialize()");
+   if ( TString(m_WhereToRun).BeginsWith("i",TString::kIgnoreCase) ) return RunCachedBankGenerator();
+   else return StatusCode::SUCCESS;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode FTKCachedBankGenAlgo::execute() {
+   //ATH_MSG_INFO ("execute()");
+   if ( TString(m_WhereToRun).BeginsWith("e",TString::kIgnoreCase) ) return RunCachedBankGenerator();
+   else return StatusCode::SUCCESS;
+}
+
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+StatusCode FTKCachedBankGenAlgo::finalize() {
+   //ATH_MSG_INFO ("finalize()");
+   if ( TString(m_WhereToRun).BeginsWith("f",TString::kIgnoreCase) ) return RunCachedBankGenerator();
+   else return StatusCode::SUCCESS;
+}
+ 
+ 
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode FTKCachedBankGenAlgo::RunCachedBankGenerator(){
+   // MsgStream log(msgSvc(), name());
+   ATH_MSG_INFO("initialize() Make FTKCachedBankGenAlgo object.");
+
+   // set HWMODEID
+   FTKSetup &ftkset = FTKSetup::getFTKSetup();
+   ftkset.setHWModeSS(m_hwmodeid_default);
+   // set IBL mode
+   ftkset.setIBLMode(m_IBLMode);
+   // set ITk mode
+   ftkset.setITkMode(m_ITkMode);
+   // set debugging level
+   ftkset.setVerbosity(m_verbosity);
+   // set ITK mode
+   ftkset.setITkMode(m_ITkMode);
+
+   ATH_MSG_INFO(" Setting IBLMode="+TString::Format("%d",m_IBLMode));
+   FTKSetup::getFTKSetup().setIBLMode(m_IBLMode);
+
+   // --- check input
+   if (m_ssmapAM_path.empty() ) {// check ss file
+      ATH_MSG_FATAL("No AM-SS configuration file given");
+      return StatusCode::FAILURE;
+   }
+   if (m_in_bank_path.empty() && m_in_cache_path.empty() ) {// check input file
+      ATH_MSG_FATAL("No input file given");
+      return StatusCode::FAILURE;
+   }
+   if (m_out_ccache_path.empty() &&  m_out_pcache_path.empty()) {// check ss file
+      ATH_MSG_FATAL("No output file given");
+      return StatusCode::FAILURE;
+   }
+
+   // --- get maps ---
+   const bool force_am_hashmap = false;
+   FTKPlaneMap* pmap = NULL;
+   FTKRegionMap* rmap = NULL;
+   FTKSSMap* ssmapTSP = NULL;
+
+
+   // check whether maps are available in TSP-pattern-file
+   ATH_MSG_INFO("Checking maps in input file.");
+   FTKSSMap* ssmapTSPPatt = 0;
+#ifdef UNUSED
+   if(!m_in_bank_path.empty()) {
+      ssmapTSPPatt=FTKSSMap::GetSSMapFromRootFile
+         (FTKRootFile::Instance()->OpenRootFileReadonly
+          (m_in_bank_path.c_str()),"TSP");
+      if ( ssmapTSPPatt->getIsOK() ) {
+         ATH_MSG_INFO("Using maps from input file.");
+         ssmapTSP = ssmapTSPPatt;
+         // pmap = ssmapTSP->getPlaneMap();
+         // rmap = ssmapTSP->getRegionMap();
+         pmap = ssmapTSP->getModifyablePlaneMap();
+            //FTKPlaneMap::GetPMapFromRootFile(FTKRootFile::Instance()->OpenRootFileReadonly(m_in_bank_path.c_str()));
+         rmap =ssmapTSP->getModifyableRegionMap();
+         //FTKRegionMap::GetRMapFromRootFile(FTKRootFile::Instance()->OpenRootFileReadonly(m_in_bank_path.c_str()));
+      } else {
+         ATH_MSG_INFO("No meta-tags (pmap, ssmap, etc.) found in input file.");
+      }
+   }
+#endif
+   if(ssmapTSPPatt) delete ssmapTSPPatt;
+   ssmapTSPPatt=0;
+
+   // cross checks
+   if ( !ssmapTSP ) {
+      if (m_pmap_path.empty()) { // check pmap file
+	 ATH_MSG_FATAL("Main plane map definition missing");
+	 return StatusCode::FAILURE;
+      } else {
+	 // --- Create the pmap file object
+	 ATH_MSG_INFO("initialize() Make FTKPlaneMap.");
+	 pmap = new FTKPlaneMap(m_pmap_path.c_str());
+	 if (!(*pmap)) {
+	    ATH_MSG_FATAL("Error using plane map: "+m_pmap_path);
+	    return StatusCode::FAILURE;
+	 }
+      }
+      if (m_rmap_path.empty()) { // check rmap file
+	 ATH_MSG_FATAL("Region map file needed");
+	 return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("initialize() Make FTKRegionMap.");
+      rmap = new FTKRegionMap(pmap, m_rmap_path.c_str());
+
+      if (m_ssmapTSP_path.empty() ) {// check ss file
+	 ATH_MSG_FATAL("No TSP-SS configuration file given");
+	 return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("initialize() Make FTKSSMapTSP.");
+      ssmapTSP = new FTKSSMap(rmap, m_ssmapTSP_path.c_str(), force_am_hashmap);
+   } else {
+      // cross check maps
+      if ( !m_pmap_path.empty() && !m_rmap_path.empty() && !m_ssmapTSP_path.empty() ) { // check pmap file
+	 // --- Create the pmap file object
+	 FTKPlaneMap* pmap2 = new FTKPlaneMap(m_pmap_path.c_str());
+	 if (!(*pmap2)) {
+	    ATH_MSG_FATAL("Error using plane map: "+m_pmap_path);
+	    return StatusCode::FAILURE;
+	 }
+	 if ( pmap->CalcChecksum() != pmap2->CalcChecksum() ) {
+	    ATH_MSG_FATAL("The given plane-map does not fit to the TSP pattern.");
+	    return StatusCode::FAILURE;
+	 }
+
+	 // check rmap file
+	 FTKRegionMap* rmap2 = new FTKRegionMap(pmap, m_rmap_path.c_str());
+	 if ( rmap2->CalcChecksum() != rmap->CalcChecksum() ) {
+            ATH_MSG_FATAL("The given region-map does not fit to the TSP pattern.");
+            return StatusCode::FAILURE;
+         }
+	 // check tsp ss file
+	 FTKSSMap* ssmapTSP2 = new FTKSSMap(rmap, m_ssmapTSP_path.c_str(), force_am_hashmap);
+	 if ( ssmapTSP->CalcChecksum() != ssmapTSP2->CalcChecksum() ) {
+            ATH_MSG_FATAL("The given TSP ss-map does not fit to the TSP pattern.");
+            return StatusCode::FAILURE;
+         }
+	 delete ssmapTSP;
+         ssmapTSP=ssmapTSP2;
+	 //delete rmap2;
+	 //delete pmap2;
+      }
+   }
+   //ATH_MSG_INFO("initialize() checking module LUT");
+   if((m_hwmodeid_default==2)||(m_hwmodeid_tspcc==2)||(m_hwmodeid_dc==2)) {
+      if(!rmap->isModuleIDLUTloaded()) {
+         if(m_modulelut_path.empty()) {
+            ATH_MSG_FATAL("A module LUT is required when HW SS calculation is required");
+         } else {
+            ATH_MSG_INFO("Loading module LUT from file \""+
+                         m_modulelut_path+"\"");
+            rmap->loadModuleIDLUT(m_modulelut_path.c_str());
+         }
+      }
+   }
+   //exit(0);
+   // --- ---
+
+   // --- Create new AM-ssmap
+   //ATH_MSG_INFO("initialize() Make FTKSSMapAM.");
+   FTKSSMap* ssmapAM  = new FTKSSMap(rmap, m_ssmapAM_path.c_str(), force_am_hashmap);
+
+   // ftk setup
+   
+
+   // --- create FTK_CompressedAMBank
+   //ATH_MSG_INFO("Create FTK_CompressedAMBank");
+   ATH_MSG_INFO(" + default HWMODEID (used if -1 is specified): "
+                +TString::Format("%d",m_hwmodeid_default));
+   ATH_MSG_INFO(" + HWMODEID of input/output pcache DC bank: "
+                +TString::Format("%d",m_hwmodeid_dc));
+   ATH_MSG_INFO(" + HWMODEID of input/output tsp/ccache DC bank: "
+                +TString::Format("%d",m_hwmodeid_tspcc));
+   //  FTKPattGenRoot pattgen(pmap,rmap,m_curreg,ssmap,sectorslice,constbank);
+
+   FTK_CompressedAMBank bank(m_curreg,m_iSubReg,ssmapAM,ssmapTSP,
+                             m_hwmodeid_tspcc,m_hwmodeid_dc);
+
+   if(bank.getHWModeSS_dc() != bank.getHWModeSS_tsp()) {
+      if(m_sectordefHW0.empty() || m_sectordefHW2.empty()) {
+	 ATH_MSG_FATAL("Different HWMODEID for TSP and DC bank but sector definition files not given");
+      } else {
+	 bank.readSectorDefinition(m_sectordefHW0.c_str(),m_sectordefHW2.c_str());
+      }
+   }
+   ostringstream msg;
+   msg<<"HWMODEID="<<bank.getHWModeSS_tsp()
+      <<" on TSP level (sectorordered/ccache bank) and HWMODEID="
+      <<bank.getHWModeSS_dc()<<" on DC level (pcache bank)";
+   ATH_MSG_INFO(msg.str().c_str());
+
+   // set TSP import parameters
+   if(m_ndcMax>=0) {
+      bank.setNDCmax(m_ndcMax);
+   }
+   if(m_wildcardPenalty) {
+      bank.setWildcardPenalty(m_wildcardPenalty);
+   }
+   for(size_t plane=0;plane<m_ndcMaxPlane.size();plane++) {
+      bank.setNDCmaxPlane(plane,m_ndcMaxPlane[plane]);
+   }
+   for(size_t plane=0;plane<m_wildcardPenaltyPlane.size();plane++) {
+      bank.setWildcardPenaltyPlane(plane,m_wildcardPenaltyPlane[plane]);
+   }
+
+   // set list of bad modules
+   bank.setBadSSMapPath(m_badmap_path);
+   bank.setBadSSMapPath2(m_badmap_path2);
+
+   if(!m_in_cache_path.empty()) {
+      // read only one subregion (or whatever is in that file)
+      bank.readROOTBankCache(m_in_cache_path.c_str());
+   } else if(!m_partitionList.empty()) {
+      bank.readSectorOrderedBank(m_in_bank_path.c_str(),
+                                 m_partitionList.c_str(),
+                                 m_nSubReg,
+                                 m_nSectorMax,
+                                 m_nLamb);
+   } else {
+      bank.readSectorOrderedBank(m_in_bank_path.c_str(),
+                                 m_maxpatt,
+                                 m_nSubReg,
+                                 m_nSectorMax,
+                                 m_nLamb);
+   }
+   if(!m_out_ccache_path.empty())
+      bank.writeCCachedBankFile(m_out_ccache_path.c_str(),m_flatFormat);
+   if(!m_out_pcache_path.empty()) {
+      bank.writePCachedBankFile(m_out_pcache_path.c_str(),m_flatFormat,
+                                m_nSubReg,m_nLamb);
+   }
+
+   // Important: 'return' deletes the  FTKPattGenRoot object and thus writes the patterns to disk
+   return StatusCode::SUCCESS;
+} 
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/FTKConstGenAlgo.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKConstGenAlgo.cxx
new file mode 100644
index 00000000000..39664e44eeb
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKConstGenAlgo.cxx
@@ -0,0 +1,2468 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/FTKBankGenAlgo.h"
+#include "TrigFTKBankGen/FTKConstGenAlgo.h"
+#include "TrigFTKBankGen/FTKPattKDTree.h"
+#include "TrigFTKBankGen/atlparslice_root.h"
+
+#include "TrigFTKSim/FTKSetup.h"
+
+#include "GaudiKernel/MsgStream.h"
+
+#include "GaudiKernel/ITHistSvc.h"
+
+#include "TH1.h"
+#include "TFile.h"
+#include "TTree.h"
+#include "TMath.h"
+#include "TROOT.h"
+
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <cmath>
+#include <string>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include <TMatrixD.h>
+#include <TVectorD.h>
+#include <TDecompLU.h>
+#define MTX_TOLERANCE 3e-16
+
+geo_constants *geo_const,*gcorth;
+using namespace std;
+
+/////////////////////////////////////////////////////////////////////////////
+FTKConstGenAlgo::FTKConstGenAlgo(const std::string& name, ISvcLocator* pSvcLocator) :
+  AthAlgorithm(name, pSvcLocator),
+  m_merging(false),
+  m_genconst(false),
+  m_subregion(false),
+  m_extract_1stStage(false),
+  m_fpath(0x0),
+  m_outfilename(""),//output file name used for all process
+  m_ITkMode(false),
+  m_allregion(false),//do allregion or not
+  m_region(0),// use if not using all regions
+  m_nsubregion(0),
+  m_nbank(64),// number of total regions
+  m_pmap(0x0),//12L pmap used for extract 1st stage
+  m_pmap_8L(0x0),//8L pmap used for extract 1st stage
+  m_pmap_path(),//12L pmap path used for extract 1st stage
+  m_pmap_8L_path()//8L pmap path used for extract 1st stage
+{
+  declareProperty("file_path",m_fpath,"array of merging files");
+  declareProperty("merged_file_path",m_cfpath,"merged file");
+  declareProperty("gcon_file_path",m_gfpath,"gcon file");
+  declareProperty("sector_file_path",m_sfpath,"sector file");
+  declareProperty("LayerChange_path",m_extractpath,"extract1stStage");
+  declareProperty("pmap_path",m_pmap_path);
+  declareProperty("pmap_8L_path",m_pmap_8L_path);
+  declareProperty("merging",m_merging);
+  declareProperty("genconst",m_genconst);
+  declareProperty("subregion",m_subregion);
+  declareProperty("eightLayer",m_extract_1stStage);
+  declareProperty("ITkMode",m_ITkMode);
+  declareProperty("allregion",m_allregion);
+  declareProperty("region",m_region);
+  declareProperty("nsubregion",m_nsubregion);  
+  declareProperty("nbank",m_nbank);
+
+  declareProperty("OutputFileName",m_outfilename);
+}
+
+
+FTKConstGenAlgo::~FTKConstGenAlgo()
+{
+  if (m_pmap) delete m_pmap;
+  if (m_pmap_8L) delete m_pmap_8L;
+}
+
+StatusCode FTKConstGenAlgo::initialize(){
+
+  // toggle ITk geometry (placeholder with no effect as of Jan. 2016)
+  FTKSetup::getFTKSetup().setITkMode( m_ITkMode );
+  
+  MsgStream log(msgSvc(), name());
+  log << MSG::INFO << "FTKConstGenAlgo::initialize()" << endmsg;
+  
+  // merge
+  if(true==m_merging){
+    log << MSG::INFO << "This job will be  merging " <<m_fpath.size() << " files  "  <<endmsg;
+    merge();
+  }
+  
+  // sector/constant calcuration from matrix
+  if(true==m_genconst){
+    log << MSG::INFO << "This job will be accumulating fit constant "   <<endmsg;
+    constantgen();
+  }
+  
+  // 12L->8L reduction for matrix file
+  if(true==m_extract_1stStage){
+    log << MSG::INFO << "This job will be making 8Layer From 12Layer  "   <<endmsg;
+
+    // Look for the main plane-map (12L)
+    log << MSG::INFO << "Read the logical layer definitions" << endmsg;
+    if (m_pmap_path.empty()) {
+      log << MSG::FATAL << "Main plane map definition missing" << endmsg;
+      return StatusCode::FAILURE;
+    }
+    else {
+      m_pmap = new FTKPlaneMap(m_pmap_path.c_str());
+      if (!(*m_pmap)) {
+	log << MSG::FATAL << "Error using plane map: " << m_pmap_path << endmsg;
+	return StatusCode::FAILURE;
+      }
+    }
+    // Look for the main plane-map (8L)
+    if (m_pmap_8L_path.empty()) {
+      log << MSG::FATAL << "Main plane map definition missing" << endmsg;
+      return StatusCode::FAILURE;
+    }
+    else {
+      m_pmap_8L = new FTKPlaneMap(m_pmap_8L_path.c_str());
+      if (!(*m_pmap_8L)) {
+	log << MSG::FATAL << "Error using plane map: " << m_pmap_8L_path << endmsg;
+	return StatusCode::FAILURE;
+      }
+    }
+    
+    doRelation = false;
+    nplane = m_pmap->getNPlanes();
+    nplane8 = m_pmap_8L->getNPlanes();
+
+    // These 6 counters will evolve in each step of map building
+    // to generalize to 1st/2nd stage extrapolation.
+    endcap_inversion = new bool[12];
+
+    plane_index_1st_stage = 0;
+    plane_index_2nd_stage = 0;
+    coord_index_1st_stage = 0;
+    coord_index_2nd_stage = 0;
+    index_missing_plane = 0;
+    index_missing_coord = 0;
+
+    doInvert = false;
+
+    // select 8L from 12L, and check do endcap inversion or not
+    for(int nlayer=0; nlayer<m_pmap->getNPlanes(); nlayer++){// loop Layer for 2nd stage
+
+      // dimension of this layer (2 for pixel, 1 for SCT). Reading from .pmap file.
+      const int ndimension = m_pmap->getPlane(plane_index_2nd_stage,0).getNDimension();
+      
+      // if doRelation is false, the layer is not used for 1st stage
+      doRelation = false;
+      if (plane_index_1st_stage >= nplane8) {
+	doRelation = true;
+      } else if (m_pmap_8L->getPlane(plane_index_1st_stage, 0).getLayer() !=
+		 m_pmap   ->getPlane(plane_index_2nd_stage, 0).getLayer()
+		 ) {
+	doRelation = true;
+      }
+      
+      if(doRelation){
+	
+	// move the indexes
+	plane_index_2nd_stage += 1;
+	coord_index_2nd_stage += ndimension;
+	index_missing_plane += 1;
+	index_missing_coord += ndimension;
+	
+      }else{
+
+      // do Invert in this plane?
+      doInvert = m_pmap->getPlane(plane_index_2nd_stage,0).getNSte() != m_pmap->getPlane(plane_index_2nd_stage,1).getNSte();
+      if (m_pmap->getPlane(plane_index_2nd_stage,0).getNDimension()!=1) doInvert = false;
+      
+      endcap_inversion[index_missing_plane] = doInvert;
+	
+      // keep values for later use
+      vec_plane_index_1st_stage.push_back(plane_index_1st_stage);
+      vec_plane_index_2nd_stage.push_back(plane_index_2nd_stage);
+      vec_coord_index_1st_stage.push_back(coord_index_1st_stage);
+      vec_coord_index_2nd_stage.push_back(coord_index_2nd_stage);
+      vec_ndimension.push_back(ndimension);
+      vec_doInvert.push_back(doInvert);
+
+      // move the indexes
+      plane_index_1st_stage += 1;
+      coord_index_1st_stage += ndimension;
+      plane_index_2nd_stage += 1;
+      coord_index_2nd_stage += ndimension;
+
+      }//doRelation
+
+    }// loop for 2nd stage layer
+
+    extract_1stStage();
+  }
+
+  // make subregion, currently not used
+  if(true==m_subregion){
+    log << MSG::INFO << "This job will be making subregions from sectors and constants "   <<endmsg;
+    make_subregion();
+  }
+  return StatusCode::SUCCESS;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+StatusCode FTKConstGenAlgo::execute() {
+
+  MsgStream log(msgSvc(), name());
+  log << MSG::INFO << "FTKConstGenAlgo::execute() start" << endmsg;
+ 
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FTKConstGenAlgo::finalize() {
+  MsgStream log(msgSvc(), name());
+  log << MSG::INFO << "finalize()" << endmsg;
+    
+
+  return StatusCode::SUCCESS;
+}
+
+
+// HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+// HH the main part of each functions start from here HH
+// HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+
+void FTKConstGenAlgo::merge()
+{
+  MsgStream log(msgSvc(), name());
+  
+  log << MSG::INFO <<" m_path " << m_fpath.size() << endmsg;
+  m_nfile=m_fpath.size();
+
+  //
+  // variables of matrix before merge
+  //
+
+  float nevent = 0;
+  int npatterns=0;
+  int ndim;
+  int ndim2;
+  int *sectorID=NULL;
+  int *hashID=NULL;
+  double *vec=NULL;
+  double tmpC;
+  double tmpD;
+  double tmpPhi;
+  double tmpCoto;
+  double tmpZ;
+  float nhit;
+  double *tmpxC=NULL;
+  double *tmpxD=NULL;
+  double *tmpxPhi=NULL;
+  double *tmpxCoto=NULL;
+  double *tmpxZ=NULL;
+  double *tmpcovx=NULL;
+  ULong64_t m_merged_monval[100]={0};
+  bool monFlag=false;
+
+  std::vector<short >* tmp_intc = new std::vector<short >;
+  std::vector<short >* tmp_intphi = new std::vector<short >;
+  std::vector<short >* tmp_intd0 = new std::vector<short >;
+  std::vector<short >* tmp_intz0 = new std::vector<short >;
+  std::vector<short >* tmp_inteta = new std::vector<short >;
+  
+  matrix Mtmp;
+  
+  double tmp_cmax;
+  double tmp_cmin;
+  int tmp_cslices;
+  
+  double tmp_phimax;
+  double tmp_phimin;
+  int tmp_phislices;
+  
+  double tmp_d0max;
+  double tmp_d0min;
+  int tmp_d0slices;
+  
+  double tmp_z0max;
+  double tmp_z0min;
+  int tmp_z0slices;
+  
+  double tmp_etamax;
+  double tmp_etamin;
+  int tmp_etaslices;
+
+  //
+  // read information from matrix file
+  //
+
+  /* obtain the first valid file to extract some general information
+   * used to intialize the merge structures
+   */
+  string fpath;
+  TFile *file=NULL;
+  int check_file=0;
+
+  while(check_file<m_nfile){ // loop over the files, ends at the first valid file
+    fpath=m_fpath[check_file];
+    file = TFile::Open(fpath.c_str());
+    if(!file){
+      log << MSG::WARNING << fpath.c_str() << " is not found " << endmsg;
+    }else{
+      if(file->GetNkeys()!=0) break;
+    }
+    check_file++;
+  } // end loop over the files
+
+  /* extract the TTree for a reference region, all the values
+   * used in this block are independent
+   */
+  TTree *tree = (TTree*)file->Get(Form("am%d",m_region));
+  TTree *slice_tree = (TTree*)file->Get("slice");
+  if(gROOT->FindObject("montree")){
+    monFlag=true;
+  }
+
+  // extract logical layers related info: total dimenstion and number of logical layers
+  tree->SetBranchAddress("ndim",&ndim);
+  tree->SetBranchAddress("nplanes",&nplane);
+  tree->SetBranchAddress("ndim2",&ndim2);
+  tree->GetEntry(0); 
+  
+  slice_tree->SetBranchAddress("c_max",&tmp_cmax);
+  slice_tree->SetBranchAddress("c_min", &tmp_cmin);
+  slice_tree->SetBranchAddress("c_slices", &tmp_cslices);
+  slice_tree->SetBranchAddress("phi_max", &tmp_phimax);
+  slice_tree->SetBranchAddress("phi_min", &tmp_phimin);
+  slice_tree->SetBranchAddress("phi_slices", &tmp_phislices);
+  slice_tree->SetBranchAddress("d0_max", &tmp_d0max);
+  slice_tree->SetBranchAddress("d0_min", &tmp_d0min);
+  slice_tree->SetBranchAddress("d0_slices", &tmp_d0slices);
+  slice_tree->SetBranchAddress("z0_max", &tmp_z0max);
+  slice_tree->SetBranchAddress("z0_min", &tmp_z0min);
+  slice_tree->SetBranchAddress("z0_slices", &tmp_z0slices);
+  slice_tree->SetBranchAddress("eta_max", &tmp_etamax);
+  slice_tree->SetBranchAddress("eta_min", &tmp_etamin);
+  slice_tree->SetBranchAddress("eta_slices", &tmp_etaslices);
+  slice_tree->GetEntry(0); 
+  
+  sectorID = (int *) calloc(nplane+1,sizeof(int));
+  hashID = (int *) calloc(nplane+1,sizeof(int));
+  vec = (double *) calloc(ndim,sizeof(double));  
+  tmpxC = (double *) calloc(ndim,sizeof(double));  
+  tmpxD = (double *) calloc(ndim,sizeof(double));
+  tmpxPhi = (double *) calloc(ndim,sizeof(double));  
+  tmpxCoto = (double *) calloc(ndim,sizeof(double));  
+  tmpxZ = (double *) calloc(ndim,sizeof(double));  
+  tmpcovx = (double *) calloc(ndim2,sizeof(double));  
+
+  // close the temporary file
+  file->Close();
+
+  // setup the boundaries for the merge, it can be a single region or a range
+  // i.e. use all region or one region
+
+  int b_int;
+  int b_end;
+
+  int nbanks;
+  int bank_order;
+  if(true==m_allregion){
+    b_int=0;
+    b_end=m_nbank;
+  }else{
+    b_int=m_region; 
+    b_end=m_region+1; 
+  }
+
+  nbanks = b_end - b_int;
+  initPattTree(nbanks, nplane+1,ndim);
+
+  for(int i=0;i<m_nfile;i++){ // loop over the input files
+    const string &fpath = m_fpath[i]; 
+    log << MSG::INFO <<" m_file " << i << endmsg;
+    
+    TFile *mfile = TFile::Open(fpath.c_str());
+    gROOT->cd();
+
+    // check if the file is valid, if not move to the next
+    if(!mfile){
+      log << MSG::WARNING << fpath.c_str() << " is not found " << endmsg;
+      mfile->Close();
+      continue;
+    }
+    else if(mfile->GetNkeys()==0){
+      log << MSG::WARNING << " This file has not keys " << i << endmsg;
+      mfile->Close();
+      continue;
+    }
+
+    for(int b=b_int;b<b_end;b++) { // loop over the towers
+
+      // get the tree for the specific bank
+      TTree *am_tree = (TTree*)mfile->Get(Form("am%d",b));
+
+      // extract the number of events and connect the branches
+      nevent =am_tree->GetEntries();
+      am_tree->SetBranchAddress("sectorID",sectorID);
+      am_tree->SetBranchAddress("hashID",hashID);
+      am_tree->SetBranchAddress("tmpC",&tmpC);
+      am_tree->SetBranchAddress("tmpD",&tmpD);
+      am_tree->SetBranchAddress("tmpPhi",&tmpPhi);
+      am_tree->SetBranchAddress("tmpCoto",&tmpCoto);
+      am_tree->SetBranchAddress("tmpZ",&tmpZ);
+      am_tree->SetBranchAddress("nhit",&nhit);
+      am_tree->SetBranchAddress("Vec",vec);
+      am_tree->SetBranchAddress("tmpxC", tmpxC);
+      am_tree->SetBranchAddress("tmpxD", tmpxD);
+      am_tree->SetBranchAddress("tmpxPhi", tmpxPhi);
+      am_tree->SetBranchAddress("tmpxCoto", tmpxCoto);
+      am_tree->SetBranchAddress("tmpxZ", tmpxZ);
+      am_tree->SetBranchAddress("tmpcovx", tmpcovx);
+
+      am_tree->SetBranchAddress("tmpintc", &tmp_intc);
+      am_tree->SetBranchAddress("tmpintphi", &tmp_intphi);
+      am_tree->SetBranchAddress("tmpintd0", &tmp_intd0);
+      am_tree->SetBranchAddress("tmpintz0", &tmp_intz0);
+      am_tree->SetBranchAddress("tmpinteta", &tmp_inteta);
+      
+      // check the number of sectors analyzed
+      nsector = nsector+nevent;
+      
+      for(int j=0;j<nevent;j++){ // event loop
+        // load the current entry
+        am_tree->GetEntry(j);
+        Mtmp.C=tmpC, Mtmp.D=tmpD, Mtmp.Phi=tmpPhi;
+        Mtmp.Coto=tmpCoto, Mtmp.Z=tmpZ,Mtmp.nhit=nhit;
+
+        sectorID[nplane] = 0;//for sector, we set it to zero.
+        hashID[nplane] = 0;//for sector, we set it to zero.
+
+        bank_order = b - b_int;
+        addPattReturnCode=addKDPattern(bank_order,false,sectorID,hashID,1,Mtmp,vec,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+                                       tmp_intc[0],tmp_intphi[0],tmp_intd0[0],tmp_intz0[0],tmp_inteta[0]);
+
+	// new pattern found
+        if(1==addPattReturnCode){
+          ++npatterns;
+        }
+      } // end event loop
+
+      // close current file
+      delete am_tree;
+      am_tree=NULL;
+    } // end bank loop
+
+    if(monFlag){
+      TTree *m_montree = (TTree *)mfile->Get("montree");
+      ULong64_t m_monval[100]={0};
+      m_montree->SetBranchAddress("monval", m_monval);
+      m_montree->GetEntry(0);
+      for(int ibin=0;ibin<100;ibin++){
+        m_merged_monval[ibin] += m_monval[ibin];
+      }// for ibin                                                                                                                                                                                     
+      delete m_montree;
+      m_montree=NULL;
+    }
+
+    // close current file
+    mfile->Close();
+    delete mfile;
+    mfile=NULL;
+  } // end loop over the files
+  
+  free(sectorID);
+  free(hashID);
+  free(vec);
+  free(tmpxC);
+  free(tmpxD);
+  free(tmpxPhi);
+  free(tmpxCoto);
+  free(tmpxZ); 
+  free(tmpcovx);
+  
+  ////////////////////////////////////////////////////////////
+  ////// create new file merged some files
+  ///////////////////////////////////////////////////////////
+  
+  //
+  // variables for merged matrix file
+  //
+
+  int *mergeSec=NULL;
+  int *mergehashID=NULL;
+  double *mergevec=NULL;
+  double mergeC;
+  double mergeD;
+  double mergePhi;
+  double mergeCoto;
+  double mergeZ;
+  float mergenhit;
+  
+  double *mergexC=NULL;
+  double *mergexD=NULL;
+  double *mergexPhi=NULL;
+  double *mergexCoto=NULL;
+  double *mergexZ=NULL;
+  double *mergecovx=NULL;
+
+  TTree *m_tree=NULL;
+  TTree *m_mergeslice=NULL;
+  TTree *m_merged_montree=0;
+  if(monFlag){
+    m_merged_montree = new TTree("montree", "monitor tree");
+    m_merged_montree->Branch("monval", m_merged_monval, "m_monval[100]/l");
+    m_merged_montree->Fill();
+  }
+
+  m_mergeslice=new TTree("slice", "slice para");
+  
+  mergeSec = (int *) calloc(nplane,sizeof(int));  
+  mergehashID = (int *) calloc(nplane,sizeof(int));  
+  mergevec = (double *) calloc(ndim,sizeof(double));  
+  mergexC = (double *) calloc(ndim,sizeof(double));  
+  mergexD = (double *) calloc(ndim,sizeof(double));
+  mergexPhi = (double *) calloc(ndim,sizeof(double));  
+  mergexCoto = (double *) calloc(ndim,sizeof(double));  
+  mergexZ = (double *) calloc(ndim,sizeof(double));  
+  mergecovx = (double *) calloc(ndim2,sizeof(double));  
+  
+  // define output file
+  if (m_outfilename.size()==0) {
+    // if the output file is not specified the name is built according a specific conention
+    char filename[40];
+    if(true==m_allregion){
+      sprintf(filename,"matrix_%dL_%dDim_regall.root",nplane,ndim);
+    }else{
+      sprintf(filename,"matrix_%dL_%dDim_reg%d.root",nplane,ndim,m_region);
+    }
+    m_outfilename = filename;
+  }
+
+  // open the output file for the merged matrixes
+  file = TFile::Open(m_outfilename.c_str(),"recreate");
+
+  char name[5];
+  char mtitle[20];
+
+  m_mergeslice->Branch("c_max",&tmp_cmax);
+  m_mergeslice->Branch("phi_max",&tmp_phimax);
+  m_mergeslice->Branch("d0_max",&tmp_d0max);
+  m_mergeslice->Branch("z0_max",&tmp_z0max);
+  m_mergeslice->Branch("eta_max",&tmp_etamax);
+  
+  m_mergeslice->Branch("c_min",&tmp_cmin);
+  m_mergeslice->Branch("phi_min",&tmp_phimin);
+  m_mergeslice->Branch("d0_min",&tmp_d0min);
+  m_mergeslice->Branch("z0_min",&tmp_z0min);
+  m_mergeslice->Branch("eta_min",&tmp_etamin);
+  
+  m_mergeslice->Branch("c_slices",&tmp_cslices);
+  m_mergeslice->Branch("phi_slices",&tmp_phislices);
+  m_mergeslice->Branch("d0_slices",&tmp_d0slices);
+  m_mergeslice->Branch("z0_slices",&tmp_z0slices); 
+  m_mergeslice->Branch("eta_slices",&tmp_etaslices);    
+  m_mergeslice->Fill();
+  m_mergeslice->Write();
+
+  if(monFlag){
+    m_merged_montree->Write();
+  }
+
+  gROOT->cd();
+
+  //
+  // define branch name of merged matrix file, and fill
+  //
+
+  for(int b=b_int;b<b_end;b++){
+    sprintf(name,"am%d",b);
+    sprintf(mtitle,"Ambank %d para",b);
+        
+    m_tree = new TTree(name, mtitle);
+    
+    m_tree->Branch("ndim",&ndim,"ndim/I");
+    m_tree->Branch("ndim2",&ndim2,"ndim2/I");
+    m_tree->Branch("Vec", mergevec,"Vec[ndim]/D");
+    m_tree->Branch("nplanes",&nplane,"nplanes/I");
+    m_tree->Branch("sectorID", mergeSec,"sectorID[nplanes]/I");
+    m_tree->Branch("hashID", mergehashID,"hashID[nplanes]/I");
+    m_tree->Branch("nhit", &mergenhit,"nhit/F");
+    m_tree->Branch("tmpC", &mergeC,"tmpC/D");
+    m_tree->Branch("tmpD", &mergeD,"tmpD/D");
+    m_tree->Branch("tmpPhi", &mergePhi,"tmpPhi/D");
+    m_tree->Branch("tmpCoto", &mergeCoto,"tmpCoto/D");
+    m_tree->Branch("tmpZ", &mergeZ,"tmpZ/D");
+    m_tree->Branch("tmpxC", mergexC,"tmpxC[ndim]/D");
+    m_tree->Branch("tmpxD", mergexD,"tmpxD[ndim]/D");
+    m_tree->Branch("tmpxPhi", mergexPhi,"tmpxPhi[ndim]/D");
+    m_tree->Branch("tmpxCoto", mergexCoto,"tmpxCoto[ndim]/D");
+    m_tree->Branch("tmpxZ", mergexZ,"tmpxZ[ndim]/D");
+    m_tree->Branch("tmpcovx", mergecovx,"tmpcovx[ndim2]/D");
+                     
+    m_mergeintc= new std::vector<short>;
+    m_mergeintphi= new std::vector<short>;
+    m_mergeintd0= new std::vector<short>;
+    m_mergeintz0= new std::vector<short>;
+    m_mergeinteta= new std::vector<short>;
+
+    m_tree->Branch("tmpintc", &m_mergeintc);
+    m_tree->Branch("tmpintphi", &m_mergeintphi);
+    m_tree->Branch("tmpintd0", &m_mergeintd0);
+    m_tree->Branch("tmpintz0", &m_mergeintz0);
+    m_tree->Branch("tmpinteta", &m_mergeinteta);
+
+    bank_order = b - b_int;
+
+    sortMPatterns(bank_order);
+    
+    for(int i=0; i<getNPatterns(bank_order);i++){
+      m_mergeintc->clear();
+      m_mergeintphi->clear();
+      m_mergeintd0->clear();
+      m_mergeintz0->clear();
+      m_mergeinteta->clear();	
+
+      log << MSG::INFO <<"sector ";
+      for(int k=0;k<nplane;k++){
+	mergeSec[k]=getPatternSS(bank_order,i,k);
+	mergehashID[k]=getPatthashID(bank_order,i,k);
+	log <<getPatternSS(bank_order,i,k)<<" ";//tmp out
+      }
+      log <<" "<<getPattnhit(bank_order,i) <<endmsg;//tmp out
+      mergenhit=getPattnhit(bank_order,i);
+      mergeC=getPattC(bank_order,i);
+      mergeD=getPattD(bank_order,i);
+      mergePhi=getPattPhi(bank_order,i);
+      mergeCoto=getPattCoto(bank_order,i);
+      mergeZ=getPattZ(bank_order,i);
+      for(int k=0;k<ndim;k++){
+	mergevec[k]=getPatthitc(bank_order,i,k);
+	mergexC[k]=getPattxC(bank_order,i,k);
+	mergexD[k]=getPattxD(bank_order,i,k);
+	mergexPhi[k]=getPattxPhi(bank_order,i,k);
+	mergexCoto[k]=getPattxCoto(bank_order,i,k);
+	mergexZ[k]=getPattxZ(bank_order,i,k);
+	for(int l=0;l<ndim;l++){
+	  mergecovx[k*ndim+l]=getPattcovx(bank_order,i,k*ndim+l);
+	  log << MSG::DEBUG <<" i= "  << k*ndim+l <<"bank= "<< mergecovx[k*ndim+l] <<endmsg;
+	}
+	log <<getPatthitc(bank_order,i,k)<<" ";
+      }
+
+      log <<"  "<<endmsg;
+      
+      for(int m=0;m<mergenhit;m++){
+	m_mergeintc->push_back(getPattintc(bank_order,i,m));
+	m_mergeintphi->push_back(getPattintphi(bank_order,i,m));
+	m_mergeintd0->push_back(getPattintd0(bank_order,i,m));
+	m_mergeintz0->push_back(getPattintz0(bank_order,i,m));
+	m_mergeinteta->push_back(getPattinteta(bank_order,i,m));
+	      
+      }
+      
+      m_tree->Fill();
+    }
+
+    file->cd();
+    m_tree->Write();
+    gROOT->cd();
+
+    delete m_tree;
+    m_tree=NULL;
+  }
+
+  free(mergeSec);
+  free(mergehashID);
+  free(mergevec);
+  free(mergexC);
+  free(mergexD);
+  free(mergexPhi);
+  free(mergexCoto);
+  free(mergexZ);
+  free(mergecovx);
+
+  file->Close();
+  delete file;
+  file=NULL;
+}
+
+void FTKConstGenAlgo::constantgen()
+{
+  MsgStream log(msgSvc(), name());
+
+  //
+  // variables of matrix before merge
+  //
+
+  int ndim,tmp_ndim;
+  int nplane,tmp_nplane;
+  double *sum_Vec;
+  int *sum_Sec;
+  int *sum_Hash;
+  double sum_C;
+  double sum_D;
+  double sum_Phi;
+  double sum_Coto;
+  double sum_Z;
+  float sum_nhit;
+  char region[5];
+  int nsector;
+  TTree *const_tree;
+  double *sum_xC; 
+  double *sum_xD;
+  double *sum_xPhi;
+  double *sum_xCoto;
+  double *sum_xZ;
+  double **sum_covx;
+  double *sum_covx_i;
+  double *sum_covx_v;
+  double **ccopy;
+  double *eigval;
+  double *ccopy_v;
+  double **eigvec;
+  double *eigvec_v;
+  int nconst=0;
+
+  //slice file
+  int nslices[5];
+  double minvals[5];
+  double maxvals[5];
+  char s_filename[40];
+  bool monFlag=false;
+  
+  std::vector<short >* sum_intc = new std::vector<short >;
+  std::vector<short >* sum_intphi = new std::vector<short >;
+  std::vector<short >* sum_intd0 = new std::vector<short >;
+  std::vector<short >* sum_intz0 = new std::vector<short >;
+  std::vector<short >* sum_inteta = new std::vector<short >;
+
+  //
+  // get information from input matrix file
+  //
+  
+  sprintf(region,"am%d",m_region);
+  // open the file with the matrix files after the merging
+  TFile *mafile = 0x0;
+  if (m_merging) {
+    // if the merging was executed within this session the file was
+    // created in the ::merge() routine according the specific flags
+    mafile = TFile::Open(m_outfilename.c_str());
+  }
+  else {
+    // if the merging was executed in a previous step the matrix files
+    // is passed using the m_cfpath variable, controlled by JO
+    mafile = TFile::Open(m_cfpath.c_str());
+  }
+  gROOT->cd();
+
+  TTree *mslice_tree = (TTree*)mafile->Get("slice");
+  const_tree = (TTree*)mafile->Get(region);
+  nsector =const_tree->GetEntries();
+
+
+  if(gROOT->FindObject("montree")){
+    monFlag=true; 
+  }
+
+  TTree *m_montree=NULL;
+  if(monFlag){
+    TTree *m_montree_org = (TTree *)mafile->Get("montree");
+    m_montree_org->SetName("montree_org");
+    m_montree = m_montree_org->CloneTree();
+    m_montree->SetName("montree");
+    delete m_montree_org;
+    m_montree_org=NULL;
+  }
+
+  const_tree->SetBranchAddress("ndim",&tmp_ndim);
+  const_tree->SetBranchAddress("nplanes",&tmp_nplane);
+  const_tree->GetEntry(0);
+  ndim = tmp_ndim;
+  nplane = tmp_nplane;
+ 
+  sum_Sec = (int *) calloc(nplane,sizeof(int));
+  sum_Hash = (int *) calloc(nplane,sizeof(int));
+  sum_Vec = (double *) calloc(ndim,sizeof(double));
+  sum_xC = (double *) calloc(ndim,sizeof(double));
+  sum_xD = (double *) calloc(ndim,sizeof(double));
+  sum_xPhi = (double *) calloc(ndim,sizeof(double));
+  sum_xCoto = (double *) calloc(ndim,sizeof(double));
+  sum_xZ = (double *) calloc(ndim,sizeof(double));
+  sum_covx_i = (double *) calloc(ndim*ndim,sizeof(double));
+  
+  const_tree->SetBranchAddress("sectorID",sum_Sec);
+  const_tree->SetBranchAddress("hashID",sum_Hash);
+  const_tree->SetBranchAddress("tmpC",&sum_C);
+  const_tree->SetBranchAddress("tmpD",&sum_D);
+  const_tree->SetBranchAddress("tmpPhi",&sum_Phi);
+  const_tree->SetBranchAddress("tmpCoto",&sum_Coto);
+  const_tree->SetBranchAddress("tmpZ",&sum_Z);
+  const_tree->SetBranchAddress("nhit",&sum_nhit);
+  const_tree->SetBranchAddress("Vec",sum_Vec);
+  const_tree->SetBranchAddress("tmpxC", sum_xC);
+  const_tree->SetBranchAddress("tmpxD", sum_xD);
+  const_tree->SetBranchAddress("tmpxPhi", sum_xPhi);
+  const_tree->SetBranchAddress("tmpxCoto", sum_xCoto);
+  const_tree->SetBranchAddress("tmpxZ", sum_xZ);
+  const_tree->SetBranchAddress("tmpcovx", sum_covx_i);
+  
+  const_tree->SetBranchAddress("tmpintc", &sum_intc);
+  const_tree->SetBranchAddress("tmpintphi", &sum_intphi);
+  const_tree->SetBranchAddress("tmpintd0", &sum_intd0);
+  const_tree->SetBranchAddress("tmpintz0", &sum_intz0);
+  const_tree->SetBranchAddress("tmpinteta", &sum_inteta);
+  
+  mslice_tree->SetBranchAddress("c_max",&maxvals[0]);
+  mslice_tree->SetBranchAddress("c_min", &minvals[0]);
+  mslice_tree->SetBranchAddress("c_slices", &nslices[0]);
+  mslice_tree->SetBranchAddress("d0_max", &maxvals[1]);
+  mslice_tree->SetBranchAddress("d0_min", &minvals[1]);
+  mslice_tree->SetBranchAddress("d0_slices", &nslices[1]);
+  mslice_tree->SetBranchAddress("phi_max", &maxvals[2]);
+  mslice_tree->SetBranchAddress("phi_min", &minvals[2]);
+  mslice_tree->SetBranchAddress("phi_slices", &nslices[2]);
+  mslice_tree->SetBranchAddress("z0_max", &maxvals[3]);
+  mslice_tree->SetBranchAddress("z0_min", &minvals[3]);
+  mslice_tree->SetBranchAddress("z0_slices", &nslices[3]);
+  mslice_tree->SetBranchAddress("eta_max", &maxvals[4]);
+  mslice_tree->SetBranchAddress("eta_min", &minvals[4]);
+  mslice_tree->SetBranchAddress("eta_slices", &nslices[4]);
+  
+  mslice_tree->GetEntry(0); 
+
+  eigval = (double *) calloc(ndim,sizeof(double));
+  ccopy_v = (double *) calloc(ndim*ndim,sizeof(double));
+  eigvec_v = (double *) calloc(ndim*ndim,sizeof(double));
+  sum_covx_v = (double *) calloc(ndim*ndim,sizeof(double));  
+  ccopy = (double **) malloc(ndim*sizeof(double*));
+  eigvec = (double **) malloc(ndim*sizeof(double*));
+  sum_covx = (double **) malloc(ndim*sizeof(double*));
+
+  for(int i=0;i<ndim;++i){
+    sum_covx[i] =(double *) calloc(ndim,sizeof(double));    
+    ccopy[i] =(double *) calloc(ndim,sizeof(double));
+    eigvec[i] =(double *) calloc(ndim,sizeof(double));    
+    sum_covx[i] = &sum_covx_v[ndim*i];
+    ccopy[i]=  &ccopy_v[ndim*i];
+    eigvec[i]= &eigvec_v[ndim*i]; 
+  }
+
+  geo_const =(struct geo_constants *) malloc(nsector*sizeof(struct geo_constants));
+  gcorth =(struct geo_constants *) malloc(nsector*sizeof(struct geo_constants));
+    
+  for(int i=0;i<nsector;i++){
+    geo_const[i].Vd = (double *) calloc(ndim,sizeof(double));
+    geo_const[i].Vc = (double *) calloc(ndim,sizeof(double));
+    geo_const[i].Vf = (double *) calloc(ndim,sizeof(double));
+    geo_const[i].Vz0 = (double *) calloc(ndim,sizeof(double));
+    geo_const[i].Vo = (double *) calloc(ndim,sizeof(double));
+    geo_const[i].kernel = (double **) malloc((ndim-NPARS)*sizeof(double *));
+    gcorth[i].Vd = (double *) malloc(ndim*sizeof(double));
+    gcorth[i].Vc = (double *) malloc(ndim*sizeof(double));
+    gcorth[i].Vf = (double *) malloc(ndim*sizeof(double));
+    gcorth[i].Vz0 = (double *) malloc(ndim*sizeof(double));
+    gcorth[i].Vo = (double *) malloc(ndim*sizeof(double));
+    gcorth[i].kernel = (double **) malloc((ndim-NPARS)*sizeof(double *));
+    geo_const[i].kaverages = (double *) calloc((ndim-NPARS),sizeof(double));      
+    gcorth[i].kaverages = (double *) calloc((ndim-NPARS),sizeof(double));
+    for(int j=0;j<ndim-NPARS;j++){
+      geo_const[i].kernel[j] = (double *) calloc(ndim,sizeof(double));
+      gcorth[i].kernel[j] = (double *) calloc(ndim,sizeof(double));
+	
+    }
+  }
+            
+  minvals[4]=sinh(minvals[4]);
+  maxvals[4]=sinh(maxvals[4]);
+  maxvals[2]= maxvals[2]*M_PI;
+  minvals[2]= minvals[2]*M_PI;
+
+  double resolutions[14] = {0.04, 0.08265625, 0.04, 0.08265625, 0.04, 0.08265625, 0.04515625, 0.04515625, 0.04515625, 0.04515625, 0.04515625, 0.04515625, 0.04515625, 0.04515625};
+#ifdef DEBUG_NOISE
+  float n[30];
+#endif
+  
+  int nkernel=(ndim-NPARS)*ndim;
+  int nkaverages=ndim-NPARS;
+  int ndim2=ndim*ndim;
+  char filename[40];
+  char name[5];
+  char title[20];
+  double Cd,Cc,Cf,Cz0,Co;
+  double *Vc,*Vd,*Vf,*Vz0,*Vo;
+  double *kernel,*kaverages;
+        
+  Vc = (double *) calloc(ndim,sizeof(double));
+  Vd = (double *) calloc(ndim,sizeof(double));
+  Vf = (double *) calloc(ndim,sizeof(double));
+  Vz0 = (double *) calloc(ndim,sizeof(double));
+  Vo = (double *) calloc(ndim,sizeof(double));  
+    
+  kernel = (double *) calloc(ndim*(ndim-NPARS),sizeof(double));  
+  kaverages = (double *) calloc((ndim-NPARS),sizeof(double));  
+    
+  ///////// root file part
+    
+  sprintf(filename,"const_%dL_%dDim_reg%d.root",nplane,ndim,m_region);
+  cfile = new TFile(filename,"recreate");
+  gROOT->cd();
+  
+  sprintf(name,"Am%d",m_region);
+  sprintf(title,"Ambank %d const",m_region);
+  m_ctree = new TTree(name, title);
+       
+  m_ctree->Branch("ndim",&ndim,"ndim/I");
+  m_ctree->Branch("ndim2",&ndim2,"ndim2/I");
+  m_ctree->Branch("nkernel",&nkernel,"nkernel/I");
+  m_ctree->Branch("nkaverages",&nkaverages,"nkaverages/I");
+  m_ctree->Branch("nplane",&nplane,"nplane/I");
+  m_ctree->Branch("sectorID",sum_Sec,"m_sectorID[nplane]/I");
+  m_ctree->Branch("hashID",sum_Hash,"m_hashID[nplane]/I");
+  m_ctree->Branch("nhit",&sum_nhit,"nhit/F");
+  m_ctree->Branch("Cd", &Cd,"Cd/D");
+  m_ctree->Branch("Cc", &Cc,"Cc/D");
+  m_ctree->Branch("Cf", &Cf,"Cf/D");
+  m_ctree->Branch("Cz0", &Cz0,"Cz0/D");
+  m_ctree->Branch("Co", &Co,"Co/D");
+  m_ctree->Branch("Vc",Vc,"Vc[ndim]/D");
+  m_ctree->Branch("Vd",Vd,"Vd[ndim]/D");
+  m_ctree->Branch("Vf",Vf,"Vf[ndim]/D");
+  m_ctree->Branch("Vz0",Vz0,"Vz0[ndim]/D");
+  m_ctree->Branch("Vo",Vo,"Vo[ndim]/D");
+  m_ctree->Branch("kernel",kernel,"kernel[nkernel]/D");
+  m_ctree->Branch("kaverages",kaverages,"kaverages[nkaverages]/D");
+
+
+  //
+  // keep matrix information with "good" sectors to extract 8L from this matrix file
+  //
+
+  // matrix files with good sectors
+  TTree *m_good_tree=NULL;
+  TTree *m_good_slice=NULL;
+
+  double good_C;
+  double good_D;
+  double good_Phi;
+  double good_Coto;
+  double good_Z;
+
+  double *good_Vec;
+  double *good_xC; 
+  double *good_xD;
+  double *good_xPhi;
+  double *good_xCoto;
+  double *good_xZ;
+  double *good_covx_i;
+
+  good_Vec = (double *) calloc(ndim,sizeof(double));
+  good_xC = (double *) calloc(ndim,sizeof(double));
+  good_xD = (double *) calloc(ndim,sizeof(double));
+  good_xPhi = (double *) calloc(ndim,sizeof(double));
+  good_xCoto = (double *) calloc(ndim,sizeof(double));
+  good_xZ = (double *) calloc(ndim,sizeof(double));
+  good_covx_i = (double *) calloc(ndim*ndim,sizeof(double));
+  
+
+  if (m_outfilename.size()==0) {
+    // if the output file is not specified the name is built according a specific conention
+    char filename[40];
+    if(true==m_allregion){
+      sprintf(filename,"good_matrix_%dL_%dDim_regall.root",nplane,ndim);
+    }else{
+      sprintf(filename,"good_matrix_%dL_%dDim_reg%d.root",nplane,ndim,m_region);
+    }
+    m_outfilename = filename;
+  }
+
+  // open the output file for the good matrixes
+  good_file = TFile::Open(m_outfilename.c_str(),"recreate");
+  gROOT->cd();
+
+  m_good_slice=new TTree("slice", "slice para");
+  
+  m_good_slice->Branch("c_max",&maxvals[0]);
+  m_good_slice->Branch("d0_max",&maxvals[1]);
+  m_good_slice->Branch("phi_max",&maxvals[2]);
+  m_good_slice->Branch("z0_max",&maxvals[3]);
+  m_good_slice->Branch("eta_max",&maxvals[4]);
+  
+  m_good_slice->Branch("c_min",&minvals[0]);
+  m_good_slice->Branch("d0_min",&minvals[1]);
+  m_good_slice->Branch("phi_min",&minvals[2]);
+  m_good_slice->Branch("z0_min",&minvals[3]);
+  m_good_slice->Branch("eta_min",&minvals[4]);
+  
+  m_good_slice->Branch("c_slices",&nslices[0]);
+  m_good_slice->Branch("d0_slices",&nslices[1]);
+  m_good_slice->Branch("phi_slices",&nslices[2]);
+  m_good_slice->Branch("z0_slices",&nslices[3]); 
+  m_good_slice->Branch("eta_slices",&nslices[4]);    
+
+  m_good_slice->Fill();
+  
+  good_file->cd();
+  m_good_slice->Write();
+  if(monFlag){
+    m_montree->Write();
+  }
+  gROOT->cd();
+
+  sprintf(name,"am%d",m_region);
+  sprintf(title,"Ambank %d para",m_region);
+  
+  m_good_tree = new TTree(name, title);
+
+  m_good_tree->Branch("ndim",&ndim,"ndim/I");
+  m_good_tree->Branch("ndim2",&ndim2,"ndim2/I");
+  m_good_tree->Branch("Vec", good_Vec,"Vec[ndim]/D");
+  m_good_tree->Branch("nplanes",&nplane,"nplanes/I");
+  m_good_tree->Branch("sectorID", sum_Sec,"sectorID[nplanes]/I");
+  m_good_tree->Branch("hashID", sum_Hash,"hashID[nplanes]/I");
+  m_good_tree->Branch("nhit", &sum_nhit,"nhit/F");
+  m_good_tree->Branch("tmpC", &good_C,"tmpC/D");
+  m_good_tree->Branch("tmpD", &good_D,"tmpD/D");
+  m_good_tree->Branch("tmpPhi", &good_Phi,"tmpPhi/D");
+  m_good_tree->Branch("tmpCoto", &good_Coto,"tmpCoto/D");
+  m_good_tree->Branch("tmpZ", &good_Z,"tmpZ/D");
+  m_good_tree->Branch("tmpxC", good_xC,"tmpxC[ndim]/D");
+  m_good_tree->Branch("tmpxD", good_xD,"tmpxD[ndim]/D");
+  m_good_tree->Branch("tmpxPhi", good_xPhi,"tmpxPhi[ndim]/D");
+  m_good_tree->Branch("tmpxCoto", good_xCoto,"tmpxCoto[ndim]/D");
+  m_good_tree->Branch("tmpxZ", good_xZ,"tmpxZ[ndim]/D");
+  m_good_tree->Branch("tmpcovx", good_covx_i,"tmpcovx[ndim2]/D");
+  
+  m_good_tree->Branch("tmpintc", &sum_intc);
+  m_good_tree->Branch("tmpintphi", &sum_intphi);
+  m_good_tree->Branch("tmpintd0", &sum_intd0);
+  m_good_tree->Branch("tmpintz0", &sum_intz0);
+  m_good_tree->Branch("tmpinteta", &sum_inteta);
+  
+  //
+  // calcurate constants start
+  //
+
+  for(int sector=0;sector<nsector;sector++){
+      
+    const_tree->GetEntry(sector);
+
+    // keep original values before calcuration for "good" matrix
+    good_C = sum_C;
+    good_D = sum_D;
+    good_Phi = sum_Phi;
+    good_Coto = sum_Coto;
+    good_Z = sum_Z;
+
+    for(int i=0;i<ndim;++i){
+      good_Vec[i]= sum_Vec[i];
+      good_xC[i] = sum_xC[i];
+      good_xD[i] = sum_xD[i];
+      good_xPhi[i] = sum_xPhi[i];
+      good_xCoto[i] = sum_xCoto[i];
+      good_xZ[i] = sum_xZ[i];
+
+      for(int j=0;j<ndim;++j){
+	good_covx_i[ndim*i+j]=sum_covx_i[ndim*i+j];
+      }
+
+    }
+
+    for(int i=0;i<ndim;++i){
+      for(int j=0;j<ndim;++j){
+	sum_covx[i][j]=sum_covx_i[ndim*i+j];
+      }
+    }
+
+    // don't leave unitialized variables
+    // fill of zero, matrix ad vector
+      
+    if ( sum_nhit<15/*MIN_TRACK_SEC*/) {
+      //      puts("Not enough tracks!");
+      nullifyConstants(sector,ndim);
+      continue;
+    } // end insufficient track case
+      
+      //////////////////////////////////////////////////////  
+      ///  renormalize and diagonalize correlation matrixes and vector, 
+      ///  for all sector
+      //////////////////////////////////////////////////////
+      
+    sum_C /= sum_nhit;
+    sum_D /= sum_nhit;
+    sum_Phi /= sum_nhit;
+    sum_Coto /= sum_nhit;
+    sum_Z /= sum_nhit;  
+
+    for (int i=0 ; i<ndim ; ++i ) {
+      sum_Vec[i] /= sum_nhit;    
+    }
+    // traslate parameters
+      
+    for (int i=0;i<ndim;++i) {
+      sum_xC[i] = (sum_xC[i]-sum_Vec[i]*sum_C*sum_nhit)/(sum_nhit-1);
+      sum_xD[i] =(sum_xD[i]-sum_Vec[i]*sum_D*sum_nhit)/(sum_nhit-1);
+      sum_xPhi[i] =(sum_xPhi[i]-sum_Vec[i]*sum_Phi*sum_nhit)/(sum_nhit-1);
+      sum_xZ[i] = (sum_xZ[i]-sum_Vec[i]*sum_Z*sum_nhit)/(sum_nhit-1);
+      sum_xCoto[i] =(sum_xCoto[i]-sum_Vec[i]*sum_Coto*sum_nhit)/(sum_nhit-1);
+	
+      // symmetrize
+
+      for (int j=i;j<ndim;++j) {
+	ccopy[j][i] = ccopy[i][j] = 
+	  sum_covx[j][i] = sum_covx[i][j] =
+	  (sum_covx[i][j]-sum_Vec[i]*sum_Vec[j]*sum_nhit)/(sum_nhit-1);
+      }
+    }
+
+    //FlagAK - covering the case when matrix is singular (i.e., if linearity is too good due to small # of tracks)
+    if(mtx_eigen(ndim,sum_covx_v,eigval,eigvec_v)==-1 || mtx_invert(ndim,ccopy_v)==-1) {
+      log << MSG::INFO <<" sector " << sector << endmsg;
+      puts("Failed matrix operations!");
+      nullifyConstants(sector,ndim);
+      continue;
+    }
+
+    // Get the "noise" contribution
+    // Diagonal resolutions:
+    for(int i=0;i<ndim;i++) {
+      double noise_i = 0;
+      for(int j=0;j<ndim;j++){
+	noise_i += eigvec[i][j] * resolutions[j] * eigvec[i][j];
+      }
+#ifdef DEBUG_NOISE
+      n[16+i] = noise_i;
+      //printf("% 8f ",noise_i);
+#endif
+    }
+       
+    sigmad(geo_const[sector].Vc/*,sum_covx*/,ccopy,sum_xC,ndim);
+    sigmad(geo_const[sector].Vd/*,sum_covx*/,ccopy,sum_xD,ndim);
+    sigmad(geo_const[sector].Vf/*,sum_covx*/,ccopy,sum_xPhi,ndim);
+    sigmad(geo_const[sector].Vz0/*,sum_covx*/,ccopy,sum_xZ,ndim);
+    sigmad(geo_const[sector].Vo/*,sum_covx*/,ccopy,sum_xCoto,ndim);
+
+    for(int i=0;i<ndim-NPARS;i++) for(int j=0;j<ndim;j++)
+      geo_const[sector].kernel[i][j] = eigvec[i][j];
+
+    for(int i=0;i<ndim-NPARS;i++)
+      geo_const[sector].kaverages[i] = 0;
+    
+    for(int i=0;i<ndim-NPARS;i++) {
+      for(int j=0;j<ndim;j++){
+	geo_const[sector].kernel[i][j] = eigvec[i][j]/sqrt(eigval[i]);
+      }
+    }
+        
+    for(int i=0;i<ndim-NPARS;i++) for(int j=0;j<ndim;j++)
+      geo_const[sector].kaverages[i] +=
+	-geo_const[sector].kernel[i][j]*sum_Vec[j];
+    
+    geo_const[sector].Cd = sum_D;
+    geo_const[sector].Cc = sum_C;
+    geo_const[sector].Cf = sum_Phi;
+    geo_const[sector].Cz0 = sum_Z;
+    geo_const[sector].Co = sum_Coto;
+    
+    for(int i=0;i<ndim;i++)
+      geo_const[sector].Cd += -geo_const[sector].Vd[i]*sum_Vec[i];
+    
+    for(int i=0;i<ndim;i++)
+      geo_const[sector].Cc += -geo_const[sector].Vc[i]*sum_Vec[i];
+
+    for(int i=0;i<ndim;i++)
+      geo_const[sector].Cf += -geo_const[sector].Vf[i]*sum_Vec[i];
+
+    for(int i=0;i<ndim;i++)
+      geo_const[sector].Cz0 += -geo_const[sector].Vz0[i]*sum_Vec[i];
+
+    for(int i=0;i<ndim;i++)
+      geo_const[sector].Co += -geo_const[sector].Vo[i]*sum_Vec[i];
+
+    geo_const[sector].real = sum_nhit; // valid set of contants
+    
+    //now orthogonalize 
+     
+#define gc (geo_const[sector])
+#define gco (gcorth[sector])
+     
+    for(int j=0;j<ndim;j++) {
+      gco.Vd[j] = gc.Vd[j]; 
+      gco.Vc[j] = gc.Vc[j];
+      gco.Vf[j] = gc.Vf[j];
+      gco.Vz0[j] = gc.Vz0[j];
+      gco.Vo[j] = gc.Vo[j];
+    }
+       
+    gco.Cd = gc.Cd; gco.Cc = gc.Cc; gco.Cf = gc.Cf;
+    gco.Co = gc.Co; gco.Cz0 = gc.Cz0;
+    gco.real = gc.real;
+
+    for(int i=0;i<ndim-NPARS;i++) {
+      pr = proj(gc.Vd,gc.kernel[i],ndim)/proj(gc.kernel[i],gc.kernel[i],ndim);
+      for(int j=0;j<ndim;j++) gco.Vd[j] += -gc.kernel[i][j]*pr;
+      gco.Cd += -gc.kaverages[i]*pr;
+      
+      pr = proj(gc.Vc,gc.kernel[i],ndim)/proj(gc.kernel[i],gc.kernel[i],ndim);
+      for(int j=0;j<ndim;j++) gco.Vc[j] += - gc.kernel[i][j]*pr;
+      gco.Cc += -gc.kaverages[i]*pr;
+	  
+      pr = proj(gc.Vf,gc.kernel[i],ndim)/proj(gc.kernel[i],gc.kernel[i],ndim);
+      for(int j=0;j<ndim;j++) gco.Vf[j] += -gc.kernel[i][j]*pr;
+      gco.Cf += -gc.kaverages[i]*pr;
+
+      pr = proj(gc.Vz0,gc.kernel[i],ndim)/proj(gc.kernel[i],gc.kernel[i],ndim);
+      for(int j=0;j<ndim;j++) gco.Vz0[j] += -gc.kernel[i][j]*pr;
+      gco.Cz0 += -gc.kaverages[i]*pr;
+
+      pr = proj(gc.Vo,gc.kernel[i],ndim)/proj(gc.kernel[i],gc.kernel[i],ndim);
+      for(int j=0;j<ndim;j++) gco.Vo[j] += -gc.kernel[i][j]*pr;
+      gco.Co += -gc.kaverages[i]*pr;
+      
+        
+      // Copy the kernel 
+      for(int j=0;j<ndim;j++) gco.kernel[i][j] = gc.kernel[i][j];
+      gco.kaverages[i] = gc.kaverages[i];
+    }
+
+    // FlagAK - final check to make sure the constants have no "nan" values
+    if(failedConstants(sector,ndim)) {
+      log << MSG::INFO <<" sector " << sector << endmsg;
+      puts("Found nans in final writeout!");
+      nullifyConstants(sector,ndim);
+      continue;
+    }
+    else {
+      
+      Cc=geo_const[sector].Cc;
+      Cd=geo_const[sector].Cd;
+      Cf=geo_const[sector].Cf;
+      Cz0=geo_const[sector].Cz0;
+      Co=geo_const[sector].Co;
+
+      for(int i=0;i<ndim;i++){
+	Vc[i]=geo_const[sector].Vc[i];
+	Vd[i]=geo_const[sector].Vd[i];
+	Vf[i]=geo_const[sector].Vf[i];
+	Vz0[i]=geo_const[sector].Vz0[i];
+	Vo[i]=geo_const[sector].Vo[i];
+      }
+      for(int i=0;i<ndim-NPARS;i++){ 
+	kaverages[i]=geo_const[sector].kaverages[i];
+      }
+	
+      for(int i=0;i<ndim-NPARS;i++){ 
+	for(int j=0;j<ndim;j++){ 
+	  kernel[i*ndim+j]=geo_const[sector].kernel[i][j];
+	}
+      }
+      m_ctree->Fill();
+      nconst++;
+
+      //fill matrix
+      m_good_tree->Fill();
+
+      // Record information on eigenvalues and noise
+#ifdef DEBUG_NOISE
+      n[0] = sector;
+      n[1] = sum_nhit;
+      n[2] = eigval[0];
+      n[3] = eigval[1];
+      n[4] = eigval[2];
+      n[5] = eigval[3];
+      n[6] = eigval[4];
+      n[7] = eigval[5];
+      n[8] = eigval[6];
+      n[9] = eigval[7];
+      n[10] = eigval[8];
+      n[11] = eigval[9];
+      n[12] = eigval[10];
+      n[13] = eigval[11];
+      n[14] = eigval[12];
+      n[15] = eigval[13];
+      // n[16] - n[29] recorded above for noise
+#endif
+    }
+
+  }// for sector
+
+  //
+  // for good matrix
+  //
+
+  good_file->cd();
+  m_good_tree->Write();
+  gROOT->cd();
+  
+  delete m_good_tree;
+  m_good_tree=NULL;
+
+  //
+  // const.root    
+  //
+  cfile->cd();
+  m_ctree->Write();
+  gROOT->cd();
+  cfile->Close();
+  
+
+  ////// ASCII file part (.gcon and .patt)
+  FILE *sector_file;
+  FILE *sectorHW_file;
+  FILE *const_file;
+  char sector_filename[40];
+  char sectorHW_filename[40];
+  char const_filename[40];
+  int nconst1=0;
+    
+  //slice file
+  initNSlices(1,nslices,minvals,maxvals);
+  initSlices(0,nconst);
+       
+  // slice file
+    
+  sprintf(const_filename,"corrgen_raw_%dL_reg%d.gcon",nplane,m_region);
+  sprintf(sector_filename,"sectors_raw_%dL_reg%d.patt",nplane,m_region);
+  sprintf(sectorHW_filename,"sectorsHW_raw_%dL_reg%d.patt",nplane,m_region);
+  sector_file = fopen(sector_filename,"w");
+  sectorHW_file = fopen(sectorHW_filename,"w");
+  const_file = fopen(const_filename,"w");
+    
+  fprintf(const_file,"! ***           RECONSTRUCTION GEOMETRY CONSTANTS               ***\n");
+  fprintf(const_file,"\n");
+  fprintf(const_file,"Version 2       ! File format version number\n");
+  fprintf(const_file,"\n");
+  fprintf(const_file,"! ***           PHI is now in GLOBAL coordinate system          ***\n");
+  fprintf(const_file," NPLANES\n");
+  fprintf(const_file," %d\n",nplane);
+  fprintf(const_file," NSECTORS\n");
+  fprintf(const_file,"%d\n",nconst);
+  fprintf(const_file," NDIM\n");
+  fprintf(const_file," 2\n");
+    
+  fprintf(sector_file,"%d %d\n",nconst,nplane);
+  fprintf(sectorHW_file,"%d %d\n",nconst,nplane);
+    
+  for(int sector=0;sector<nsector;sector++){
+    const_tree->GetEntry(sector);
+    if(geo_const[sector].Cc!=0){
+	
+      // sector file
+      fprintf(sector_file,"%d ",nconst1);
+      fprintf(sectorHW_file,"%d ",nconst1);
+      for(int i=0;i<nplane;i++){
+	fprintf(sector_file,"%d ",sum_Sec[i]);
+	fprintf(sectorHW_file,"%d ",sum_Hash[i]);
+      }
+      int nhit=sum_nhit;
+      fprintf(sector_file,"0 %d",nhit);
+      fprintf(sector_file,"\n");
+      fprintf(sectorHW_file,"0 %d",nhit);
+      fprintf(sectorHW_file,"\n");
+      // sector file
+	
+      //gcon file  
+	
+      fprintf(const_file,"sector\n");
+      fprintf(const_file,"%d\n",nconst1);
+	
+      fprintf(const_file," Vc \n");
+      for(int i=0;i<ndim;i++){
+	fprintf(const_file,"%e\n",geo_const[sector].Vc[i]);
+      }
+	
+      fprintf(const_file," Vd \n");
+      for(int i=0;i<ndim;i++){
+	fprintf(const_file,"%e\n",geo_const[sector].Vd[i]);
+      }
+
+      fprintf(const_file," Vf \n");
+      for(int i=0;i<ndim;i++){
+	fprintf(const_file,"%e\n",geo_const[sector].Vf[i]);
+      }
+
+      fprintf(const_file," Vz0 \n");
+      for(int i=0;i<ndim;i++){
+	fprintf(const_file,"%e\n",geo_const[sector].Vz0[i]);
+      }
+
+      fprintf(const_file," Vo \n");
+      for(int i=0;i<ndim;i++){
+	fprintf(const_file,"%e\n",geo_const[sector].Vo[i]);
+      }
+	
+      fprintf(const_file,"kaverages\n");
+      for(int i=0;i<ndim-NPARS;i++){ 
+	fprintf(const_file,"%e\n",geo_const[sector].kaverages[i]);
+      }
+	
+      fprintf(const_file,"kernel\n");
+      for(int i=0;i<ndim-NPARS;i++){ 
+	for(int j=0;j<ndim;j++){ 
+	  fprintf(const_file,"%e\n",geo_const[sector].kernel[i][j]);
+	}
+      }
+	
+      fprintf(const_file,"Cc\n");
+      fprintf(const_file,"%e\n",geo_const[sector].Cc);
+	
+      fprintf(const_file,"Cd\n");
+      fprintf(const_file,"%e\n",geo_const[sector].Cd);
+
+      fprintf(const_file,"Cf\n");
+      fprintf(const_file,"%e\n",geo_const[sector].Cf);
+	
+      fprintf(const_file,"Cz0\n");
+      fprintf(const_file,"%e\n",geo_const[sector].Cz0);
+
+      fprintf(const_file,"Co\n");
+      fprintf(const_file,"%e\n",geo_const[sector].Co);
+      //gcon file
+	
+      for(int i=0;i<nhit;i++){
+	addSectorToSlice(0,nconst1,sum_intc[0][i],sum_intd0[0][i],sum_intphi[0][i],sum_intz0[0][i],sum_inteta[0][i]);
+      }
+      nconst1++;
+    }//Cc!=0
+  }//sector loop
+    
+  mafile->Close();
+  fclose(sector_file);
+  fclose(sectorHW_file);
+  fclose(const_file);
+
+  sprintf(s_filename,"slices_%dL_reg%d.root",nplane,m_region);
+  saveSlices(0,s_filename);
+  //////ASCII file part
+  for (int i=0;i<nsector;++i) {
+      
+    for (int j=0;j<ndim-NPARS;++j) {
+      free(geo_const[i].kernel[j]);
+      free(gcorth[i].kernel[j]);
+    }
+    // free arrays of array
+    free(geo_const[i].kernel);
+    free(geo_const[i].Vc);
+    free(geo_const[i].Vd);
+    free(geo_const[i].Vf);
+    free(geo_const[i].Vz0);
+    free(geo_const[i].Vo);
+      
+    free(gcorth[i].kernel);
+    free(gcorth[i].Vc);
+    free(gcorth[i].Vd);
+    free(gcorth[i].Vf);
+    free(gcorth[i].Vz0);    
+    free(gcorth[i].Vo);
+      
+    free(geo_const[i].kaverages);
+    free(gcorth[i].kaverages);
+      
+  }
+
+}//const gen
+
+
+/** Extract a reduce set of constants from sectors built using
+ * more modules
+ */
+void FTKConstGenAlgo::extract_1stStage()
+{
+  MsgStream log(msgSvc(), name());
+
+  // retrieve the original file
+  TFile *Lfile = TFile::Open(m_extractpath.c_str(),"");
+  // retrieve the TTree for the slices and the information on the sectors
+  TTree *tree = (TTree*)Lfile->Get(Form("am%d",m_region));
+  TTree *slice_tree = (TTree*) Lfile->Get("slice");
+
+  for(int idx=0; idx<(int)vec_plane_index_2nd_stage.size(); idx++){
+    log << MSG::INFO <<"2nd stage layer :" << vec_plane_index_2nd_stage[idx] << ", 1st stage layer: "<< vec_plane_index_1st_stage[idx] << ", doInvert: " << vec_doInvert[idx] << ", coord 2nd stage: " << vec_coord_index_2nd_stage[idx] << ", coord 1st stage: " << vec_coord_index_1st_stage[idx] << endmsg;
+  }
+
+  // prepare the pointers to retrieve the data from the TTrees
+  int nevent;
+  int npatterns=0;
+  int ndim;
+  int nth_dim  = 0;
+  int nth_dim2 = 0;
+  int ndim2;
+  int *sectorID;
+  int *hashID;
+  double *vec; 
+  double tmpC;
+  double tmpD;
+  double tmpPhi;
+  double tmpCoto;
+  double tmpZ;
+  float nhit;
+  double *tmpxC;
+  double *tmpxD;
+  double *tmpxPhi;
+  double *tmpxCoto;
+  double *tmpxZ;
+  double *tmpcovx;
+
+  int ndim8 = 11;
+  int ndim2_8 = 11*11;
+  int nth_dim8 = 0;
+  int nth_dim8_2 = 0;
+  int idx_cov8 = 0;
+  int *sectorID8;
+  int *hashID8;
+  double *vec8; 
+  double *tmpxC8;
+  double *tmpxD8;
+  double *tmpxPhi8;
+  double *tmpxCoto8;
+  double *tmpxZ8;
+  double *tmpcovx8;
+
+  std::vector<short >* tmp_intc = new std::vector<short >;
+  std::vector<short >* tmp_intphi = new std::vector<short >;
+  std::vector<short >* tmp_intd0 = new std::vector<short >;
+  std::vector<short >* tmp_intz0 = new std::vector<short >;
+  std::vector<short >* tmp_inteta = new std::vector<short >;
+  
+  matrix Mtmp;
+  
+  double tmp_cmax;
+  double tmp_cmin;
+  int tmp_cslices;
+  
+  double tmp_phimax;
+  double tmp_phimin;
+  int tmp_phislices;
+  
+  double tmp_d0max;
+  double tmp_d0min;
+  int tmp_d0slices;
+  
+  double tmp_z0max;
+  double tmp_z0min;
+  int tmp_z0slices;
+  
+  double tmp_etamax;
+  double tmp_etamin;
+  int tmp_etaslices;
+  
+  //
+  // read matrix file
+  //
+
+  tree->SetBranchAddress("ndim",&ndim);
+  tree->SetBranchAddress("nplanes",&nplane);
+  tree->SetBranchAddress("ndim2",&ndim2);
+  tree->GetEntry(0); 
+  
+  slice_tree->SetBranchAddress("c_max",&tmp_cmax);
+  slice_tree->SetBranchAddress("c_min", &tmp_cmin);
+  slice_tree->SetBranchAddress("c_slices", &tmp_cslices);
+  slice_tree->SetBranchAddress("phi_max", &tmp_phimax);
+  slice_tree->SetBranchAddress("phi_min", &tmp_phimin);
+  slice_tree->SetBranchAddress("phi_slices", &tmp_phislices);
+  slice_tree->SetBranchAddress("d0_max", &tmp_d0max);
+  slice_tree->SetBranchAddress("d0_min", &tmp_d0min);
+  slice_tree->SetBranchAddress("d0_slices", &tmp_d0slices);
+  slice_tree->SetBranchAddress("z0_max", &tmp_z0max);
+  slice_tree->SetBranchAddress("z0_min", &tmp_z0min);
+  slice_tree->SetBranchAddress("z0_slices", &tmp_z0slices);
+  slice_tree->SetBranchAddress("eta_max", &tmp_etamax);
+  slice_tree->SetBranchAddress("eta_min", &tmp_etamin);
+  slice_tree->SetBranchAddress("eta_slices", &tmp_etaslices);
+  slice_tree->GetEntry(0); 
+  
+  sectorID = (int *) calloc(nplane+1,sizeof(int));  
+  hashID = (int *) calloc(nplane+1,sizeof(int));  
+  vec = (double *) calloc(ndim,sizeof(double));  
+  tmpxC = (double *) calloc(ndim,sizeof(double));  
+  tmpxD = (double *) calloc(ndim,sizeof(double));
+  tmpxPhi = (double *) calloc(ndim,sizeof(double));  
+  tmpxCoto = (double *) calloc(ndim,sizeof(double));  
+  tmpxZ = (double *) calloc(ndim,sizeof(double));  
+  tmpcovx = (double *) calloc(ndim2,sizeof(double));  
+
+  sectorID8 = (int *) calloc(nplane8+1,sizeof(int));  
+  hashID8 = (int *) calloc(nplane8+1,sizeof(int));  
+  vec8 = (double *) calloc(ndim8,sizeof(double));  
+  tmpxC8 = (double *) calloc(ndim8,sizeof(double));  
+  tmpxD8 = (double *) calloc(ndim8,sizeof(double));
+  tmpxPhi8 = (double *) calloc(ndim8,sizeof(double));  
+  tmpxCoto8 = (double *) calloc(ndim8,sizeof(double));  
+  tmpxZ8 = (double *) calloc(ndim8,sizeof(double));  
+  tmpcovx8 = (double *) calloc(ndim8*ndim8,sizeof(double));  
+
+  // setup the boundaries for the merge, it can be a single region or a range
+  int b_int;
+  int b_end;
+  
+  int bank_order;
+  if(true==m_allregion){
+    b_int=0;
+    b_end=m_nbank;
+  }else{
+    b_int=m_region; 
+    b_end=m_region+1; 
+  }
+
+  initPattTree(m_nbank,nplane8+1,ndim8);  //(nregions, nplane+1, ndim)
+
+  for(int b=b_int;b<b_end;b++) { // loop over the banks
+
+    TTree *am_tree = (TTree*)Lfile->Get(Form("am%d",b));
+
+    nevent =am_tree->GetEntries();
+    am_tree->SetBranchAddress("sectorID",sectorID);
+    am_tree->SetBranchAddress("hashID",hashID);
+    am_tree->SetBranchAddress("tmpC",&tmpC);
+    am_tree->SetBranchAddress("tmpD",&tmpD);
+    am_tree->SetBranchAddress("tmpPhi",&tmpPhi);
+    am_tree->SetBranchAddress("tmpCoto",&tmpCoto);
+    am_tree->SetBranchAddress("tmpZ",&tmpZ);
+    am_tree->SetBranchAddress("nhit",&nhit);
+    am_tree->SetBranchAddress("Vec",vec);
+    am_tree->SetBranchAddress("tmpxC", tmpxC);
+    am_tree->SetBranchAddress("tmpxD", tmpxD);
+    am_tree->SetBranchAddress("tmpxPhi", tmpxPhi);
+    am_tree->SetBranchAddress("tmpxCoto", tmpxCoto);
+    am_tree->SetBranchAddress("tmpxZ", tmpxZ);
+    am_tree->SetBranchAddress("tmpcovx", tmpcovx);
+  
+    am_tree->SetBranchAddress("tmpintc", &tmp_intc);
+    am_tree->SetBranchAddress("tmpintphi", &tmp_intphi);
+    am_tree->SetBranchAddress("tmpintd0", &tmp_intd0);
+    am_tree->SetBranchAddress("tmpintz0", &tmp_intz0);
+    am_tree->SetBranchAddress("tmpinteta", &tmp_inteta);
+      
+    log << MSG::INFO <<  " region: " << b << ", nevent: " << nevent <<endmsg;
+
+    //
+    // extract 8L from 12L
+    //
+
+    for(int j=0;j<nevent;j++){ // event loop
+
+      am_tree->GetEntry(j);
+      Mtmp.C=tmpC, Mtmp.D=tmpD, Mtmp.Phi=tmpPhi;
+      Mtmp.Coto=tmpCoto, Mtmp.Z=tmpZ,Mtmp.nhit=nhit;
+
+      // check if the module belongs to endcap (for endcap inversion.).
+      bool isEndcap[12]={0};
+
+      for(int plane_idx_2nd_stage = 0;plane_idx_2nd_stage<nplane;plane_idx_2nd_stage++){
+      	if(sectorID[plane_idx_2nd_stage]%1000>20) isEndcap[plane_idx_2nd_stage]=true;
+      }
+
+      // main function extract 1st stage (8L) from 2nd stage (12L)
+      for(int idx_layer=0; idx_layer<(int)vec_plane_index_2nd_stage.size(); idx_layer++){
+	
+	if(vec_doInvert[idx_layer] && isEndcap[vec_plane_index_2nd_stage[idx_layer]]){// if endcap and SCT layer
+
+	  // stereo or axial
+	  if(vec_plane_index_2nd_stage[idx_layer] % 2 == 0) inversion = 1;
+	  else inversion = -1;
+
+	}else{// if no inversion
+	  inversion = 0;
+	}// endcap inversion
+
+	sectorID8[idx_layer] = sectorID[vec_plane_index_2nd_stage[idx_layer] + inversion];
+	hashID8[idx_layer] = hashID[vec_plane_index_2nd_stage[idx_layer] + inversion];
+	
+	for(int ndm=0; ndm<vec_ndimension[idx_layer]; ndm++){// pixel:2, SCT:1
+
+	  nth_dim  = vec_coord_index_2nd_stage[idx_layer] + ndm;
+	  nth_dim8 = vec_coord_index_1st_stage[idx_layer] + ndm;
+
+	  vec8[nth_dim8] = vec[nth_dim + inversion];
+	  tmpxC8[nth_dim8] = tmpxC[nth_dim + inversion];
+	  tmpxD8[nth_dim8] = tmpxD[nth_dim + inversion];
+	  tmpxPhi8[nth_dim8] = tmpxPhi[nth_dim + inversion];
+	  tmpxCoto8[nth_dim8] = tmpxCoto[nth_dim + inversion];
+	  tmpxZ8[nth_dim8] = tmpxZ[nth_dim + inversion];
+
+	  // tmpcovx culcuration
+	  for(int idx2_layer=0; idx2_layer<(int)vec_plane_index_2nd_stage.size(); idx2_layer++){
+	    for(int ndm2=0; ndm2<vec_ndimension[idx2_layer]; ndm2++){
+	      
+	      if(vec_doInvert[idx2_layer] && isEndcap[vec_plane_index_2nd_stage[idx2_layer]]){//if endcap and SCT layer
+		
+		// stereo or axial
+		if(vec_plane_index_2nd_stage[idx2_layer] % 2 == 0) inversion2 = 1;
+		else inversion2 = -1;
+		
+	      }else{// if no inversion
+		inversion2 = 0;
+	      }// endcap inversion
+
+	      nth_dim2   = vec_coord_index_2nd_stage[idx2_layer] + ndm2;
+	      nth_dim8_2 = vec_coord_index_1st_stage[idx2_layer] + ndm2;
+
+	      idx_cov8 = (nth_dim8) * ndim8 + nth_dim8_2;//11*x + y
+	      
+	      if(nth_dim8>nth_dim8_2){//make triangle
+		tmpcovx8[idx_cov8] = 0;
+	      }else{
+		tmpcovx8[idx_cov8] = tmpcovx[(nth_dim + inversion) * ndim + nth_dim2 + inversion2];
+	      }// nth_dim8 < 7
+
+	    }// dimension loop 2
+	  }// layer loop 2
+	  // tmpcovx culc end
+
+	}// dimension loop
+
+      }// layer loop
+
+      sectorID8[8] = 0;//for sector, we set it to zero
+      hashID8[8] = 0;//for sector, we set it to zero
+      bank_order = b - b_int;
+      
+      addPattReturnCode=addKDPattern(bank_order,false,sectorID8,hashID8,1,Mtmp,vec8,tmpxC8,tmpxD8,tmpxPhi8,tmpxCoto8,tmpxZ8,tmpcovx8,
+				     tmp_intc[0],tmp_intphi[0],tmp_intd0[0],tmp_intz0[0],tmp_inteta[0]);
+
+      if(1==addPattReturnCode){
+	++npatterns;
+      }
+
+    }// end of event loop
+  }// end of bank loop
+    
+  Lfile->Close();
+    
+  free(sectorID);
+  free(hashID);
+  free(vec);
+  free(tmpxC);
+  free(tmpxD);
+  free(tmpxPhi);
+  free(tmpxCoto);
+  free(tmpxZ); 
+  free(tmpcovx);
+  
+  //
+  // create new file of 8L extracted from 12L
+  //
+
+  ndim2_8=ndim8*ndim8;
+  int *extract_Sec;
+  int *extract_hash;
+  double *extract_vec; 
+  double extract_C;
+  double extract_D;
+  double extract_Phi;
+  double extract_Coto;
+  double extract_Z;
+  float extract_nhit;
+  
+  double *extract_xC=NULL;
+  double *extract_xD=NULL;
+  double *extract_xPhi=NULL;
+  double *extract_xCoto=NULL;
+  double *extract_xZ=NULL;
+  double *extract_covx=NULL;
+
+  TTree *m_tree=NULL;
+  TTree *m_extract_slice=NULL;
+
+  m_extract_slice=new TTree("slice", "slice para");
+  
+  extract_Sec = (int *) calloc(nplane8,sizeof(int));  
+  extract_hash = (int *) calloc(nplane8,sizeof(int));  
+  extract_vec = (double *) calloc(ndim8,sizeof(double));  
+  extract_xC = (double *) calloc(ndim8,sizeof(double));  
+  extract_xD = (double *) calloc(ndim8,sizeof(double));
+  extract_xPhi = (double *) calloc(ndim8,sizeof(double));  
+  extract_xCoto = (double *) calloc(ndim8,sizeof(double));  
+  extract_xZ = (double *) calloc(ndim8,sizeof(double));  
+  extract_covx = (double *) calloc(ndim8*ndim8,sizeof(double));  
+
+  // define output file
+  if (m_outfilename.size()==0) {
+    char filename[40];
+    if(true==m_allregion){
+      sprintf(filename,"matrix_%dL_%dDim_regall.root",nplane8,ndim8);
+    }else{
+      sprintf(filename,"matrix_%dL_%dDim_reg%d.root",nplane8,ndim8,m_region);
+    }
+    Lfile = new TFile(filename,"recreate");
+  }
+  else  {
+    Lfile = TFile::Open(m_outfilename.c_str(),"recreate");
+  }
+
+  char name[5];
+  char mtitle[20];
+
+  m_extract_slice->Branch("c_max",&tmp_cmax);
+  m_extract_slice->Branch("phi_max",&tmp_phimax);
+  m_extract_slice->Branch("d0_max",&tmp_d0max);
+  m_extract_slice->Branch("z0_max",&tmp_z0max);
+  m_extract_slice->Branch("eta_max",&tmp_etamax);
+  
+  m_extract_slice->Branch("c_min",&tmp_cmin);
+  m_extract_slice->Branch("phi_min",&tmp_phimin);
+  m_extract_slice->Branch("d0_min",&tmp_d0min);
+  m_extract_slice->Branch("z0_min",&tmp_z0min);
+  m_extract_slice->Branch("eta_min",&tmp_etamin);
+  
+  m_extract_slice->Branch("c_slices",&tmp_cslices);
+  m_extract_slice->Branch("phi_slices",&tmp_phislices);
+  m_extract_slice->Branch("d0_slices",&tmp_d0slices);
+  m_extract_slice->Branch("z0_slices",&tmp_z0slices); 
+  m_extract_slice->Branch("eta_slices",&tmp_etaslices);    
+  m_extract_slice->Fill();
+  m_extract_slice->Write();
+
+  //
+  // define 8L matrix branch, sort by ntracks, and fill
+  //
+
+  for(int b=b_int;b<b_end;b++){
+    sprintf(name,"am%d",b);
+    sprintf(mtitle,"Ambank %d para",b);
+        
+    m_tree = new TTree(name, mtitle);
+    
+    m_tree->Branch("ndim",&ndim8,"ndim8/I");
+    m_tree->Branch("ndim2",&ndim2_8,"ndim2_8/I");
+    m_tree->Branch("Vec", extract_vec,"Vec[ndim8]/D");
+    m_tree->Branch("nplanes",&nplane8,"nplanes/I");
+    m_tree->Branch("sectorID", extract_Sec, "sectorID[nplanes]/I");
+    m_tree->Branch("hashID", extract_hash, "hashID[nplanes]/I");
+    m_tree->Branch("nhit", &extract_nhit,"nhit/F");
+    m_tree->Branch("tmpC", &extract_C,"tmpC/D");
+    m_tree->Branch("tmpD", &extract_D,"tmpD/D");
+    m_tree->Branch("tmpPhi", &extract_Phi,"tmpPhi/D");
+    m_tree->Branch("tmpCoto", &extract_Coto,"tmpCoto/D");
+    m_tree->Branch("tmpZ", &extract_Z,"tmpZ/D");
+    m_tree->Branch("tmpxC", extract_xC,"tmpxC[ndim8]/D");
+    m_tree->Branch("tmpxD", extract_xD,"tmpxD[ndim8]/D");
+    m_tree->Branch("tmpxPhi", extract_xPhi,"tmpxPhi[ndim8]/D");
+    m_tree->Branch("tmpxCoto", extract_xCoto,"tmpxCoto[ndim8]/D");
+    m_tree->Branch("tmpxZ", extract_xZ,"tmpxZ[ndim8]/D");
+    m_tree->Branch("tmpcovx", extract_covx,"tmpcovx[ndim2_8]/D");
+                     
+    m_extract_intc= new std::vector<short>;
+    m_extract_intphi= new std::vector<short>;
+    m_extract_intd0= new std::vector<short>;
+    m_extract_intz0= new std::vector<short>;
+    m_extract_inteta= new std::vector<short>;
+
+    m_tree->Branch("tmpintc", &m_extract_intc);
+    m_tree->Branch("tmpintphi", &m_extract_intphi);
+    m_tree->Branch("tmpintd0", &m_extract_intd0);
+    m_tree->Branch("tmpintz0", &m_extract_intz0);
+    m_tree->Branch("tmpinteta", &m_extract_inteta);
+
+    bank_order = b - b_int;
+
+    sortMPatterns(bank_order);
+    
+    log << MSG::INFO <<"nsector "<< getNPatterns(bank_order) <<endmsg;
+    for(int i=0; i<getNPatterns(bank_order);i++){
+      m_extract_intc->clear();
+      m_extract_intphi->clear();
+      m_extract_intd0->clear();
+      m_extract_intz0->clear();
+      m_extract_inteta->clear();	
+      
+      log << MSG::INFO <<"sector ";
+      for(int k=0;k<nplane8;k++){
+	extract_Sec[k]=getPatternSS(bank_order,i,k);
+	extract_hash[k]=getPatthashID(bank_order,i,k);
+	log <<getPatternSS(bank_order,i,k)<<" ";
+      }
+      log <<" "<<getPattnhit(bank_order,i) <<endmsg;
+      extract_nhit=getPattnhit(bank_order,i);
+      extract_C=getPattC(bank_order,i);
+      extract_D=getPattD(bank_order,i);
+      extract_Phi=getPattPhi(bank_order,i);
+      extract_Coto=getPattCoto(bank_order,i);
+      extract_Z=getPattZ(bank_order,i);
+      for(int k=0;k<ndim8;k++){
+	extract_vec[k]=getPatthitc(bank_order,i,k);
+	extract_xC[k]=getPattxC(bank_order,i,k);
+	extract_xD[k]=getPattxD(bank_order,i,k);
+	extract_xPhi[k]=getPattxPhi(bank_order,i,k);
+	extract_xCoto[k]=getPattxCoto(bank_order,i,k);
+	extract_xZ[k]=getPattxZ(bank_order,i,k);
+	for(int l=0;l<ndim8;l++){
+	  extract_covx[k*ndim8+l]=getPattcovx(bank_order,i,k*ndim8+l);
+	  log << MSG::DEBUG <<" i= "  << k*ndim8+l <<"bank= "<< extract_covx[k*ndim8+l] <<endmsg;
+	}
+	log <<getPatthitc(bank_order,i,k)<<" ";
+      }
+      
+      log <<"  "<<endmsg;
+      
+      for(int m=0;m<extract_nhit;m++){
+	m_extract_intc->push_back(getPattintc(bank_order,i,m));
+	m_extract_intphi->push_back(getPattintphi(bank_order,i,m));
+	m_extract_intd0->push_back(getPattintd0(bank_order,i,m));
+	m_extract_intz0->push_back(getPattintz0(bank_order,i,m));
+	m_extract_inteta->push_back(getPattinteta(bank_order,i,m));
+      }
+
+      // fill the output TTree after the reduce information has been informed
+      m_tree->Fill();
+    }
+    // save the result in the output TTree
+    Lfile->cd();
+    m_tree->Write();
+    gROOT->cd();
+
+    delete m_tree;
+    m_tree=NULL;
+  }// loop over regions
+
+  free(extract_Sec);
+  free(extract_hash);
+  free(extract_vec);
+  free(extract_xC);
+  free(extract_xD);
+  free(extract_xPhi);
+  free(extract_xCoto);
+  free(extract_xZ);
+  free(extract_covx);
+}
+
+void FTKConstGenAlgo::make_subregion()
+{
+  MsgStream log(msgSvc(), name());
+
+  char **sector_filename;
+  char **gcon_filename;
+  FILE *sector_file;
+  FILE *gcon_file;
+  
+  sector_filename = (char **) malloc(m_nsubregion*sizeof(char*));
+  gcon_filename = (char **) malloc(m_nsubregion*sizeof(char*));
+  for(int i=0;i<m_nsubregion;i++){
+    sector_filename[i] = (char *) calloc(50,sizeof(char));
+    gcon_filename[i] = (char *) calloc(50,sizeof(char));
+  }
+
+  // sector file
+
+  for(unsigned int i=0;i<m_sfpath.size();i++){
+    int nlayer;
+    int nsector;
+    int **sector;
+    int *ntrack;
+    int brank;
+    int sectorID;
+    
+    const string &sfpath = m_sfpath[i];
+    ifstream slice_file(sfpath.c_str());
+    
+    slice_file >>nsector;
+    log << MSG::INFO <<" nsector =  " << nsector << endmsg;
+    
+    slice_file >>nlayer;
+    log << MSG::INFO <<" nlayer =  " << nlayer << endmsg;
+    sector = (int **) malloc(nsector*sizeof(int*));
+    ntrack=(int *) calloc(nsector,sizeof(int));
+    
+    for(int id=0;id<nsector;id++){
+      sector[id] =(int *) calloc(nlayer,sizeof(int));
+    }
+    
+    for(int id=0;id<nsector;id++){
+      slice_file >> sectorID;
+      if(id!=sectorID){log << MSG::FATAL <<" This file is bad format " << sfpath.c_str() << endmsg;}else{
+	for(int layer=0;layer<nlayer;layer++){
+	  slice_file >> sector[id][layer];
+	}
+	slice_file >>brank;
+	slice_file>>ntrack[id];
+      }
+      
+    }
+    
+    for(int sub=0;sub<m_nsubregion;sub++){
+      int sub_nsector;
+      sub_nsector=nsector/m_nsubregion;
+      if(sub<nsector%m_nsubregion){
+	sub_nsector=sub_nsector+1;
+      }
+      
+      sprintf(sector_filename[sub],"sectors_raw_%dL_%dM_reg%d_sub%d.patt",nlayer,m_nsubregion,i,sub);
+      sector_file = fopen(sector_filename[sub],"w");
+      fprintf(sector_file,"%d %d\n",sub_nsector,nlayer);
+      
+      for(int id=0;id<sub_nsector;id++){
+	fprintf(sector_file,"%d ",id);
+	for(int layer=0;layer<nlayer;layer++){
+	  fprintf(sector_file,"%d ", sector[id*m_nsubregion+sub][layer]);
+	}
+	fprintf(sector_file,"0 %d",ntrack[id*m_nsubregion+sub]);
+	fprintf(sector_file,"\n");
+      }
+      
+    }//for subregion
+  }// for region
+  
+  //sector file 
+  //gcon file
+
+  for(unsigned int i=0;i<m_gfpath.size();i++){
+    int nlayer;
+    int nsector;
+    int ndim=0,NDIM;
+    int *sectorID;
+    string tmp_e; 
+    string identifier;
+    geo_constants *tmp_const;
+    const string &gfpath = m_gfpath[i];
+    ifstream slice_file(gfpath.c_str());
+    
+    string init_line[10];
+    for(int j=0;j<6;j++){
+      getline(slice_file, init_line[j]);
+    }
+    slice_file>>nlayer;
+    getline(slice_file, init_line[6]);
+    getline(slice_file, init_line[6]);
+    slice_file>>nsector;    
+    getline(slice_file, init_line[7]);
+    getline(slice_file, init_line[7]);
+    slice_file>>NDIM;
+    getline(slice_file, init_line[8]);
+
+    if(nlayer==11 || nlayer==8) ndim=nlayer+3;//w/o IBL or 1st stage
+    else if(nlayer==12) ndim=nlayer+4;//IBL
+
+    tmp_const =(struct geo_constants *) malloc(nsector*sizeof(struct geo_constants));
+    sectorID=(int *) calloc(nsector,sizeof(int));
+    for(int j=0;j<nsector;j++){
+      tmp_const[j].Vd = (double *) calloc(ndim,sizeof(double));
+      tmp_const[j].Vc = (double *) calloc(ndim,sizeof(double));
+      tmp_const[j].Vf = (double *) calloc(ndim,sizeof(double));
+      tmp_const[j].Vz0 = (double *) calloc(ndim,sizeof(double));
+      tmp_const[j].Vo = (double *) calloc(ndim,sizeof(double));
+      tmp_const[j].kaverages = (double *) calloc((ndim-NPARS),sizeof(double));      
+      tmp_const[j].kernel = (double **) malloc((ndim-NPARS)*sizeof(double *));
+      for(int k=0;k<ndim-NPARS;k++){
+	tmp_const[j].kernel[k] = (double *) calloc(ndim,sizeof(double));
+      }
+    }
+    
+    int id=0;
+    while(1){
+      if(nsector==id){
+	break;
+      }
+      getline(slice_file,identifier);
+      if("sector"==identifier){
+	getline(slice_file,tmp_e);
+	istringstream is( tmp_e );
+	is>>sectorID[id];
+      }
+      
+      if(" Vc "==identifier){
+	for(int l=0;l<ndim;l++){
+	  getline(slice_file,tmp_e);
+	  istringstream is( tmp_e ); 
+	  is>>tmp_const[id].Vc[l];
+	}
+      }
+      if(" Vd "==identifier){
+	for(int l=0;l<ndim;l++){
+	  getline(slice_file,tmp_e);
+	  istringstream is( tmp_e ); 
+	  is>>tmp_const[id].Vd[l];
+	}
+      }
+      if(" Vf "==identifier){
+	for(int l=0;l<ndim;l++){
+	  getline(slice_file,tmp_e);
+	  istringstream is( tmp_e ); 
+	  is>>tmp_const[id].Vf[l];
+	}
+      }
+      if(" Vz0 "==identifier){
+	for(int l=0;l<ndim;l++){
+	  getline(slice_file,tmp_e);
+	  istringstream is( tmp_e ); 
+	  is>>tmp_const[id].Vz0[l];
+	}
+      }
+
+      if(" Vo "==identifier){
+	for(int l=0;l<ndim;l++){
+	  getline(slice_file,tmp_e);
+	  istringstream is( tmp_e ); 
+	  is>>tmp_const[id].Vo[l];
+	}
+      }
+      
+      if("kaverages"==identifier){
+	for(int l=0;l<ndim-NPARS;l++){
+	  getline(slice_file,tmp_e);
+	  istringstream is( tmp_e ); 
+	  is>>tmp_const[id].kaverages[l];
+	}
+      }
+      
+      if("kernel"==identifier){
+	for(int l=0;l<ndim-NPARS;l++){
+	  for(int m=0;m<ndim;m++){
+	    getline(slice_file,tmp_e);
+	    istringstream is( tmp_e ); 
+	    is>>tmp_const[id].kernel[l][m];
+	  }
+	}
+      }
+      
+      if("Cc"==identifier){
+	getline(slice_file,tmp_e);
+	istringstream is( tmp_e ); 
+	is>>tmp_const[id].Cc;
+      }
+
+      if("Cd"==identifier){
+	getline(slice_file,tmp_e);
+	istringstream is( tmp_e ); 
+	is>>tmp_const[id].Cd;
+      }
+      
+      if("Cf"==identifier){
+	getline(slice_file,tmp_e);
+	istringstream is( tmp_e ); 
+	is>>tmp_const[id].Cf;
+      }
+
+      if("Cz0"==identifier){
+	getline(slice_file,tmp_e);
+	istringstream is( tmp_e ); 
+	is>>tmp_const[id].Cz0;
+      }
+      
+      if("Co"==identifier){
+	getline(slice_file,tmp_e);
+	istringstream is( tmp_e ); 
+	is>>tmp_const[id].Co;
+	id++;
+      }
+    }//read ASCII file 
+    
+    for(int sub=0;sub<m_nsubregion;sub++){
+      int sub_nsector;
+      sub_nsector=nsector/m_nsubregion;
+      if(sub<nsector%m_nsubregion){
+	sub_nsector=sub_nsector+1;
+      }
+      sprintf(gcon_filename[sub],"corrgen_raw_%dL_%dM_reg%d_sub%d.gcon",nlayer,m_nsubregion,i,sub);
+      gcon_file = fopen(gcon_filename[sub],"w");
+      for(int j=0;j<6;j++){
+	fprintf(gcon_file,init_line[j].c_str());
+	fprintf(gcon_file,"\n");
+      }
+      fprintf(gcon_file," %d\n",nlayer);
+      fprintf(gcon_file,init_line[6].c_str());
+      fprintf(gcon_file,"\n");
+      fprintf(gcon_file,"%d\n",sub_nsector);
+      fprintf(gcon_file,init_line[7].c_str());
+      fprintf(gcon_file,"\n");
+      fprintf(gcon_file," %d\n",2);
+      fprintf(gcon_file,init_line[8].c_str());
+      for(int id=0;id<sub_nsector;id++){
+	fprintf(gcon_file,"sector\n");
+	fprintf(gcon_file,"%d\n",id);
+	fprintf(gcon_file," Vc \n");
+	for(int k=0;k<ndim;k++){
+	  fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Vc[k]);
+	}
+	fprintf(gcon_file," Vd \n");
+	for(int k=0;k<ndim;k++){
+	  fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Vd[k]);
+	}
+	fprintf(gcon_file," Vf \n");
+	for(int k=0;k<ndim;k++){
+	  fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Vf[k]);
+	}
+	fprintf(gcon_file," Vz0 \n");
+	for(int k=0;k<ndim;k++){
+	  fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Vz0[k]);
+	}
+	fprintf(gcon_file," Vo \n");
+	for(int k=0;k<ndim;k++){
+	  fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Vo[k]);
+	}
+	fprintf(gcon_file,"kaverages\n");
+	for(int k=0;k<ndim-NPARS;k++){
+	  fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].kaverages[k]);
+	}
+	fprintf(gcon_file,"kernel\n");
+	for(int k=0;k<ndim-NPARS;k++){
+	  for(int m=0;m<ndim;m++){
+	    fprintf(gcon_file,"%e \n",tmp_const[id*m_nsubregion+sub].kernel[k][m]);
+	  }
+	}
+	fprintf(gcon_file,"Cc\n");
+	fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Cc);
+	fprintf(gcon_file,"Cd\n");
+	fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Cd);
+	fprintf(gcon_file,"Cf\n");
+	fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Cf);
+	fprintf(gcon_file,"Cz0\n");
+	fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Cz0);
+	fprintf(gcon_file,"Co\n");
+	fprintf(gcon_file,"%e\n",tmp_const[id*m_nsubregion+sub].Co);
+      }
+            
+      
+    }//for subregion
+  }// for region
+  //gcon file
+
+
+}
+
+int FTKConstGenAlgo::mtx_eigen(int dim, double *mtx_v, double *eigval_v, double *eigvecs_v) {
+  TMatrixD mtx(dim,dim,mtx_v);
+
+  // Catching singular matrix
+  TMatrixD chk_mtx(dim,dim,mtx_v);
+  TDecompLU dc(chk_mtx);
+  int status = dc.InvertLU(chk_mtx,MTX_TOLERANCE);
+  if(!status) return -1;
+  // Catching singular matrix
+  
+  TVectorD eigvals(dim);
+  TMatrixD eigvecs(dim,dim);
+  
+  // calculate eigvecs and aigvals
+  eigvecs = mtx.EigenVectors(eigvals);
+    
+  // copy into the vectors in the right mode: autovetors per columun
+  double *tmpv = eigvals.GetMatrixArray();
+  //  double *tmpm = eigvecs.GetMatrixArray();
+
+  for (int i=0;i<dim;++i){
+    for (int j=0;j<dim;++j) {
+      eigvecs_v[i*dim+j] = eigvecs[j][dim-1-i];
+    }
+  }
+
+  for (int i=0;i<dim;++i) {
+    eigval_v[i] = tmpv[dim-1-i];
+  }
+  return 0;
+}
+
+
+int FTKConstGenAlgo::mtx_invert(int dim, double *mtx_v) {
+  TMatrixD mtx(dim,dim,mtx_v);
+  
+  // Catching singular matrix
+  TMatrixD chk_mtx(dim,dim,mtx_v);
+  TDecompLU dc(chk_mtx);
+  int status = dc.InvertLU(chk_mtx,MTX_TOLERANCE);
+  if(!status) return -1;
+  // Catching singular matrix
+
+  //mtx.Print();
+  mtx.Invert();
+
+  double *tmpm = mtx.GetMatrixArray();
+  for (int i=0;i<dim;++i) for (int j=0;j<dim;++j) {
+    mtx_v[i*dim+j] =tmpm[i*dim+j];
+  }
+
+  return 0;
+}
+
+// FlagAK: If constants are bad (eg, contain "nan"), fill them up with zeros!
+void FTKConstGenAlgo::nullifyConstants(int sector,int ndim) {
+  int i;
+  int j;
+  //printf("Sector %d has bad constants; nullifying them!\n",sector);
+  // to don't leave unitialized the variables
+  // fill of zero, matrix ad vector
+  gcorth[sector].Cc = geo_const[sector].Cc = .0;
+  gcorth[sector].Cd = geo_const[sector].Cd = .0;
+  gcorth[sector].Cf = geo_const[sector].Cf = .0;
+  gcorth[sector].Cz0 = geo_const[sector].Cz0 = .0;
+  gcorth[sector].Co = geo_const[sector].Co = .0;
+  
+  for (i=0;i<ndim;++i) {
+    gcorth[sector].Vc[i] = geo_const[sector].Vc[i] = .0;
+    gcorth[sector].Vd[i] = geo_const[sector].Vd[i] = .0;
+    gcorth[sector].Vf[i] = geo_const[sector].Vf[i] = .0;
+    gcorth[sector].Vz0[i] = geo_const[sector].Vz0[i] = .0;
+    gcorth[sector].Vo[i] = geo_const[sector].Vo[i] = .0;
+  }
+  
+  for (i=0;i<ndim-NPARS;++i) {
+    geo_const[sector].kaverages[i] = .0;
+    for (j=0;j<ndim;++j)
+      geo_const[sector].kernel[i][j] = .0;
+  }
+  
+  geo_const[sector].real = 0; // flag for validate constants 
+  
+  return;
+}
+
+void FTKConstGenAlgo::sigmad(double *geoconstvect/*, double **marray*/, double **marrayinv,double *v,int ndim)
+{
+  //int i,k,j;
+  //double *vd,*sreturn,sigmadreturn,ssd;
+
+  int i,j;
+  double *vd;
+
+  if ((vd = (double*) calloc(ndim,sizeof(double)))==NULL) {
+     //  svt_err(1,"main:error allocating vd") ;
+  }
+  for(i=0;i<ndim;i++)
+    {
+      for(j=0;j<ndim;j++)
+	vd[i] += marrayinv[i][j]*v[j];
+    }
+
+  for(i = 0;i < ndim;i++) 
+    geoconstvect[i] = vd[i];
+
+  free(vd);
+}
+
+float FTKConstGenAlgo::proj(double *vec1, double *vec2, int size)
+{
+  float total=0;
+  int i;
+  for(i=0;i<size;i++)
+    total+=vec1[i]*vec2[i];
+  return (float)total;
+}
+
+// FlagAK: Check if constants are bad (eg, contain "nan")
+int FTKConstGenAlgo::failedConstants(int sector,int ndim) {
+  MsgStream log(msgSvc(), name());
+
+  int status = 0;
+  int i;
+  int j;
+
+  //check if the constants are reasonable
+  //Cc
+  if(TMath::IsNaN(gcorth[sector].Cc)) {
+    log << MSG::DEBUG << "Bad gcorth[" << sector << "].Cc: " << gcorth[sector].Cc << endmsg;
+    status++;
+  }
+  if(TMath::IsNaN(geo_const[sector].Cc)) {
+    //  if(TMath::IsNaN(geo_const[sector].Cc) || geo_const[sector].Cc==0) {//tomoya
+    log << MSG::DEBUG << "Bad geo_const[" << sector << "].Cc: " << geo_const[sector].Cc << endmsg;
+    status++;
+  }
+  
+  //Cd
+  if(TMath::IsNaN(gcorth[sector].Cd)) {
+    log << MSG::DEBUG << "Bad gcorth[" << sector << "].Cd: " << gcorth[sector].Cd << endmsg;
+    status++;
+  }
+  if(TMath::IsNaN(geo_const[sector].Cd)) {
+    log << MSG::DEBUG << "Bad geo_const[" << sector << "].Cd: " << geo_const[sector].Cd << endmsg;
+    status++;
+  }
+
+  //Cf
+  if(TMath::IsNaN(gcorth[sector].Cf)) {
+    log << MSG::DEBUG << "Bad gcorth[" << sector << "].Cf: " << gcorth[sector].Cf << endmsg;
+    status++;
+  }
+  if(TMath::IsNaN(geo_const[sector].Cf)) {
+    log << MSG::DEBUG << "Bad geo_const[" << sector << "].Cf: " << geo_const[sector].Cf << endmsg;
+    status++;
+  }
+
+  //Cz0
+  if(TMath::IsNaN(gcorth[sector].Cz0)) {
+    log << MSG::DEBUG << "Bad gcorth[" << sector << "].Cz0: " << gcorth[sector].Cz0 << endmsg;
+    status++;
+  }
+  if(TMath::IsNaN(geo_const[sector].Cz0)) {
+    log << MSG::DEBUG << "Bad geo_const[" << sector << "].Cz0: " << geo_const[sector].Cz0 << endmsg;
+    status++;
+  }
+
+  //Co
+  if(TMath::IsNaN(gcorth[sector].Co)) {
+    log << MSG::DEBUG << "Bad gcorth[" << sector << "].Co: " << gcorth[sector].Co << endmsg;
+    status++;
+  }
+  if(TMath::IsNaN(geo_const[sector].Co)) {
+    log << MSG::DEBUG << "Bad geo_const[" << sector << "].Co: " << geo_const[sector].Co << endmsg;
+    status++;
+  }
+
+  for (i=0;i<ndim;++i) {
+    //Vc
+    if(TMath::IsNaN(gcorth[sector].Vc[i])) {
+      log << MSG::DEBUG << "Bad gcorth[" << sector << "].Vc[" << i << "]: " << gcorth[sector].Vc[i] << endmsg;
+      status++;
+    }
+    if(TMath::IsNaN(geo_const[sector].Vc[i])) {
+      log << MSG::DEBUG << "Bad geo_const[" << sector << "].Vc[" << i << "]: " << geo_const[sector].Vc[i] << endmsg;
+      status++;
+    }
+
+    //Vd
+    if(TMath::IsNaN(gcorth[sector].Vd[i])) {
+      log << MSG::DEBUG << "Bad gcorth[" << sector << "].Vd[" << i << "]: " << gcorth[sector].Vd[i] << endmsg;
+      status++;
+    }
+    if(TMath::IsNaN(geo_const[sector].Vd[i])) {
+      log << MSG::DEBUG << "Bad geo_const[" << sector << "].Vd[" << i << "]: " << geo_const[sector].Vd[i] << endmsg;
+      status++;
+    }
+
+    //Vf
+    if(TMath::IsNaN(gcorth[sector].Vf[i])) {
+      log << MSG::DEBUG << "Bad gcorth[" << sector << "].Vf[" << i << "]: " << gcorth[sector].Vf[i] << endmsg;
+      status++;
+    }
+    if(TMath::IsNaN(geo_const[sector].Vf[i])) {
+      log << MSG::DEBUG << "Bad geo_const[" << sector << "].Vf[" << i << "]: " << geo_const[sector].Vf[i] << endmsg;
+      status++;
+    }
+
+    //Vz0
+    if(TMath::IsNaN(gcorth[sector].Vz0[i])) {
+      log << MSG::DEBUG << "Bad gcorth[" << sector << "].Vz0[" << i << "]: " << gcorth[sector].Vz0[i] << endmsg;
+      status++;
+    }
+    if(TMath::IsNaN(geo_const[sector].Vz0[i])) {
+      log << MSG::DEBUG << "Bad geo_const[" << sector << "].Vz0[" << i << "]: " << geo_const[sector].Vz0[i] << endmsg;
+      status++;
+    }
+
+    //Vo
+    if(TMath::IsNaN(gcorth[sector].Vo[i])) {
+      log << MSG::DEBUG << "Bad gcorth[" << sector << "].Vo[" << i << "]: " << gcorth[sector].Vo[i] << endmsg;
+      status++;
+    }
+    if(TMath::IsNaN(geo_const[sector].Vo[i])) {
+      log << MSG::DEBUG << "Bad geo_const[" << sector << "].Vo[" << i << "]: " << geo_const[sector].Vo[i] << endmsg;
+      status++;
+    }
+
+  }
+
+  for (i=0;i<ndim-NPARS;++i) {
+    if(TMath::IsNaN(geo_const[sector].kaverages[i])) {
+      log << MSG::DEBUG << "Bad geo_const[" << sector << "].kaverages[" << i << "]: " << geo_const[sector].kaverages[i] << endmsg;
+      status++;
+    }
+    for (j=0;j<ndim;++j)
+      if(TMath::IsNaN(geo_const[sector].kernel[i][j])) {
+	log << MSG::DEBUG << "Bad geo_const[" << sector << "].kernel[" << i << "][" << j << "]: " << geo_const[sector].kernel[i][j];
+	status++;
+      }
+  }
+
+  return status;
+}
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRoot.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRoot.cxx
new file mode 100644
index 00000000000..60c0daadf7f
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRoot.cxx
@@ -0,0 +1,1059 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/FTKPattGenRoot.h"
+#include <fstream>
+#include <cmath>
+#include <algorithm>
+#include <TFile.h>
+#include <TDirectory.h>
+#include "TrigFTKSim/FTKSetup.h"
+#include "TrigFTKSim/FTKRootFile.h"
+#include <TFile.h>
+#include "TrigFTKSim/FTKTrack.h"
+// #include "TrigFTKSim/FTKPatternBySector.h"
+// #include "TrigFTKSim/ftk_dcap.h"
+#include "TrigFTKSim/ftk_dcap_helper.h"
+#include "TrigFTKBankGen/decodeEtacode.h"
+
+#ifdef DEBUG_BEAMSPOT
+#include "TrkGeometry/MagneticFieldProperties.h"
+#endif
+
+/* class FTKPattGenRoot
+ *
+ * Generate patterns from constants.
+ * authors: D. Britzger, after PattBankGenAlgo by L. Luongo, G. Volpi, ....
+ *
+ * Usage:
+ *    FTKPattGenRoot pattgen(pmap,ssmap,sectorslice,rmap,m_curreg,constbank);
+ *    pattgen.SetRootOutput("patterns.root");
+ *  repeated times:
+ *    pattgen.trackInvertion(m_trials,true);
+ *    // patterns will be written when pattgen is destroyed
+ * Alternative usage: Use pointers and 'delete pattgen'.
+ *  
+ * If desired write out also ascii format:
+ *     (not yet implemented)
+ *  
+ */
+
+using namespace std;
+
+//================== class FTKPattGenRoot =================
+
+
+
+FTKPattGenRoot::FTKPattGenRoot(int curreg, FTKSSMap* ssmap, FTKSectorSlice* slices, FTKConstantBank* constbank,int keep7of8,double tolerance7of8
+#ifdef DEBUG_BEAMSPOT
+                  ,ToolHandle<Trk::IPropagator> *propagator
+#endif
+                               )
+   : FTKLogging("FTKPattGenRoot"), m_curreg(curreg), m_ssmap(ssmap),
+     m_sectorslice(slices), m_constbank(constbank),
+     m_RndGauss(0),
+     m_RndFlat(0),
+     m_output(0),
+     m_patternWriter(0),
+     m_keep7of8(keep7of8),m_tolerance7of8(tolerance7of8),
+     m_d0_alpha(0.)
+#ifdef DEBUG_BEAMSPOT
+,m_propagator(propagator)
+#endif
+ {
+   /************************************************
+    *
+    *  Create patterns from constants
+    *  Input parameters are:  
+    *    + Current region:          (int)curreg
+    *    + SS map:                  ssmap (how many strips, pixels are in each layer's modules)
+    *    + Sector slices:           slices
+    *    + Geometry constants:      constbank
+    *  
+    ************************************************/
+
+   SetSliceParameters(); // init slice parameters
+   m_constbank->prepareInvConstants();
+
+   m_select = ModuleGeometry; //FTKPattGenRoot::RndSector;
+
+   ostream & out=
+      (Info("FTKPattGenRoot")<<"keep 7/8 patterns for missing planes [");
+   unsigned mask=keep7of8;
+   for(int missing =0;mask;missing ++,mask>>=1) {
+      if(mask & 1) {
+         out<<" "<<missing;
+      }
+   }
+   out<<"]\n";
+}
+
+void FTKPattGenRoot::SetRandomNumberGenerator(CLHEP::HepRandomEngine* RndEng ) {
+   m_RndGauss=new CLHEP::RandGauss(RndEng);
+   m_RndFlat=new CLHEP::RandFlat(RndEng);
+}
+
+//___________________________________________________________________________________________ //
+FTKPattGenRoot::~FTKPattGenRoot() {
+   //! Destructor
+   //! Destroy pattern writer object to safe patterns to disk
+   Info("~FTKPattGenRoot")<<"Deleting PatternWriter = write root-patterns to disk"<<endl;
+   if ( m_patternWriter) delete m_patternWriter;
+   if(m_output) delete m_output;
+}
+
+
+//___________________________________________________________________________________________ //
+const FTKPlaneMap* FTKPattGenRoot::pmap() const { 
+   return m_ssmap->getPlaneMap(); // same as m_rmap->getPlaneMap();
+}
+
+
+//___________________________________________________________________________________________ //
+void FTKPattGenRoot::DeleteMaps() { 
+   // delete pointers of input files
+   m_ssmap=NULL;
+   Info("DeleteMaps")<<"Delete m_sectorslice"<<endl;
+   if (m_sectorslice) delete m_sectorslice;
+   m_sectorslice=NULL;
+   Info("DeleteMaps")<<"Delete m_constbank"<<endl;
+   if (m_constbank) delete m_constbank;
+   m_constbank=NULL;
+}
+
+
+//___________________________________________________________________________________________ //
+bool FTKPattGenRoot::GoodTrack(const FTKTrack& track, int isector, FTKPatternWithSector* tmp_curpatt,int *missingPlanesPtr,double *distancePtr) {
+   /**
+   *   Check if track is in sector
+   *   returns true or false
+   *   tmp_curpatt is filled coordinates
+   */
+   int missing=0;
+   double distance=0.0;
+   for (int p=0; p<pmap()->getNPlanes(); ++p) {
+      int ndim = pmap()->getDim(p,1)==-1 ? 1 : 2;
+      FTKHit hit(ndim);
+      int ssid=-1;
+      // potential BUG with HWMODEID=2
+      // the section number and module number are not known
+      int section=0;
+      int phimod=0;
+      int etamod=0;
+      if(FTKSetup::getFTKSetup().getHWModeSS()==0) {
+         hit.setSector(m_sectorbank[isector].GetHit(p));
+	 hit.setITkMode(FTKSetup::getFTKSetup().getITkMode());
+         section=hit.getSection();
+         phimod=hit.getPhiModule();
+         etamod=hit.getEtaModule();
+      }
+      double x_width=m_ssmap->getMap(p,section,phimod).m_phiwidth;
+      int ix = pmap()->getDim(p,0);
+      double x_track = track.getCoord(ix);
+      double x_ssid=x_track;
+      if(x_ssid<0) {
+         x_ssid=0.;
+         missing |= (1<<p);
+      } else if(x_ssid>=x_width) {
+         x_ssid=x_width-1.;
+         missing |= (1<<p);
+      }
+      double y_width=0.,y_track=0.,y_ssid=0.;
+      if(ndim==2) {
+         y_width=m_ssmap->getMap(p,section,etamod).m_etawidth;
+         int iy = pmap()->getDim(p,1);
+         y_track = track.getCoord(iy);
+         y_ssid=y_track;
+         if(y_ssid<0.) {
+            y_ssid=0.;
+            missing |= (1<<p);
+         } else if(y_ssid>=y_width) {
+            y_ssid=y_width-1;
+            missing |= (1<<p);
+         }
+      }
+      if (FTKSetup::getFTKSetup().getHWModeSS()==0) {
+         hit.setCoord(0, x_ssid);
+         if ( ndim==2) {
+            hit.setCoord(1, y_ssid);
+         }
+         // build hit
+         hit.setPlane(p);
+         hit.setEtaWidth(1);
+         hit.setPhiWidth(1);	 
+         ssid=m_ssmap->getSSGlobal(hit);
+      } else { 
+         // HWMIDEID==2
+         int globalModuleId=m_sectorbank[isector].GetHit(p);
+         int localModuleID=m_ssmap->getRegionMap()
+            ->getLocalId(m_curreg,p,globalModuleId);
+         if(localModuleID<0) {
+            cout<<"globalModuleId="<<globalModuleId
+                <<" -> local="<<localModuleID<<"\n";
+         }
+         if(ndim==2) {
+            ssid=m_ssmap->compressed_ssid_word_pixel
+               (localModuleID,p,section,x_ssid,y_ssid);
+         } else {
+            ssid=m_ssmap->compressed_ssid_word_strip
+               (localModuleID,p,section,x_ssid);
+         }
+      }
+      tmp_curpatt->SetHit(p,ssid);
+      if(missing & (1<<p)) {
+         double d=(x_ssid-x_track)/x_width;
+         if(fabs(d)>distance) distance=d;
+         if(ndim==2) {
+            d=(y_ssid-y_track)/y_width;
+            if(fabs(d)>distance) distance=d;
+         }
+      }
+   } // for n-planes
+   if(missingPlanesPtr) *missingPlanesPtr=missing;
+   if(distancePtr) *distancePtr=distance;
+   return !missing;
+
+}
+
+
+//___________________________________________________________________________________________ //
+uint64_t FTKPattGenRoot::trackInvertion(u_int64_t ntrials, bool smear) {
+   //!
+   //! 'main' function ot do the track inversion
+   //! and generate patterns
+   //!
+
+   if (m_sectorbank.empty()) {
+      Error("trackInvertion")<<"No sectors given. Please call ReadSectorFile(filename) first."<<endl;
+      return 0;
+   }
+   FTKTrack track;
+   track.setNCoords(pmap()->getTotalDim());
+   static FTKPatternWithSector* tmp_curpatt = new FTKPatternWithSector(pmap()->getNPlanes());
+   static vector<double> constr(m_constbank->getNConstr()); // filled with 0
+
+   uint64_t nFound=0;
+   uint64_t nFound7of8=0;
+   uint64_t nSuccTrials=0;
+
+   ofstream *gap_monitoring=0;
+   ofstream *overlap_monitoring=0;
+   ofstream *trackpar_monitoring=0;
+#ifdef DEBUG_GAP_MONITORING
+   ostringstream gap_file_name;
+   gap_file_name<<"gap_monitoring_reg"<<m_curreg<<".txt";
+   gap_monitoring=new ofstream(gap_file_name.str().c_str());
+#endif
+#ifdef DEBUG_OVERLAP
+   ostringstream overlap_file_name;
+   overlap_file_name<<"overlap_monitoring_reg"<<m_curreg<<".txt";
+   overlap_monitoring=new ofstream(overlap_file_name.str().c_str());
+#endif
+#ifdef DEBUG_BEAMSPOT
+   ostringstream trackpar_file_name;
+   trackpar_file_name<<"trackpar_monitoring_reg"<<m_curreg<<".txt";
+   trackpar_monitoring=new ofstream(trackpar_file_name.str().c_str());
+#endif
+
+   for (u_int64_t t=0; t<ntrials; ++t) {
+      nSuccTrials++;
+      if ( nSuccTrials%1000000==0 )
+	 Info("trackInvertion()")
+            <<"Number of all trials: "<<nSuccTrials
+            <<". Number of successful trials: "<<nFound
+            <<" with 7/8: "<<nFound7of8<<endl; //nFound==t
+      // build track with random numbers
+      GetRandomTrack(track); 
+      // Convert phi to the format used in the constants calculations
+      ConvertPhi(track);
+     
+      vector<int>* sectors =  m_sectorslice->searchSectors(track);
+      //m_sectorHist->Fill((Double_t)sectors->size());
+      if (sectors->size() == 0) {
+	 t--; // we want to have ntrials patterns (also below)
+	 delete sectors;
+	 continue;
+      } 
+
+      // Generate constraints (random numbers from the standard Gaussian Distribution or 0)
+      if (smear) 
+	 for (unsigned int i=0; i<constr.size(); ++i) 
+	    constr[i] = getRandomGaus();
+
+      // loop over found sectors
+      std::vector<FTKPatternWithSector> found_patterns,found_patterns7of8;
+      std::map<int,pair<int,double> > info7of8;
+      for ( auto isec : *sectors ) {
+	 tmp_curpatt->SetSectorID(isec); // not available in FTKPatternWithCoverage
+	 tmp_curpatt->SetCoverage(1);
+	 m_constbank->invlinfit(isec, track, &constr[0]); // set: track.setCoord
+         int missingPlanes=0;
+         double distance=0.;
+	 if ( GoodTrack(track,isec,tmp_curpatt,&missingPlanes,&distance) ) {
+	    found_patterns.push_back(*tmp_curpatt);
+	 } else {
+            for(int missingPlane=0;missingPlane<pmap()->getNPlanes();
+                missingPlane++) {
+               // check whetrher 7/8 is allowed for this plane
+               if(!(m_keep7of8 & (1<<missingPlane))) continue;
+               // check whether there is exactly one hit missing in this plane
+               if(missingPlanes != (1<<missingPlane)) continue;
+               // check wthere distance is small enough
+               if(fabs(distance)>m_tolerance7of8) continue;
+
+               // check whether this is the first 7/8 pattern
+               //   for the given missing plane
+               std::map<int,pair<int,double> >::iterator infoPtr=
+                  info7of8.find(missingPlane);
+               if(infoPtr!=info7of8.end()) {
+                  // previous pattern exists
+                  if( fabs(distance)<fabs((*infoPtr).second.second)) {
+                     // new hit has a smaller distance, replace
+                     // old pattern
+                     (*infoPtr).second.second= distance;
+                     found_patterns7of8[(*infoPtr).second.first]=
+                        *tmp_curpatt;
+                  }
+               } else {
+                  // first 7/8 pattern for this plane, always store it
+                  info7of8[missingPlane]=
+                     make_pair(found_patterns7of8.size(),distance);
+                  found_patterns7of8.push_back(*tmp_curpatt);
+               }
+            }
+         }
+      }
+
+      // if there is no 8/8 pattern, try 7/8
+      bool is7of8=false;
+      if(found_patterns.empty() && m_keep7of8) {
+         found_patterns=found_patterns7of8;
+         is7of8=true;
+      } else {
+         if(overlap_monitoring && found_patterns.size()>1) {
+            (*overlap_monitoring)<<found_patterns.size();
+            for(unsigned i=0;i<found_patterns.size();i++) {
+               (*overlap_monitoring)
+                  <<" "<<found_patterns[i].GetSectorID();
+            }
+            (*overlap_monitoring)<<"\n";
+         }
+      }
+      if(gap_monitoring && is7of8 && info7of8.size()) {
+         (*gap_monitoring)<< info7of8.size()<<"\n";
+         for(std::map<int,pair<int,double> >::const_iterator infoPtr=
+                info7of8.begin();infoPtr!=info7of8.end();infoPtr++) {
+            int isector=found_patterns[(*infoPtr).second.first].GetSectorID();
+            int moduleID=m_sectorbank[isector].GetHit((*infoPtr).first);
+            (*gap_monitoring)
+               <<(*infoPtr).first
+               <<" "<<moduleID
+               <<" "<<(*infoPtr).second.second<<"\n";
+            gap_monitoring->flush();
+         }
+      }
+
+      OverlapRemoval(found_patterns ); 
+
+      // patterns found? keep it following the selection criterion
+      if ( !found_patterns.empty() ) {
+	 // sector selection
+         unsigned patt=0;
+	 if ( m_select == FTKPattGenRoot::RndSector ) {
+	    // prepare to iterate on the list of sector IDs
+	    patt = (unsigned int)(found_patterns.size() * getRandom());//m_pEng->flat());
+            if(patt>=found_patterns.size()) patt=found_patterns.size();
+	 } else if((m_select==ModuleGeometry)||
+                   (m_select==ModuleGeometrySmallestSector)||
+                   (m_select==ModuleGeometryBestMatch)) {
+            if(FTKSetup::getFTKSetup().getHWModeSS()!=2) {
+               Fatal("trackInvertion")
+                  <<"Selector="<<m_select<<" only implemented for HDMODEID==2\n";
+            }
+            // for each candidate, calculate a weight 0<w<1
+            vector<double> weight(found_patterns.size());
+            unsigned nFound=0;
+            vector<unsigned> exactMatch;
+            static double const B_FACTOR=-0.3*2.083;// conversion factor 1/Mev -> 1/mm
+            double rho=B_FACTOR*track.getHalfInvPt() *(2.0);
+            for(unsigned ipatt=0;ipatt<found_patterns.size();ipatt++) {
+               double w=1.0;
+               bool found=true;
+               int isector=found_patterns[ipatt].GetSectorID();
+               // the weight w is the a product of the weights from each plane
+               for (int p=0; p<pmap()->getNPlanes(); ++p) {
+                  // skip pixel planes - for sime reason it does not work
+                  if(pmap()->getDim(p,1)!=-1) continue;
+                  int id=m_sectorbank[isector].GetHit(p);
+                  // lookup geometry by module ID
+                  map<int,RZminmax_t>::const_iterator irz=
+                     m_moduleBounds.find(id);
+                  if(irz==m_moduleBounds.end()) {
+                     // module not found
+                     found=false;
+                  } else {
+                     RZminmax_t const &rz=(*irz).second;
+                     // rMin,rMax and zMin,zMax are the 
+                     // module bounds in r,z
+                     float dz=rz.zMax-rz.zMin;
+                     float dr=rz.rMax-rz.rMin;
+                     // track parameters in r,z
+                     double cotTh=track.getCotTheta();
+                     double z0=track.getZ0();
+                     // d is the distance from the border
+                     // in units of module size
+                     // if the track is inside bounds, d=0
+                     double d=0.0;
+                     if(dz>dr) {
+                        // barrel: module dimension in z is larger than in r
+                        double r=0.5*(rz.rMax+rz.rMin);
+                        // sagitta correction
+                        double rrho=r*rho;
+                        double s=r*(1.+rrho*rrho/24.);
+                        double z=s*cotTh+z0;
+                        if(z<rz.zMin) d=(rz.zMin-z)/dz;
+                        if(z>rz.zMax) d=(z-rz.zMax)/dz;
+                        /* cout<<"barr"<<p<<" "<<isector
+                            <<" "<<z<<" "<<rz.zMin<<" "<<rz.zMax
+                            <<" d="<<d<<"\n"; */
+                     } else {
+                        // endcap: module is smaller in z than in r
+                        double z=0.5*(rz.zMax+rz.zMin);
+                        double s=(z-z0)/cotTh;
+                        // sagitta correction
+                        double srho=s*rho;
+                        double r=s*(1.-srho*srho/24.);
+                        if(r<rz.rMin) d=(rz.rMin-r)/dr;
+                        if(r>rz.rMax) d=(r-rz.rMax)/dr;
+                        /*cout<<"endc"<<p<<" "<<isector
+                            <<" "<<s<<" "<<rz.rMin<<" "<<rz.rMax
+                            <<" d="<<d<<"\n"; */
+                     }
+                     if(d>0.0) {
+                        w *=TMath::Exp(-d*d*50.); 
+                     }
+                  }
+               }
+               if(found) {
+                  nFound++;
+               }
+               weight[ipatt]=w;
+               if(w>=1.0) exactMatch.push_back(ipatt);
+            }
+            // here: sectors where track is within all modules bounds
+            //       have weight=1
+            //     the indices are stored in: exactMatch
+            // other sectors have 0<weight<1
+            //     the weight is stored in weight[]
+            if(nFound!=found_patterns.size()) {
+               Fatal("trackInvertion")<<"some modules not found\n";
+            }
+            // throw a random number here, even if it is not sued
+            // -> algorithms can be compared event by event
+            double rndForSector=getRandom();
+            if(exactMatch.size()>0) {
+               // have an exact match
+               if((m_select==ModuleGeometrySmallestSector)||
+                  (m_select==ModuleGeometryBestMatch)) {
+                  // use smallest sector ID
+                  patt=exactMatch[0];
+               } else {
+                  // random selection
+                  unsigned i= (unsigned)(exactMatch.size() * rndForSector);
+                  if(i>=exactMatch.size()) i=exactMatch.size()-1;
+                  patt=exactMatch[i];
+               }
+            } else {
+               // no exact match
+               if(m_select==ModuleGeometryBestMatch) {
+                  // find sector with largest weight and use it
+                  double maxw=-1.;
+                  patt=0;
+                  for(unsigned ipatt=0;ipatt<found_patterns.size();ipatt++) {
+                     double w=weight[ipatt];
+                     if(w>maxw) {
+                        maxw=w;
+                        patt=ipatt;
+                     }
+                  }
+               } else {
+                  // random selection                  
+                  // select a pattern according to probability
+                  //   given by the pattern weight
+                  double wSum=0.0;
+                  for(unsigned ipatt=0;ipatt<found_patterns.size();ipatt++) {
+                     wSum+=weight[ipatt];
+                  }
+                  double threshold= wSum*rndForSector;
+                  for(patt=0;patt<found_patterns.size()-1;patt++) {
+                     threshold -=weight[patt];
+                     if(threshold<=0.0) break;
+                  }
+               }
+            }
+            static int print=30;
+            if(print) {
+               cout<<"candidates: [";
+               for(unsigned ipatt=0;ipatt<found_patterns.size();ipatt++) {
+                  cout<<" "<<weight[ipatt];
+               }
+               cout<<"] selected: "<<patt<<" w="<<weight[patt]<<"\n";
+               print--;
+               //if(!print) exit(0);
+            }
+	 } else {
+	    Fatal("trackInvertion")<<"Selector not yet implemented."<<endl;
+	 }
+
+         if ( m_patternWriter ) m_patternWriter->AppendPattern(found_patterns[patt]);
+         if(trackpar_monitoring) {
+#ifdef DEBUG_BEAMSPOT
+            Amg::Vector3D nominal(0.,0.,0.);
+            double theta=atan2(1.,track.getCotTheta());
+            Trk::Perigee trackpar
+               (track.getIP(),track.getZ0(),track.getPhi(),
+                theta,
+                2.*track.getHalfInvPt()*sin(theta),
+                Trk::PerigeeSurface(nominal));
+            
+            Trk::PerigeeSurface beamspot
+               (Amg::Vector3D(m_beamspot[0],m_beamspot[1],0.));
+
+            Trk::MagneticFieldProperties magnet
+               =Trk::MagneticFieldProperties(Trk::FullField);;
+            const Trk::TrackParameters* tP=
+               (*m_propagator)->propagate
+               (trackpar,beamspot,Trk::anyDirection, false,magnet);
+            double sinth=sin(tP->parameters()[Trk::theta]);
+#endif
+            
+            (*trackpar_monitoring)
+               <<track.getPhi()
+               <<" "<<2.*track.getHalfInvPt()
+               <<" "<<track.getIP()
+               <<" "<<track.getZ0()
+               <<" "<<track.getCotTheta()
+#ifdef DEBUG_BEAMSPOT
+               <<" "<< tP->parameters()[Trk::phi]
+               <<" "<< tP->parameters()[Trk::qOverP]/sinth
+               <<" "<< tP->parameters()[Trk::d0]
+               <<" "<< tP->parameters()[Trk::z0]
+               <<" "<< cos(tP->parameters()[Trk::theta])/sinth
+               <<" "<<m_d0BS<<" "<<m_z0BS
+#endif
+               <<"\n";
+#ifdef DEBUG_BEAMSPOT
+            delete tP;
+#endif
+         }
+         nFound++;
+         if(is7of8) nFound7of8++;
+      }
+      else {
+	 t--; // we want to have ntrials patterns (also above)
+      }
+      delete sectors;
+      
+   } // for ntrials
+   if(gap_monitoring) delete gap_monitoring;
+   if(overlap_monitoring) delete overlap_monitoring;
+   if(trackpar_monitoring) delete trackpar_monitoring;
+
+   return nSuccTrials;
+}
+
+
+//___________________________________________________________________________________________ // 
+void FTKPattGenRoot::OverlapRemoval(std::vector<FTKPatternWithSector>& patterns){
+   set<unsigned int> remove;
+   for ( unsigned int i = 0 ; i<patterns.size() ; i++ ) {
+      int s1 = patterns[i].GetSectorID();
+      for ( unsigned int j = i+1 ; j<patterns.size() ; j++ ) {
+	 int s2 = patterns[j].GetSectorID();
+	 int compsect = 0;
+	 if ( !remove.count(s1) && !remove.count(s2) ) { // one of the two is already listed
+	    if (m_overlap==0 ) compsect = 0 ; // no overlap removal
+	    else if (m_overlap==1 ) compsect = OverlapSectorBarrel( s1, s2);
+	    else if (m_overlap==2 ) compsect = OverlapSector( s1, s2);
+	    else printf("Warning. cannot understand m_overlap. Allowed values are 0,1,2 but is %d\n",m_overlap);
+	    //printf("(s1=%d,s2=%d)\tCOMPSECT=%d \n",s1,s2,compsect); 
+	    if ( compsect ==  1 ) remove.insert(i);
+	    if ( compsect == -1 ) remove.insert(j);
+	 }
+      }
+   }
+
+   if (!remove.empty() ) {
+      for (set<unsigned int>::iterator it=remove.end(); it!=remove.begin(); ) {
+	 it--;
+      }
+   }
+}
+
+
+//___________________________________________________________________________________________ // 
+void FTKPattGenRoot::RemovePattern(std::vector<FTKPatternWithSector>& patterns, unsigned int id) {
+   if ( patterns.empty() ) return; // nothing todo
+   patterns.erase(patterns.begin()+id);
+}
+
+
+//___________________________________________________________________________________________ // 
+int FTKPattGenRoot::OverlapSectorBarrel(int s1, int s2){
+   //! adapted from pe2sector.c
+   const FTKHitPattern& m1 = m_sectorbank[s1];
+   const FTKHitPattern& m2 = m_sectorbank[s2];
+   int score = 0;
+   int zero = 0;
+   
+   if(pmap()->getNPlanes()==4){
+      Fatal("OverlapSectorBarrel")<<"NPLANES=4 Not implemented.\n";
+   }
+   if(FTKSetup::getFTKSetup().getHWModeSS()!=0) {
+      Fatal("OverlapSectorBarrel")
+         <<"HWMODEID="<<FTKSetup::getFTKSetup().getHWModeSS()
+         <<" not implemented.\n";
+   }
+
+   for(int i = 0; i < pmap()->getNPlanes(); ++i) {
+      int section = SECTION_INT(m1.GetHit(i));
+      int ireg = m_ssmap->getRegionMap()->getNumRegions()-1;
+      int rmap_maxplane = m_ssmap->getRegionMap()->getRegionMapItem(ireg,i,section).getPhiTot()-1; //  crmap.map[crmap.regions-1][i][section].phi_tot-1; 
+
+      if(m1.GetHit(i)%1000 == m2.GetHit(i)%1000) {
+	 int diff = m1.GetHit(i)/1000 - m2.GetHit(i)/1000;
+        if(diff == 0)
+          zero++;
+        else if (diff == 1 || diff == -rmap_maxplane)
+          score++;
+        else if (diff == -1 || diff == rmap_maxplane)
+          score--;
+        else
+          return 0; // |diff|>1, no overlap
+
+      } else {
+        return 0; // diff eta, no overlap
+      }
+    }
+ 
+   if(score+zero == pmap()->getNPlanes() ) // complete overlap
+      return 1;
+   else if (zero-score == pmap()->getNPlanes()) // complete overlap reversed
+      return -1;
+   else
+      return 0; // no overlap
+}
+
+
+//___________________________________________________________________________________________ // 
+int FTKPattGenRoot::OverlapSector(int s1, int s2){
+   //! adapted from pe2sector.c
+   const FTKHitPattern& m1 = m_sectorbank[s1];
+   const FTKHitPattern& m2 = m_sectorbank[s2];
+
+   int score=0;
+   int zero=0;
+ 
+   if(pmap()->getNPlanes()==4){
+      Fatal("OverlapSector")<<"NPLANES=4 Not implemented.\n";
+   }
+   if(FTKSetup::getFTKSetup().getHWModeSS()!=0) {
+      Fatal("OverlapSector")
+         <<"HWMODEID="<<FTKSetup::getFTKSetup().getHWModeSS()
+         <<" not implemented.\n";
+   }
+   
+   // code adapted from pe2sector.c from stanalone code
+  for(int i = 0; i < pmap()->getNPlanes(); ++i) {
+     if( m1.GetHit(i) == m2.GetHit(i) ) { // Same module
+	zero++;
+     }
+     else { // Different module
+	int sdiff = SECTION_INT(m1.GetHit(i)) - SECTION_INT(m2.GetHit(i));
+	int pdiff = PHI_MOD_INT(m1.GetHit(i)) - PHI_MOD_INT(m2.GetHit(i));
+	int ediff = ETA_MOD_INT(m1.GetHit(i)) - ETA_MOD_INT(m2.GetHit(i));
+
+	if( ediff==0 && sdiff==0 ) { // Same eta and section, check phi
+	   int section = SECTION_INT(m1.GetHit(i));
+	   int ireg = m_ssmap->getRegionMap()->getNumRegions()-1;
+	   int rmap_maxplane = m_ssmap->getRegionMap()->getRegionMapItem(ireg,i,section).getPhiTot()-1; //  crmap.map[crmap.regions-1][i][section].phi_tot-1; 
+	   if (pdiff == 1 || pdiff == -rmap_maxplane)
+	      score++; // Phi overlap in favor of s2
+	   else if (pdiff == -1 || pdiff == rmap_maxplane)
+	      score--; // Phi overlap in favor of s1
+	   else
+	      return 0; // |diff|>1, no overlap
+	}
+	else if (sdiff != 0) { // Section overlap is ok for disks
+	   // If one is barrel and one endcap, take the barrel hit
+
+	        
+	   if (pmap()->getPlane(i,SECTION_INT(m1.GetHit(i))).getIsEndcap()
+	       && !pmap()->getPlane(i,SECTION_INT(m2.GetHit(i))).getIsEndcap()) {
+	      // Section overlap in favor of s2
+	      score++;
+	   }
+	   else if (!pmap()->getPlane(i,SECTION_INT(m1.GetHit(i))).getIsEndcap()
+		    && pmap()->getPlane(i,SECTION_INT(m2.GetHit(i))).getIsEndcap()) {
+	      // Section overlap in favor of s1
+	      score--;
+	   }
+	   else if (pmap()->getPlane(i,SECTION_INT(m1.GetHit(i))).getPDisk()
+		    == pmap()->getPlane(i,SECTION_INT(m2.GetHit(i))).getPDisk() ) {
+	      // Same physical disk, different section -- no overlap
+	      return 0;
+	   }
+	   else if ((CSIDE_INT(m1.GetHit(i)) && ASIDE_INT(m2.GetHit(i))) 
+		    || (ASIDE_INT(m1.GetHit(i)) && CSIDE_INT(m2.GetHit(i)))) {
+	      // Opposite sides of the detector -- no overlap
+	      return 0;
+	   }
+	   else {
+	      // Now we have 2 endcap hits on the same side. Take the lower-z one.
+	      if (pmap()->getPlane(i,SECTION_INT(m1.GetHit(i))).getPDisk()
+		  > pmap()->getPlane(i,SECTION_INT(m2.GetHit(i))).getPDisk()) {
+		 score++; // Section overlap in favor of s2
+	      }
+	      else {
+		 score--; // Section overlap in favor of s1
+	      }
+	   }
+
+	}
+	else {
+	   // Now we have ediff != 0 -- no overlap
+	   return 0;
+	}
+     } 
+  }
+
+  if(zero+score == pmap()->getNPlanes()) // complete overlap
+     return 1;
+  else if (zero-score == pmap()->getNPlanes()) // complete overlap reversed
+     return -1;
+  else
+     return 0; // no overlap  
+}
+
+
+//___________________________________________________________________________________________ // 
+void FTKPattGenRoot::SetRootOutput(const string& outfilename){
+   //! Set filename for output root file
+   if (m_patternWriter){
+      Warning("SetOutputFilename")<<"Pattern writer already initialized with a filename."<<endl;
+      delete m_patternWriter;
+   }
+   if(m_output) delete m_output;
+   m_output =
+      FTKRootFile::Instance()->CreateRootFile(outfilename.c_str());
+   if(!m_output) {
+      Fatal("SetRootOutput")<<" can not open file "<<outfilename<<"\n";
+   } else {
+      m_patternWriter = FTKPatternBySectorWriter::Factory(*m_output);
+      m_patternWriter->SetNLayers(pmap()->getNPlanes());
+   }
+   return;
+}
+
+
+//___________________________________________________________________________________________ //
+void FTKPattGenRoot::WriteMapsToFile() {
+   //! Write pmap to root-file
+   // check if filename is set
+   if ( !m_patternWriter ) {
+      Fatal("WriteMapsToFile") << "RootOutput not yet set."<<endl;
+   }
+   if ( !m_ssmap ) {
+      Fatal("WriteMapsToFile") << "ssmap not set."<<endl;
+   }
+   m_ssmap->WriteMapToRootFile(m_output, "TSP" );
+}
+
+
+//___________________________________________________________________________________________ //
+void FTKPattGenRoot::SetSliceParameters(double phi_min,double phi_max, double c_min,double c_max, 
+					double d0_min,double d0_max, double z0_min,double z0_max, 
+					double eta_min, double eta_max){
+   //! set slice parameters
+   //! Use +/- 999 for autotune parameters.
+   if ( !m_sectorslice ) {
+      Fatal("SetSliceParameters") << "*** Sector file must be specified first."<< endl;
+      exit(1);
+   }
+   m_phi_min = phi_min==-999. ? m_sectorslice->getAutotunePhiMin() : phi_min;
+   m_phi_max = phi_max== 999. ? m_sectorslice->getAutotunePhiMax() : phi_max;
+
+   m_c_min   = c_min==-999.   ? m_sectorslice->getAutotuneCMin() : c_min;//-0.000625;
+   m_c_max   = c_max== 999.   ? m_sectorslice->getAutotuneCMax() : c_max;// 0.000625;
+
+   m_d0_min  = d0_min==-999.  ? m_sectorslice->getAutotuneDMin() : d0_min;
+   m_d0_max  = d0_max== 999.  ? m_sectorslice->getAutotuneDMax() : d0_max;
+
+   m_z0_min  = z0_min==-999.  ? m_sectorslice->getAutotuneZ0Min() : z0_min;
+   m_z0_max  = z0_max== 999.  ? m_sectorslice->getAutotuneZ0Max() : z0_max;
+
+   m_eta_min = eta_min==-999. ? m_sectorslice->getAutotuneEtaMin() : eta_min;
+   m_eta_max = eta_max== 999. ? m_sectorslice->getAutotuneEtaMax() : eta_max;
+
+   // JW (2016.9.14) - Update the FTKSectorSlice object with these parameter ranges
+   if( phi_min != -999 ) m_sectorslice->setPhiMin( phi_min );
+   if( phi_max !=  999 ) m_sectorslice->setPhiMax( phi_max );
+   if( c_min != -999 ) m_sectorslice->setCMin( c_min );
+   if( c_max !=  999 ) m_sectorslice->setCMax( c_max );
+   if( d0_min != -999 ) m_sectorslice->setD0Min( d0_min );
+   if( d0_max !=  999 ) m_sectorslice->setD0Max( d0_max );
+   if( z0_min != -999 ) m_sectorslice->setZ0Min( z0_min );
+   if( z0_max !=  999 ) m_sectorslice->setZ0Max( z0_max );
+   if( eta_min != -999 ) m_sectorslice->setEtaMin( eta_min );
+   if( eta_max !=  999 ) m_sectorslice->setEtaMax( eta_max );
+   m_sectorslice->resetStepSizes();
+
+   Info("SetSliceParameters")<<"Phi: "<<m_phi_min<<" "<<m_phi_max<<"\n";
+   Info("SetSliceParameters")<<"Eta: "<<m_eta_min<<" "<<m_eta_max<<"\n";
+   Info("SetSliceParameters")<<"C:   "<<m_c_min<<" "<<m_c_max<<"\n";
+   Info("SetSliceParameters")<<"D0:  "<<m_d0_min<<" "<<m_d0_max<<"\n";
+   Info("SetSliceParameters")<<"Z0:  "<<m_z0_min<<" "<<m_z0_max<<"\n";
+
+}
+
+
+//___________________________________________________________________________________________ //
+double FTKPattGenRoot::getRandom(){
+   double rndm = m_RndFlat->fire();
+   return rndm;}
+
+
+//___________________________________________________________________________________________ //
+double FTKPattGenRoot::getRandomGaus(){
+   double rndm = m_RndGauss->fire();
+   return rndm;
+}
+
+
+//___________________________________________________________________________________________ //
+void FTKPattGenRoot::GetRandomTrack(FTKTrack& track){
+   //! Get random track using the sector parameters
+
+   track.setHalfInvPt(0.5*((m_c_max - m_c_min) * getRandom() + m_c_min)); // diff!?
+
+   track.setPhi( getRandom() * (m_phi_max - m_phi_min) + m_phi_min, false); //ok
+   track.setPhiRaw(track.getPhi(),false);
+
+   track.setCotTheta(TMath::SinH((m_eta_max - m_eta_min) * getRandom() + m_eta_min)); //ok
+
+   double d0;
+   if((m_d0_min!=m_d0_max)&&(m_d0_alpha!=0.)) {
+      // generate density f(r)= k*abs(r)^n
+      //  int_0^x dx' = int_r0^r f(r')dr'
+      //   x = F(r)-F(r0)
+      //   z=x+F(r0) = F(r)
+      //   F^-1(z) = r
+      //   F(r) = k*r*abs(r)^n
+      //   1/k = r1*abs(r1)^n-r0*abs(r0)^n
+      //   z/abs(z) * (abs(z)/k)^(1/(n+1)) = r
+
+      double f0=(m_d0_min!=0.) ? m_d0_min*pow(fabs(m_d0_min),m_d0_alpha) : m_d0_min;
+      double f1=(m_d0_max!=0.) ? m_d0_max*pow(fabs(m_d0_max),m_d0_alpha) : m_d0_max;
+      double k=1./(f1-f0);
+      if(k<0.0) {
+         // swap f0,f1
+         k=f0; f0=f1; f1=k;
+         k=1./(f1-f0);
+      }
+      double z=getRandom()+k*f0;
+      d0 = (z !=0.0) ? pow(fabs(z)/k,1./(1.+m_d0_alpha)) : 0.0;
+      if(z<0.0) d0= -d0;
+
+      // test: m_d0_alpha=0:
+      //    f0=m_d0_min
+      //    f1=m_d0_max
+      //    k=1./(m_d0_max-m_d0_min)
+      //    z = rnd + m_d0_min/(m_d0_max-m_d0_min)
+      //   d0 = rnd*(m_d0_max-m_d0_min) + m_d0_min   -> OK
+      //
+   } else {
+      d0=(m_d0_max - m_d0_min) * getRandom() + m_d0_min;
+   }
+   track.setIP(d0);
+   track.setZ0( getRandom() * (m_z0_max - m_z0_min) + m_z0_min); //ok
+
+#ifdef DEBUG_BEAMSPOT
+   m_d0BS=track.getIP();
+   m_z0BS=track.getZ0();
+#endif
+   if(!isBeamAtZero()) {
+      // transform D0,Z0 (defined wrt beamspot) to origin
+      transformToOrigin(track);
+   }
+
+   track.setIPRaw(track.getIP());
+   track.setZ0Raw(track.getZ0());
+}
+
+
+//___________________________________________________________________________________________ //
+bool FTKPattGenRoot::ReadSectorFile(const std::string& sectorfile){
+   //! Read sector file in ascii format
+   //! Return boolean if file was read successfully
+
+   if (!m_sectorbank.empty()) {
+      Warning("ReadSectorFile") << "*** Sector bank already initialized."<<endl;
+      return false;
+   }
+   
+      // ftk_dcap can read gzip and bzip2 files
+      ftk_dcap::istream ifile;
+      bool okread = ftk_dcap::open_for_read(sectorfile.c_str(), ifile);
+      if (!ifile || !okread) {
+	 Fatal("ReadSectorFile") << "*** Error loading the sector bank: " << sectorfile << endl;
+      }
+      if (!ifile || !okread) return false;
+  
+      // Retrieve the number of patterns and planes
+      int tmpnplanes;
+      int nsectors;
+      ifile >> nsectors >> tmpnplanes;
+      if (tmpnplanes != pmap()->getNPlanes() ) {
+	 cerr << "Wrong planes number in the sectors file: " << sectorfile << endl;
+	 return false;
+      }
+      cout << "Loading " << nsectors << " sectors..." << endl;
+      if (nsectors > 0) {
+	 m_sectorbank.resize(nsectors,FTKHitPattern(tmpnplanes));
+	 for (int id=0; id<nsectors; id++) {
+  	    int ssid, sID, pID, cov;
+	    {
+	       ifile >> pID;
+	       for (int ip=0; ip<tmpnplanes;++ip) { // loop on the planes
+		  // the m_nplnes+1 element is the number of the sector
+		  // the other are the SS index
+		  ifile >> ssid;// patt.m_ssid[iplane];
+		  m_sectorbank[id].SetHit(ip,ssid);
+	       } 
+	       ifile >> sID;
+	       ifile >> cov;
+	    }
+	 }
+      }
+      return true;
+}
+
+void FTKPattGenRoot::setBeamspot(double beamspotX,double beamspotY) {
+   m_beamspot[0]=beamspotX;
+   m_beamspot[1]=beamspotY;
+}
+
+bool  FTKPattGenRoot::isBeamAtZero(void) const {
+   return hypot(m_beamspot[0],m_beamspot[1])<1.E-14;
+}
+
+void FTKPattGenRoot::transformToOrigin(FTKTrack &track) {
+   static double const B_FACTOR=-0.3*2.083;// conversion factor 1/Mev -> 1/mm
+   // parameters defined at the nominal vertex
+   double phi=track.getPhi();
+   double rho=B_FACTOR*track.getHalfInvPt() *(2.0);
+   double cotTheta=track.getCotTheta();
+   // parameters defined at beamspot
+   double d1=track.getIP();
+   double z1=track.getZ0();
+
+   double sPhi=sin(phi);
+   double cPhi=cos(phi);
+   double R= -m_beamspot[0]*sPhi+m_beamspot[1]*cPhi;
+   double Q=  m_beamspot[0]*cPhi+m_beamspot[1]*sPhi;
+
+   double h1=2.*d1+rho*(d1*d1-Q*Q);
+   double d0=R+h1/(sqrt(rho*h1+1.)+1.);
+
+   double s= -Q/(rho*d1+1.);
+   double alpha=rho*s;
+   if(fabs(alpha)>1.E-7) {
+      s=asin(alpha)/rho;
+   }
+   double z0=z1+cotTheta*s;
+
+   track.setIP(d0);
+   track.setZ0(z0);
+}
+
+//___________________________________________________________________________________________ //
+void FTKPattGenRoot::ConvertPhi(FTKTrack& track){
+   //! Convert phi to the format used in the constants calculations
+   //! Requires 
+   //!   + m_curreg
+   //!   + m_rmap
+   double local_phi(track.getPhi());
+   track.setPhi(remainder(local_phi,2.*M_PI));
+}
+
+#ifdef REALLY_UNUSED
+   if (m_ssmap->getRegionMap()->getNumRegions()==8) {
+      if (m_curreg>=3 && m_curreg<=5) {
+	 while (local_phi<0) local_phi += TMath::TwoPi();
+	 track.setPhi(local_phi);
+      }
+   } 
+   else {
+      if (m_curreg==9 || m_curreg==10 || m_curreg==25 || m_curreg==26 || 
+	  m_curreg==41 || m_curreg==42 || m_curreg==57 || m_curreg==58 ) {
+	 while (local_phi>=TMath::TwoPi()) local_phi -= TMath::TwoPi();
+	 while (local_phi<0) local_phi += TMath::TwoPi();
+	 track.setPhi(local_phi);
+      }
+   }
+}
+#endif
+
+void  FTKPattGenRoot::SetModuleGeometryCheck(const std::string &fileName,
+                                             SectorSelection select) {
+   m_select = select;
+   if(m_select==RndSector) {
+      Info("SetModuleGeometryCheck")
+         <<"select="<<m_select<<": no boudary check, random sector selection\n";
+   } else {
+      // read module geometry
+      TFile *f=new TFile(fileName.c_str());
+      TTree *t=0;
+      f->GetObject("modulePositions",t);
+      if(t) {
+         int id;
+         float r[2],z[2];
+         t->SetBranchAddress("id",&id);
+         t->SetBranchAddress("r",r);
+         t->SetBranchAddress("z",z);
+         for(int i=0;i<t->GetEntries();i++) {
+            t->GetEntry(i);
+            RZminmax_t &module=m_moduleBounds[id];
+            module.rMin=r[0];
+            module.rMax=r[1];
+            module.zMin=z[0];
+            module.zMax=z[1];
+         }
+      }
+      delete f;
+      if(m_moduleBounds.size()) {
+         Info("SetModuleGeometryCheck")
+            <<"found "<<m_moduleBounds.size()<<" modules\n";
+         if(m_select==ModuleGeometry) {
+            Info("SetModuleGeometryCheck")
+               <<"select="<<m_select<<" random sector within module bounds, or weighted by distance\n";
+         } else if(m_select==ModuleGeometrySmallestSector) {
+            Info("SetModuleGeometryCheck")
+               <<"select="<<m_select<<" smallest sector ID within module bounds, or weighted by distance\n";
+         } else if(m_select==ModuleGeometryBestMatch) {
+            Info("SetModuleGeometryCheck")
+               <<"select="<<m_select<<" smallest sector ID within module bounds, or best distance\n";
+         } else {
+            Error("SetModuleGeometryCheck")
+               <<"select="<<" (undefined selection algorithm)\n";
+         }
+      } else {
+         m_select= RndSector;
+         Error("SetModuleGeometryCheck")
+            <<"module geometry "<<fileName<<" not found\n";
+         Warning("SetModuleGeometryCheck")
+            <<"revert to select="<<m_select
+            <<": no boudary check, random sector selection\n";
+      }
+   }
+}
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRootAlgo.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRootAlgo.cxx
new file mode 100644
index 00000000000..1fa73d0505e
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattGenRootAlgo.cxx
@@ -0,0 +1,315 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/FTKPattGenRootAlgo.h"
+#include "TrigFTKSim/FTKPMap.h"
+#include "TrigFTKSim/FTKRegionMap.h"
+#include "TrigFTKSim/FTKSSMap.h"
+#include "TrigFTKSim/FTKConstantBank.h"
+#include "TrigFTKSim/FTKTrack.h"
+#include "TrigFTKBankGen/FTKSectorSlice.h"
+#include "AthenaKernel/IAtRndmGenSvc.h"
+#include "TrigFTKSim/ftk_dcap.h"
+#include "TrigFTKSim/FTKSetup.h"
+#include "CLHEP/Random/RandomEngine.h"
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <TMath.h>
+#include <boost/unordered_map.hpp>
+#include <list>
+#include "TrigFTKSim/FTKRootFile.h"
+#include "TrigFTKSim/FTKPatternBySector.h"
+#include "TrigFTKSim/FTKPatternWithCoverage.h"
+#include "AthenaKernel/IAtRndmGenSvc.h" // random numbers
+
+using namespace std;
+/////////////////////////////////////////////////////////////////////////////
+
+FTKPattGenRootAlgo::FTKPattGenRootAlgo(const std::string& name, ISvcLocator* pSvcLocator):
+   AthAlgorithm(name, pSvcLocator),
+   m_rndmSvc("AtRanluxGenSvc", name),
+   // m_pmap(0x0),
+   // m_rmap(0x0),
+   // m_ssmap(0x0), m_ssmap_tsp(0x0),
+   // m_constbank(0x0),
+   // m_sectorslice(0x0),
+   // m_force_am_hashmap(true),
+   m_ssmap_path(),
+   //m_ssmaptsp_path(),
+   m_pmap_path(),
+   m_rmap_path(),
+   m_modulelut_path(),
+   m_slices_path(),
+   m_fitconstants_path(),
+   m_sectors_path(),
+   m_IBLMode(1), // flag to change the IBLMode
+   m_fixEndcapL0(false), 
+   m_ITkMode(false),
+   // m_dbghit_path(),
+   // m_ifile(),
+   // m_okread(false),
+   // m_ready(false),
+   // m_phi_min(),
+   // m_phi_max(),
+   // m_c_min(),
+   // m_c_max(),
+   // m_d0_min(),
+   // m_d0_max(),
+   // m_z0_min(),
+   // m_z0_max(),
+   // //m_ctheta_min(),
+   // //m_ctheta_max(),
+   // m_eta_min(),
+   // m_eta_max(),
+   m_rndStreamName("RANDOM"),
+   m_d0_alpha(0.),
+   //m_pEng(0),
+   // m_trials(0),
+   // m_track(),
+   // m_fin(),
+   // m_pattern_counter(0),
+   // m_npatterns_partial(0),
+   // m_emptySectorList(0),
+   // m_notAnyGoodSector(0),
+   // m_ss(0),
+   // m_dimspa(0),
+   // m_dimker(0),
+   // m_curreg(0),
+   // m_seed(0),
+   //m_PCONST_OVERLAP(0),
+   // m_rndGen(0x0),
+   // m_nplanes(0),
+   // m_nsectors(0),
+   // m_constr(0x0),
+   // m_smear(),
+   // m_rnd_sector_selection(),
+   // m_weighted_rnd_sector_selection(),
+   // m_no_sector_selection(),
+   // m_rnd_pattern_selection(),
+   // m_weighted_rnd_pattern_selection(),
+   // m_hitVector(0x0),
+   // m_npatterns_reproduced(0),
+   // m_npatterns_reproduced_partial(0),
+   // m_npatterns_merged(0),
+   // m_sectorbank(0x0),
+   // m_pattmap(0x0), m_curpatt(0x0),
+   // m_found_patterns(),
+   // m_sectors_covInt(0x0)
+   m_keep7of8(0),
+   m_tolerance7of8(0.1),
+
+   m_sectorSelection(FTKPattGenRoot::SectorSelection::ModuleGeometry),
+
+   m_pattgen(0),
+   m_totalPatterns(0),m_totalThrown(0)
+{
+   SetLogger(this);
+   declareProperty("ssmap_path", m_ssmap_path);
+   declareProperty("hwmodeid", m_HWMODEID);
+   //declareProperty("ssmaptsp_path", m_ssmaptsp_path);
+   declareProperty("pmap_path", m_pmap_path);
+   declareProperty("rmap_path", m_rmap_path);
+   declareProperty("ModuleLUTPath", m_modulelut_path);
+   declareProperty("slices", m_slices_path);
+   declareProperty("fitconsts", m_fitconstants_path);
+   declareProperty("sectors", m_sectors_path);
+   // declareProperty("dbghit_path", m_dbghit_path);
+   declareProperty("phi_min", m_phi_min);
+   declareProperty("phi_max", m_phi_max);
+   declareProperty("c_min", m_c_min);
+   declareProperty("c_max", m_c_max);
+   declareProperty("d0_min", m_d0_min);
+   declareProperty("d0_max", m_d0_max);
+   declareProperty("z0_min", m_z0_min);
+   declareProperty("z0_max", m_z0_max);
+   declareProperty("eta_min", m_eta_min);
+   declareProperty("eta_max", m_eta_max);
+   declareProperty("d0_alpha", m_d0_alpha);
+   declareProperty("beamspotX", m_beamspotX);
+   declareProperty("beamspotY", m_beamspotY);
+   //declareProperty("ctheta_min", m_ctheta_min);
+   //declareProperty("ctheta_max", m_ctheta_max);
+   declareProperty("rndmSvc", m_rndmSvc);
+   declareProperty("trials", m_trials);
+   // declareProperty("writeafternpatterns", m_writeafter);
+   // declareProperty("maxopenrootfiles", m_maxopenfiles);
+   declareProperty("curreg", m_curreg);
+   declareProperty("pconst_overlap", m_overlap);
+   declareProperty("OutputFile",m_OutputFile);
+   declareProperty("sectorSelection", m_sectorSelection);
+
+   // declareProperty("smear", m_smear);
+   // declareProperty("rnd_sector_selection", m_rnd_sector_selection);
+   // declareProperty("weighted_rnd_sector_selection", m_weighted_rnd_sector_selection);
+   // declareProperty("no_sector_selection", m_no_sector_selection);
+   // declareProperty("rnd_pattern_selection", m_rnd_pattern_selection);
+   // declareProperty("weighted_rnd_pattern_selection", m_weighted_rnd_pattern_selection);
+   declareProperty("IBLMode",m_IBLMode);
+   declareProperty("FixEndcapL0",m_fixEndcapL0);
+   declareProperty("ITkMode",m_ITkMode);
+   declareProperty("keep7of8",m_keep7of8);
+   declareProperty("tolerance7of8",m_tolerance7of8);
+   declareProperty("rndStreamName",m_rndStreamName);
+
+   declareProperty("ModuleGeometryFile",m_ModuleGeometryFile);
+
+#ifdef DEBUG_BEAMSPOT
+  m_propagator = new ToolHandle<Trk::IPropagator>
+     ( "Trk::RungeKuttaPropagator/DefaultPropagator");
+#endif
+}
+
+FTKPattGenRootAlgo::~FTKPattGenRootAlgo() {
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode FTKPattGenRootAlgo::initialize() {
+
+#ifdef DEBUG_BEAMSPOT
+   if( (*m_propagator).retrieve().isFailure() ) {
+      ATH_MSG_FATAL( "Propagator tool not found");
+      return StatusCode::FAILURE;
+   }   
+#endif
+
+   MsgStream log(msgSvc(), name());
+   
+   // --- check input
+   if (m_pmap_path.empty()) { // check pmap file
+      log << MSG::FATAL << "Main plane map definition missing" << endmsg;
+      return StatusCode::FAILURE;
+   }
+   if (m_rmap_path.empty()) { // check rmap file
+      log << MSG::FATAL << "Region map file needed" << endmsg;
+      return StatusCode::FAILURE;
+   }
+   if (m_ssmap_path.empty() ) {// check ss file
+      log << MSG::FATAL << "No SS configuration file given" << endmsg;
+      return StatusCode::FAILURE;
+   }
+   if (m_slices_path.empty()) { // check slices file
+      log << MSG::FATAL << "Slices file missing" << endmsg;
+      return StatusCode::FAILURE;
+   }
+   if (m_fitconstants_path.empty()) { // check constants file
+     log << MSG::FATAL << "Fit constants bank missing" << endmsg;
+     return StatusCode::FAILURE;
+   }
+   if (m_sectors_path.empty()) {
+      log << MSG::FATAL << "Sector file missing" << endmsg;
+     return StatusCode::FAILURE;
+   }
+   // --- ---
+
+   // --- set HWMODEID
+   FTKSetup &ftkset = FTKSetup::getFTKSetup();
+   ftkset.setHWModeSS(m_HWMODEID);
+   ftkset.setIBLMode(m_IBLMode);
+   ftkset.setfixEndcapL0(m_fixEndcapL0);
+   ftkset.setITkMode(m_ITkMode);
+   
+   // --- Create the pmap file object
+   log << MSG::INFO << "RunPattGen() Make FTKPlaneMap." << endmsg;
+   FTKPlaneMap* pmap = new FTKPlaneMap(m_pmap_path.c_str());
+   if (!(*pmap)) {
+      log << MSG::FATAL << "Error using plane map: " << m_pmap_path << endmsg;
+      return StatusCode::FAILURE;
+   }
+
+   // --- Create region map object
+   log << MSG::INFO << "RunPattGen() Make FTKRegionMap." << endmsg;
+   FTKRegionMap* rmap = new FTKRegionMap(pmap, m_rmap_path.c_str());
+
+   if(m_HWMODEID==2) {
+      if(m_modulelut_path.empty()) {
+         log << MSG::FATAL <<"RunPattGen() A module LUT is required when HW SS calculation is required"<<endmsg;
+	 return StatusCode::FAILURE;
+      } else {
+         rmap->loadModuleIDLUT(m_modulelut_path.c_str());
+      }
+   }
+
+   // --- Create ssmap
+   const bool force_am_hashmap = false;
+   log << MSG::INFO << "RunPattGen() Make FTKSSMap." << endmsg;
+   FTKSSMap* ssmap = new FTKSSMap(rmap, m_ssmap_path.c_str(), force_am_hashmap);
+
+   // --- Create the slices file object
+   log << MSG::INFO << "RunPattGen() Make FTKSectorSlice." << endmsg;
+   FTKSectorSlice* sectorslice = new FTKSectorSlice();
+   sectorslice->loadSlices(m_slices_path);
+
+   // --- create  FTKConstantBank
+   log << MSG::INFO << "RunPattGen() Make FTKConstantBank." << endmsg;
+   FTKConstantBank* constbank = new FTKConstantBank(pmap->getTotalDim(), m_fitconstants_path.c_str());
+
+  // --- create pattgen object
+  log << MSG::INFO << "RunPattGen() Make FTKPattGenRoot."
+      << endmsg;
+
+  m_pattgen=new FTKPattGenRoot(m_curreg,ssmap,sectorslice,constbank,m_keep7of8,
+                               m_tolerance7of8
+#ifdef DEBUG_BEAMSPOT
+                               ,m_propagator
+#endif
+                               );
+  log << MSG::INFO << "RunPattGen() beam spot at "
+      <<m_beamspotX<<" "<<m_beamspotY
+      << endmsg;
+  m_pattgen->SetRandomNumberGenerator(m_rndmSvc->GetEngine(m_rndStreamName));
+  m_pattgen->setBeamspot(m_beamspotX,m_beamspotY);
+  m_pattgen->ReadSectorFile(m_sectors_path); // set sectors path
+  m_pattgen->SetSliceParameters(m_phi_min,m_phi_max, m_c_min, m_c_max,
+			     m_d0_min, m_d0_max, m_z0_min, m_z0_max, m_eta_min, m_eta_max);
+  m_pattgen->SetD0Exponent(m_d0_alpha);
+  m_pattgen->SetOverlapRemoval(m_overlap);
+  m_pattgen->SetModuleGeometryCheck
+     (m_ModuleGeometryFile,(FTKPattGenRoot::SectorSelection)m_sectorSelection);
+
+  // open output file
+  m_pattgen->SetRootOutput(m_OutputFile); 
+
+  return StatusCode::SUCCESS;
+} 
+
+
+// // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode FTKPattGenRootAlgo::execute() {
+   uint64_t n=m_pattgen->trackInvertion(m_trials);
+   m_totalPatterns+=m_trials;
+   m_totalThrown+=n;
+   MsgStream log(msgSvc(), name());
+   log << MSG::INFO << "Number of trials: "
+       <<m_totalPatterns<<" / "<<m_totalThrown<<endmsg;
+   
+   return StatusCode::SUCCESS;
+}
+
+
+// // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+StatusCode FTKPattGenRootAlgo::finalize() {
+   delete m_pattgen;
+   MsgStream log(msgSvc(), name());
+   log << MSG::INFO << "Total number of patterns: "
+       <<m_totalPatterns<<" / "<<m_totalThrown<<endmsg;
+   return StatusCode::SUCCESS;
+}
+
+ 
+// // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+void FTKPattGenRootAlgo::PostMessage(void) {
+   if     (FTKLogger::m_type==0)  ATH_MSG_FATAL(m_buffer->str());
+   else if(FTKLogger::m_type==1)  ATH_MSG_ERROR(m_buffer->str());
+   else if(FTKLogger::m_type==2)  ATH_MSG_WARNING(m_buffer->str());
+   else if(FTKLogger::m_type==3)  ATH_MSG_INFO(m_buffer->str());
+   else if(FTKLogger::m_type==4)  ATH_MSG_DEBUG(m_buffer->str());
+}
+
+
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattKDTree.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattKDTree.cxx
new file mode 100644
index 00000000000..2a5acaa75dd
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKPattKDTree.cxx
@@ -0,0 +1,765 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/FTKPattKDTree.h"
+#include "TrigFTKBankGen/FTKBankGenAlgo.h"
+#include "TrigFTKBankGen/FTKConstGenAlgo.h"
+
+#include <stdio.h>
+#include <algorithm>
+#include <cmath>
+#include <ctime>
+#include <cassert>
+
+#include <iostream>
+
+using namespace std;
+
+// kdtree: First index is the bank, second index is the bitmask
+// We keep one kdtree for each bitmask
+static vector<map<unsigned int, FTKPattKDTree*> > kdtree;
+static vector<vector< FTKPattKDTree* > > sortedPatterns;
+static int kdplanes(0);
+static int kddims(0);
+matrix added;
+vector<double> added_hitc;
+vector<double> added_xC;
+vector<double> added_xD;
+vector<double> added_xPhi;
+vector<double> added_xCoto;
+vector<double> added_xZ;
+vector<double> added_covx;
+vector<short> new_intc;
+vector<short> new_intphi;
+vector<short> new_intd0;
+vector<short> new_intz0;
+vector<short> new_inteta;
+
+
+//FTKPattKDTree::FTKPattKDTree(const std::vector<int>& pattern,
+FTKPattKDTree::FTKPattKDTree(const std::vector<int>& pattern,
+			     const std::vector<int>& hashID,
+			     const std::vector<double>& tmphitc,
+			     const std::vector<double>& tmpxC,
+			     const std::vector<double>& tmpxD,
+			     const std::vector<double>& tmpxPhi,
+			     const std::vector<double>& tmpxCoto,
+			     const std::vector<double>& tmpxZ,
+			     const std::vector<double>& tmpcovx,
+			     const std::vector<short>& int_c,
+			     const std::vector<short>& int_phi,
+			     const std::vector<short>& int_d0,
+			     const std::vector<short>& int_z0,
+			     const std::vector<short>& int_eta,
+			     const float& hitcount,
+			     int depth, FTKPattKDTree *parent,
+			     const double& tmpC,const double& tmpD,const double& tmpPhi,
+			     const double& tmpCoto,const double& tmpZ,const float& tmpnhit
+			     ) :
+  // Convention for m_dim is that the last number is just the sector
+  m_dim(pattern.size()-1), m_depth(depth), m_below(1), m_pattern(pattern), m_hashID(hashID), m_hitcount(hitcount),m_tmpC(tmpC),
+  m_tmpD(tmpD),m_tmpPhi(tmpPhi),m_tmpCoto(tmpCoto),m_tmpZ(tmpZ),m_tmpnhit(tmpnhit),m_tmphitc(tmphitc),
+  m_tmpxC(tmpxC),m_tmpxD(tmpxD),m_tmpxPhi(tmpxPhi),m_tmpxCoto(tmpxCoto),m_tmpxZ(tmpxZ), m_tmpcovx(tmpcovx),
+  m_intc(int_c),m_intphi(int_phi),m_intd0(int_d0),m_intz0(int_z0),m_inteta(int_eta),m_nmissing(0), m_parent(parent), m_left(0), m_right(0)
+{
+ 
+  assert(m_dim>0);
+  // determine the SS that splits the hyper-space
+  m_splitplane = parent ? (parent->getSplitPlane()+1) : 0;
+  m_splitplane %= m_dim;
+
+  while( m_pattern[m_splitplane]/100 == -999 ) { m_splitplane++; m_splitplane %= m_dim; }
+  
+  for( unsigned int i = 0, np=m_dim; i < np; i++ )
+    if( m_pattern[i]/100 == -999 ) m_nmissing++;
+  
+}
+
+/** destructor of the Tree, recursively destroy all the level */
+FTKPattKDTree::~FTKPattKDTree()
+{
+  if (m_left) delete m_left;
+  if (m_right) delete m_right;
+}
+
+
+/** find an empty leaf to place this road in the kd-tree*/
+int
+//FTKPattKDTree::addNode(const std::vector<int>& pattern,
+FTKPattKDTree::addNode(const std::vector<int>& pattern,
+		       const std::vector<int>& hashID,
+		       const std::vector<double>& tmphitc,
+		       const std::vector<double>& tmpxC,
+		       const std::vector<double>& tmpxD,
+		       const std::vector<double>& tmpxPhi,
+		       const std::vector<double>& tmpxCoto,
+		       const std::vector<double>& tmpxZ,
+		       const std::vector<double>& tmpcovx,
+		       const std::vector<short>& int_c,
+		       const std::vector<short>& int_phi,
+		       const std::vector<short>& int_d0,
+		       const std::vector<short>& int_z0,
+		       const std::vector<short>& int_eta,
+		       const float& hitcount,
+		       const double& tmpC,const double& tmpD,const double& tmpPhi,
+		       const double& tmpCoto,const double& tmpZ,const float& tmpnhit)
+{
+  
+  int nadded = 0;
+  // determine the direction
+  if ( pattern[m_splitplane] <= m_pattern[m_splitplane] ) {
+    // is the left part the axis
+    if (!m_left) {
+      // create a new sub-tree
+      m_left = new FTKPattKDTree(pattern,hashID,tmphitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+				 int_c,int_phi,int_d0,int_z0,int_eta,
+				 hitcount,m_depth+1,this,tmpC,tmpD,tmpPhi,tmpCoto,tmpZ,tmpnhit);
+      ++nadded;
+    }
+    else {
+      // continue the search
+      nadded+=m_left->addNode(pattern,hashID,tmphitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+			      int_c,int_phi,int_d0,int_z0,int_eta,
+			      hitcount,tmpC,tmpD,tmpPhi,tmpCoto,tmpZ,tmpnhit);
+    }
+  }
+  else if( pattern[m_splitplane] > m_pattern[m_splitplane] ) {
+    // is on the right part of the axis
+    if (!m_right) {
+      // create a new sub-tree
+      m_right = new FTKPattKDTree(pattern,hashID,tmphitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+				  int_c,int_phi,int_d0,int_z0,int_eta,
+				  hitcount,m_depth+1,this,tmpC,tmpD,tmpPhi,tmpCoto,tmpZ,tmpnhit);
+      ++nadded;
+    }
+    else {
+      // continue the search
+      nadded+=m_right->addNode(pattern,hashID,tmphitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+			       int_c,int_phi,int_d0,int_z0,int_eta,
+			       hitcount,tmpC,tmpD,tmpPhi,tmpCoto,tmpZ,tmpnhit);
+    }
+  }
+    
+  m_below += nadded;
+  return nadded;
+} 
+
+void
+FTKPattKDTree::markForRemoval() {
+
+  m_hitcount = -1;
+
+}
+
+void FTKPattKDTree::getAllBelow( std::vector< FTKPattKDTree* >& activePatts) {
+  
+
+
+  if( !markedForRemoval() )
+    activePatts.push_back( this );
+
+  if( m_left )
+    m_left->getAllBelow(activePatts);
+  
+  if( m_right )
+    m_right->getAllBelow(activePatts);
+
+
+}
+
+// Find all patterns in the tree similar to refpatt. If refpatt is in
+// the tree, it will be included.
+void FTKPattKDTree::findSimilar(bool const_test,
+				const vector<int>& refpatt,
+				const vector<double>& hitc,
+				const std::vector<double>& tmpxC,
+				const std::vector<double>& tmpxD,
+				const std::vector<double>& tmpxPhi,
+				const std::vector<double>& tmpxCoto,
+				const std::vector<double>& tmpxZ,
+				const std::vector<double>& tmpcovx,
+				const std::vector<short>& int_c,
+				const std::vector<short>& int_phi,
+				const std::vector<short>& int_d0,
+				const std::vector<short>& int_z0,
+				const std::vector<short>& int_eta,
+				set<FTKPattKDTree*> &nodes,
+				bool exactmatch,const double& C,const double& D,
+				const double& Phi,const double& Coto,const double& Z,
+				const float& nhit)
+{
+  
+  if( m_hitcount > 0) {
+    // If refpatt matches this node, automatically insert it:
+    bool fullmatch(true);
+    for(unsigned int i = 0, j = m_dim; i < j && fullmatch; i++) {
+      if( refpatt[i] != m_pattern[i] &&
+	  (refpatt[i]/100 != -999 || m_pattern[i]/100 != -999) )
+	fullmatch = false;
+    }
+    
+        
+    if( fullmatch ) {
+      nodes.insert(this);
+      if(!const_test){
+	added.C=m_tmpC+C;
+	added.D=m_tmpD+D;
+	added.Phi=m_tmpPhi+Phi;
+	added.Coto=m_tmpCoto+Coto;
+	added.Z=m_tmpZ+Z;
+            
+	for (int i=0;i < kddims ;++i) {
+	  added_hitc[i]=m_tmphitc[i]+hitc[i];
+	  added_xC[i]=m_tmpxC[i]+tmpxC[i];
+	  added_xD[i]=m_tmpxD[i]+tmpxD[i];
+	  added_xPhi[i]=m_tmpxPhi[i]+tmpxPhi[i];
+	  added_xCoto[i]=m_tmpxCoto[i]+tmpxCoto[i];
+	  added_xZ[i]=m_tmpxZ[i]+tmpxZ[i];
+	  for (int j=i;j < kddims ;++j) {
+	    added_covx[i*kddims+j]=m_tmpcovx[i*kddims+j]+tmpcovx[i*kddims+j];
+	  }
+	}
+            
+	added.nhit=m_tmpnhit+nhit;
+      
+	new_intc.resize(int(added.nhit));
+	new_intphi.resize(int(added.nhit));
+	new_intd0.resize(int(added.nhit));
+	new_intz0.resize(int(added.nhit));
+	new_inteta.resize(int(added.nhit));
+
+	for (int i=0;i <added.nhit ;++i) {
+	  if(i<m_tmpnhit){
+	    new_intc[i]= m_intc[i];
+	    new_intphi[i]= m_intphi[i];
+	    new_intd0[i]= m_intd0[i];
+	    new_intz0[i]= m_intz0[i];
+	    new_inteta[i]= m_inteta[i];
+	  	  
+	  }else{
+	    new_intc[i]= int_c[i-m_tmpnhit];
+	    new_intphi[i]= int_phi[i-m_tmpnhit];
+	    new_intd0[i]= int_d0[i-m_tmpnhit];
+	    new_intz0[i]= int_z0[i-m_tmpnhit];
+	    new_inteta[i]= int_eta[i-m_tmpnhit];
+	  	  
+	  }
+	}
+      }//const test      
+
+      // If we're looking for an exact match, we're done
+      if( exactmatch )
+	return;
+    }
+    else if( !exactmatch ) {
+      // evaluate if the superstrips are similar
+      bool match(true);
+      int refmissing(0);
+      
+      for (int ip=0;ip < m_dim && match;++ip) {
+	// Count how many hits are missing. We only want to find similar
+	// patterns with more or fewer hits. The only found pattern with
+	// the same number of hits as the refpatt should be that pattern
+	// itself, if it is in the tree.
+	
+	if( refpatt[ip]/100 == -999 ) {
+	  refmissing++;
+	  continue;
+	}
+	
+	if( m_pattern[ip]/100 == -999 ) continue;
+	
+	if( refpatt[ip] != m_pattern[ip] )
+	  match = false;
+      }
+      if (match && refmissing != m_nmissing ) {
+ 	// this node is similar. 
+	nodes.insert(this);
+      }
+    }
+  }
+  
+  if (m_left) {
+    // if similar patterns could be in this part continue the search
+    if ( (!exactmatch && refpatt[m_splitplane]/100 == -999) ||
+	 refpatt[m_splitplane] <= m_pattern[m_splitplane] ) {
+      m_left->findSimilar(const_test,refpatt,hitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+			  int_c,int_phi,int_d0,int_z0,int_eta,
+			  nodes,exactmatch,C,D,Phi,Coto,Z,nhit);
+    }
+  }
+  
+  if (m_right) {
+    // if similar patterns could be in this part continue the search
+    if ( (!exactmatch && refpatt[m_splitplane]/100 == -999) ||
+	 refpatt[m_splitplane] > m_pattern[m_splitplane] ) {
+      m_right->findSimilar(const_test,refpatt,hitc,tmpxC,tmpxD,tmpxPhi,tmpxCoto,tmpxZ,tmpcovx,
+			   int_c,int_phi,int_d0,int_z0,int_eta,
+			   nodes,exactmatch,C,D,Phi,Coto,Z,nhit);
+    }
+  }
+}
+
+// Interface functions
+void initPattTree(int nbanks, int nplanes,int ndims) {
+  
+  for(int i = 0; i < nbanks; i++) { kdtree.push_back( map<unsigned int, FTKPattKDTree*>() ); }
+  kdplanes = nplanes;
+  kddims = ndims;
+  added_hitc.resize(kddims);
+  added_xC.resize(kddims);
+  added_xD.resize(kddims);
+  added_xPhi.resize(kddims);
+  added_xCoto.resize(kddims);
+  added_xZ.resize(kddims);
+  added_covx.resize(kddims*kddims);
+    
+}
+
+void finishPattTree() {
+  // Get rid of the pattern KD trees
+  sortedPatterns.clear();
+
+  for( unsigned int i = 0, nt = kdtree.size(); i < nt; i++ )
+    for( map<unsigned int, FTKPattKDTree*>::iterator j = kdtree[i].begin(),
+	   jend = kdtree[i].end(); j != jend; j++ ) 
+      delete j->second;
+  
+  kdtree.clear();
+
+} 
+
+
+//int addKDPattern(int bank, bool const_test_mode, int* pattern, int mult,matrix Mtmp,double* hitc,
+int addKDPattern(int bank, bool const_test_mode, int* pattern, int *hashID, int mult,matrix Mtmp,double* hitc,
+		 double* xC,double* xD,double* xPhi,double* xCoto,double* xZ,double* covx,
+		 vector<short> int_c,vector<short> int_phi,vector<short> int_d0,
+		 vector<short> int_z0,vector<short> int_eta){
+
+  
+  // Return codes:
+  // -1 - cannot find matched pattern in const_test_mode
+  // 0 - Error
+  // 1 - Added
+  // 2 - Already existed
+  
+  int nmissing = 0;
+  vector<int> thePatt;
+  vector<int> theHash;
+  vector<double> thehitc;
+  vector<double> thexC;
+  vector<double> thexD;
+  vector<double> thexPhi;
+  vector<double> thexCoto;
+  vector<double> thexZ;
+  vector<double> thecovx;
+  
+  vector<short> intc;
+  vector<short> intphi;
+  vector<short> intd0;
+  vector<short> intz0;
+  vector<short> inteta;
+  
+  set<FTKPattKDTree*> sims;
+  
+  thePatt.resize(kdplanes);
+  theHash.resize(kdplanes);
+  thehitc.resize(kddims);
+  thexC.resize(kddims);
+  thexD.resize(kddims);
+  thexPhi.resize(kddims);
+  thexCoto.resize(kddims);
+  thexZ.resize(kddims);
+  thecovx.resize(kddims*kddims);
+
+  unsigned int bitmask = 0;
+  for( int i = 0; i < kdplanes; i++ ) {
+    if( pattern[i]/100 == -999 ) nmissing++;
+    else if( i < kdplanes-1 )
+      bitmask |= (1<<i);
+    
+    thePatt[i] = pattern[i];
+    theHash[i] = hashID[i];
+  }
+  
+  for( int i = 0; i < kddims; i++ ) {
+    thehitc[i]=hitc[i];
+    thexC[i]=xC[i];
+    thexD[i]=xD[i];
+    thexPhi[i]=xPhi[i];
+    thexCoto[i]=xCoto[i];
+    thexZ[i]=xZ[i];
+    for( int j = i; j < kddims; j++ ) {
+      thecovx[i*kddims+j]=covx[i*kddims+j];
+    }
+  }
+ 
+  intc.resize(int(Mtmp.nhit));
+  intphi.resize(int(Mtmp.nhit));
+  intd0.resize(int(Mtmp.nhit));
+  intz0.resize(int(Mtmp.nhit));
+  inteta.resize(int(Mtmp.nhit));
+
+  
+  for( int i = 0; i < Mtmp.nhit; i++ ) {
+    intc[i]=int_c[i];
+    intphi[i]=int_phi[i];
+    intd0[i]=int_d0[i];
+    intz0[i]=int_z0[i];
+    inteta[i]=int_eta[i];
+  }
+            
+  // Initialize the KD tree for this bank if it's not yet done:
+  if( kdtree[bank].count(bitmask) == 0 ) {
+    kdtree[bank][bitmask] = new FTKPattKDTree(thePatt,theHash,thehitc,thexC,thexD,thexPhi,thexCoto,thexZ,thecovx,
+					      intc,intphi,intd0,intz0,inteta,
+					      mult,0,0,Mtmp.C,Mtmp.D,Mtmp.Phi,Mtmp.Coto,Mtmp.Z,Mtmp.nhit);
+    return 1;
+  }
+  
+  // Check for an exact match:
+  kdtree[bank][bitmask]->findSimilar(const_test_mode,thePatt,thehitc,thexC,thexD,thexPhi,thexCoto,thexZ,thecovx,
+				     intc,intphi,intd0,intz0,inteta,
+				     sims, true,Mtmp.C,Mtmp.D,Mtmp.Phi,Mtmp.Coto,Mtmp.Z,Mtmp.nhit);
+  assert(sims.size()<=1); // sanity check
+
+  // If the pattern is already in the tree, keep the one with the
+  // lower sector number.
+  if( sims.size() == 1 ) {
+    
+    if( (*sims.begin())->getPattern()[kdplanes-1] <= thePatt[kdplanes-1] ) {
+      // Just increment the one in the tree and exit
+      if(const_test_mode){
+	return (*sims.begin())->getPattern()[kdplanes-1];
+      }else{
+	(*sims.begin())->incHitCount(mult);
+	(*sims.begin())->settmpC(added.C);
+	(*sims.begin())->settmpD(added.D);
+	(*sims.begin())->settmpPhi(added.Phi);
+	(*sims.begin())->settmpCoto(added.Coto);
+	(*sims.begin())->settmpZ(added.Z);
+	(*sims.begin())->settmpnhit(added.nhit);
+	(*sims.begin())->settmphitc(added_hitc);
+	(*sims.begin())->settmpxC(added_xC);
+	(*sims.begin())->settmpxD(added_xD);
+	(*sims.begin())->settmpxPhi(added_xPhi);
+	(*sims.begin())->settmpxCoto(added_xCoto);
+	(*sims.begin())->settmpxZ(added_xZ);
+	(*sims.begin())->settmpcovx(added_covx);
+	(*sims.begin())->setintc(new_intc);
+	(*sims.begin())->setintphi(new_intphi);
+	(*sims.begin())->setintd0(new_intd0);
+	(*sims.begin())->setintz0(new_intz0);
+	(*sims.begin())->setinteta(new_inteta);
+      }//const test mode
+    }
+    else {
+      // Need to deactivate the one in the tree add add this one
+      if(!const_test_mode){
+	float newCount = mult;
+	newCount += (*sims.begin())->getHitCount();
+	(*sims.begin())->markForRemoval();
+	kdtree[bank][bitmask]->addNode(thePatt,theHash,added_hitc,thexC,thexD,thexPhi,thexCoto,thexZ,thecovx,
+				       intc,intphi,intd0,intz0,inteta,
+				       newCount,added.C,added.D,added.Phi,added.Coto,added.Z,added.nhit);
+      }//const test mode
+    }
+    return 2;
+  }
+
+  sims.clear();
+
+  // Get all higher patterns similar to this one:
+  if( nmissing ) {
+    for( map<unsigned int, FTKPattKDTree*>::iterator it = kdtree[bank].begin(),
+	   end = kdtree[bank].end(); it != end; it++ )
+      if( it->second->getNMissing() < nmissing )
+	it->second->findSimilar(const_test_mode,thePatt,thehitc,thexC,thexD,thexPhi,thexCoto,thexZ,thecovx,
+				int_c,int_phi,int_d0,int_z0,int_eta,sims);
+        
+    // If it is similar to any higher patterns, increment those and exit
+    int nhigher = sims.size();
+    
+    if( nhigher ) {
+      // Only increment by this amount since the current pattern could
+      // have multiple higher patterns, but we want to keep the overall
+      // normalization of tracks constant.
+      double inc = (double)mult/(double)nhigher;
+      for( set<FTKPattKDTree*>::iterator it = sims.begin(), end = sims.end();
+	   it != end; it++ ) {
+	(*it)->incHitCount(inc);
+      }
+      
+      return 2;
+    }
+  }
+  
+  if(const_test_mode == true && Mtmp.nhit == 5){
+    return -1;//not match pattern
+  }else{
+    // If we are at this point, then we are going to add the pattern.
+    sims.clear();
+    for( map<unsigned int, FTKPattKDTree*>::iterator it = kdtree[bank].begin(),
+	   end = kdtree[bank].end(); it != end; it++ )
+      if( it->second->getNMissing() > nmissing )
+	it->second->findSimilar(const_test_mode,thePatt,thehitc,thexC,thexD,thexPhi,thexCoto,thexZ,thecovx,
+				intc,intphi,intd0,intz0,inteta,sims);
+
+    // Absorb the hit counts of any similar patterns with fewer hits,
+    // then remove them from the tree.
+    double newmult = mult;
+    for( set<FTKPattKDTree*>::iterator it = sims.begin(), end = sims.end();
+	 it != end; it++ ) {
+    
+      newmult += (*it)->getHitCount();
+      (*it)->markForRemoval();
+    }
+    
+    // Add the new pattern to the list
+    kdtree[bank][bitmask]->addNode(thePatt,theHash,thehitc,thexC,thexD,thexPhi,thexCoto,thexZ,thecovx,
+				   intc,intphi,intd0,intz0,inteta,
+				   newmult,Mtmp.C,Mtmp.D,Mtmp.Phi,Mtmp.Coto,Mtmp.Z,Mtmp.nhit);
+
+    return 1;
+  }
+}
+
+bool compare_patt(const FTKPattKDTree* a, const FTKPattKDTree* b) {
+  // The std::sort function takes a comparison operator that returns
+  // true if 'a' goes before the 'b'. Since we want to sort from
+  // most number of hits to least number, 'a' goes before 'b' if it
+  // has more hits.
+
+  if( a->getHitCount() > b->getHitCount() ) return true;
+  else return false;
+}
+
+bool compare_Mpatt(const FTKPattKDTree* a, const FTKPattKDTree* b) {
+  
+  if( a->gettmpnhit() > b->gettmpnhit() ) return true;
+  else return false;
+}
+
+int sortPatterns(int bank) {
+  
+
+  if( sortedPatterns.size() <= bank )
+    sortedPatterns.resize(bank+1);
+
+  sortedPatterns[bank].clear();
+  
+  for(map<unsigned int, FTKPattKDTree*>::iterator it = kdtree[bank].begin(),
+	end = kdtree[bank].end(); it != end; it++ ) {
+    it->second->getAllBelow(sortedPatterns[bank]);
+  }
+  kdtree[bank].clear();
+
+  sort( sortedPatterns[bank].begin(), 
+	sortedPatterns[bank].end(),
+	compare_patt );
+  
+  return 1;
+
+}
+
+int sortMPatterns(int bank) {
+  
+
+  if( sortedPatterns.size() <= bank )
+    sortedPatterns.resize(bank+1);
+
+  sortedPatterns[bank].clear();
+  
+  for(map<unsigned int, FTKPattKDTree*>::iterator it = kdtree[bank].begin(),
+	end = kdtree[bank].end(); it != end; it++ ) {
+    it->second->getAllBelow(sortedPatterns[bank]);
+  }
+  kdtree[bank].clear();
+
+  sort( sortedPatterns[bank].begin(), 
+	sortedPatterns[bank].end(),
+	compare_Mpatt );
+  
+  return 1;
+
+}
+
+
+int getNPatterns(int bank) {
+
+  if( bank >= sortedPatterns.size() ) return 0;
+  return sortedPatterns[bank].size();
+
+}
+
+int getPatternSS( int bank, int pattid, int plane) {
+
+  if( bank >= sortedPatterns.size() ) return -1;
+  if( pattid >= sortedPatterns[bank].size() ) return -1;
+
+  return sortedPatterns[bank][pattid]->getPattern()[plane];
+
+}
+
+int getPatthashID( int bank, int pattid, int plane) {
+
+  if( bank >= sortedPatterns.size() ) return -1;
+  if( pattid >= sortedPatterns[bank].size() ) return -1;
+
+  return sortedPatterns[bank][pattid]->gethashID()[plane];
+
+}
+
+int getPattNHits(int bank, int pattid) {
+
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+
+  return (int) sortedPatterns[bank][pattid]->getHitCount();
+  
+}
+
+double getPattC(int bank, int pattid) {
+
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+
+  return sortedPatterns[bank][pattid]->gettmpC();
+  
+}
+
+double getPattD(int bank, int pattid) {
+
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+
+  return sortedPatterns[bank][pattid]->gettmpD();
+  
+}
+
+double getPattPhi(int bank, int pattid) {
+
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+
+  return sortedPatterns[bank][pattid]->gettmpPhi();
+  
+}
+
+double getPattCoto(int bank, int pattid) {
+
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+
+  return sortedPatterns[bank][pattid]->gettmpCoto();
+  
+}
+double getPattZ(int bank, int pattid) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  
+  return sortedPatterns[bank][pattid]->gettmpZ();
+  
+}
+
+double getPatthitc(int bank, int pattid, int dim) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+
+  return sortedPatterns[bank][pattid]->gettmphitc()[dim];
+  
+}
+
+float getPattnhit(int bank, int pattid) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+
+  return sortedPatterns[bank][pattid]->gettmpnhit();
+  
+}
+
+double getPattxC(int bank, int pattid, int dim) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->gettmpxC()[dim];
+}
+
+double getPattxD(int bank, int pattid, int dim) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->gettmpxD()[dim];
+}
+
+double getPattxPhi(int bank, int pattid, int dim) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->gettmpxPhi()[dim];
+}
+
+double getPattxCoto(int bank, int pattid, int dim) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->gettmpxCoto()[dim];
+}
+
+double getPattxZ(int bank, int pattid, int dim) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->gettmpxZ()[dim];
+}
+
+double getPattcovx(int bank, int pattid, int dim2) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->gettmpcovx()[dim2];
+}
+
+
+
+
+short getPattintc(int bank, int pattid ,int nhit) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->getintc()[nhit];
+}
+
+
+short getPattintphi(int bank, int pattid ,int nhit) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->getintphi()[nhit];
+}
+
+
+short getPattintd0(int bank, int pattid ,int nhit) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->getintd0()[nhit];
+}
+
+short getPattintz0(int bank, int pattid ,int nhit) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->getintz0()[nhit];
+}
+
+
+short getPattinteta(int bank, int pattid ,int nhit) {
+  
+  if( bank >= sortedPatterns.size() ) return 0;
+  if( pattid >= sortedPatterns[bank].size() ) return 0;
+  return sortedPatterns[bank][pattid]->getinteta()[nhit];
+}
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/FTKSectorSlice.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKSectorSlice.cxx
new file mode 100644
index 00000000000..c97883361ef
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/FTKSectorSlice.cxx
@@ -0,0 +1,321 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/FTKSectorSlice.h"
+#include "TrigFTKSim/FTKSetup.h"
+#include <TROOT.h>
+#include <TFile.h>
+#include <TClonesArray.h>
+#include <TBits.h>
+#include <TMath.h>
+#include <GaudiKernel/MsgStream.h>
+#include <iostream>
+
+using namespace std;
+
+FTKSectorSlice::FTKSectorSlice() : 
+  bits_phi(0x0),
+  bits_c(0x0),
+  bits_d(0x0),
+  bits_z0(0x0),
+  bits_ctheta(0x0),
+
+  m_phi_min(-TMath::Pi()),
+  m_phi_max(TMath::Pi()),
+  // m_c_min(-7e-4),
+  // m_c_max(7e-4),
+  m_c_min(-1e-3),
+  m_c_max(1e-3),
+  m_d0_min(-2.2),
+  m_d0_max(2.2),
+  m_z0_min(-120),
+  m_z0_max(120),
+  m_ctheta_min(TMath::SinH(-3)),
+  m_ctheta_max(TMath::SinH(3)),
+  m_eta_min(-3),
+  m_eta_max(3),
+
+  m_autotune_phi_min(999),
+  m_autotune_c_min(999),
+  m_autotune_d0_min(999),
+  m_autotune_z0_min(999),
+  m_autotune_ctheta_min(999),
+  m_autotune_eta_min(999),
+  m_autotune_phi_max(-999),
+  m_autotune_c_max(-999),
+  m_autotune_d0_max(-999),
+  m_autotune_z0_max(-999),
+  m_autotune_ctheta_max(-999),
+  m_autotune_eta_max(-999),
+
+  m_phi_nbins(0),
+  m_c_nbins(0),
+  m_d0_nbins(0),
+  m_z0_nbins(0),
+  m_ctheta_nbins(0),
+
+  m_step_phi(0),
+  m_step_c(0),
+  m_step_d0(0),
+  m_step_z0(0),
+  m_step_ctheta(0),
+
+  m_ITkMode(false)
+  
+{
+  // nothing to do
+}
+
+void FTKSectorSlice::loadSlices(std::string slice_file_path) {
+
+  // Check if using ITk geometry
+  m_ITkMode = FTKSetup::getFTKSetup().getITkMode();
+
+  TFile slice_file(slice_file_path.c_str());
+ 
+  //TClonesArray *bits_phi = (TClonesArray*)slice_file.Get("c_bits_phi");
+  bits_phi = (TClonesArray*) (slice_file.Get("c_bits_phi")->Clone("bitsphi"));
+  m_phi_nbins = bits_phi->GetEntries();
+  m_step_phi = (m_phi_max - m_phi_min)/m_phi_nbins;
+
+  autotune(bits_phi,m_phi_min,m_phi_max,m_autotune_phi_min,m_autotune_phi_max,
+           true,"phi");
+  //TClonesArray *bits_c = (TClonesArray*) slice_file.Get("c_bits_c");
+  bits_c = (TClonesArray*) slice_file.Get("c_bits_c");
+  m_c_nbins = bits_c->GetEntries();
+  m_step_c = (m_c_max - m_c_min)/m_c_nbins;
+
+  autotune(bits_c,m_c_min,m_c_max,m_autotune_c_min,m_autotune_c_max,false,"c");
+
+  //TClonesArray *bits_d = (TClonesArray*)slice_file.Get("c_bits_d");
+  bits_d = (TClonesArray*)slice_file.Get("c_bits_d");
+  m_d0_nbins = bits_d->GetEntries();
+  m_step_d0 = (m_d0_max - m_d0_min)/m_d0_nbins;
+
+  autotune(bits_d,m_d0_min,m_d0_max,m_autotune_d0_min,m_autotune_d0_max,false,
+           "d0");
+
+  //TClonesArray *bits_z0 = (TClonesArray*)slice_file.Get("c_bits_z0");
+  bits_z0 = (TClonesArray*)slice_file.Get("c_bits_z0");
+  m_z0_nbins = bits_z0->GetEntries();
+  m_step_z0 = (m_z0_max - m_z0_min)/m_z0_nbins;
+
+  autotune(bits_z0,m_z0_min,m_z0_max,m_autotune_z0_min,m_autotune_z0_max,false,
+           "z0");
+
+  //TClonesArray *bits_ctheta = (TClonesArray*)slice_file.Get("c_bits_ctheta");
+  bits_ctheta = (TClonesArray*)slice_file.Get("c_bits_ctheta");
+  m_ctheta_nbins = bits_ctheta->GetEntries();
+  m_step_ctheta = (m_ctheta_max - m_ctheta_min)/m_ctheta_nbins;
+
+  autotune(bits_ctheta,m_ctheta_min,m_ctheta_max,
+           m_autotune_ctheta_min,m_autotune_ctheta_max,false,"cos(theta)");
+
+  
+  m_autotune_eta_min=TMath::ASinH(m_autotune_ctheta_min);
+  m_autotune_eta_max=TMath::ASinH(m_autotune_ctheta_max);
+
+#if 0
+  for (int ibin=0;ibin!=m_phi_nbins;++ibin) {
+    TBits *curtbit = (TBits*) bits_phi->At(ibin);
+    
+  }
+#endif
+  cout<<"number of sectors in the slide file \""<<slice_file_path
+      <<"\" : "<<((TBits const *)bits_ctheta->UncheckedAt(0))->GetNbits()
+      <<"\n";
+}
+
+void FTKSectorSlice::autotune
+(const TClonesArray *array,double_t x0,double_t x1,
+ double &autoMin,double &autoMax,bool isAzimuth,const char *debug) {
+   int nbin=array->GetEntries();
+   int i0,i1;
+   for(i0=0;(i0<nbin-1) &&
+          !((TBits const *)array->UncheckedAt(i0))->CountBits();i0++) { }
+   for(i1=nbin-1;(i1>0) &&
+          !((TBits const *)array->UncheckedAt(i1))->CountBits();i1--) { }
+   if(isAzimuth) {
+      int j;
+      vector<char> phi(nbin);
+      for(j=0;j<nbin;j++) { 
+         if(((TBits const *)array->UncheckedAt(j%nbin))->CountBits()) {
+            // add safety margin: +/- 1 bin
+            phi[(j+nbin-1)%nbin]++;
+            phi[(j+nbin)%nbin]++;
+            phi[(j+nbin+1)%nbin]++;
+         }
+      }
+      // locate largest continuous region
+      int gap0=-1,gapStart=-1,gapSize=0;
+      for(j=0;j<2*nbin;j++) { 
+         if(phi[j%nbin]) {
+            if(gap0<0) {
+               // start gap
+               gap0=j;
+            }
+            int size=j+1-gap0;
+            if(size>gapSize) {
+               gapStart=gap0;
+               gapSize=size;
+            }
+         } else {
+            // end gap
+            gap0=-1;
+         }
+      }
+      i0=gapStart;
+      i1=gapStart+gapSize-1;
+   }
+   autoMin=x0+((x1-x0)*i0)/nbin;
+   autoMax=x0+((x1-x0)*(i1+1))/nbin;
+   if(debug) {
+      cout<<"FTKSectorSlice::autotune "<<debug
+          <<" nbin="<<nbin<<" range=[ "<<x0<<" ; "<<x1
+          <<" ] result=[ "<<autoMin<<" ; "<<autoMax<<" ]\n";
+   }
+}
+
+double FTKSectorSlice::getAutotunePhiMin() {
+  return m_autotune_phi_min;
+}
+
+double FTKSectorSlice::getAutotuneCMin() {
+  return m_autotune_c_min;
+}
+
+double FTKSectorSlice::getAutotuneDMin() {
+  return m_autotune_d0_min;
+}
+
+double FTKSectorSlice::getAutotuneZ0Min() {
+  return m_autotune_z0_min;
+}
+
+double FTKSectorSlice::getAutotuneCthetaMin() {
+  return m_autotune_ctheta_min;
+}
+
+double FTKSectorSlice::getAutotuneEtaMin() {
+  return m_autotune_eta_min;
+}
+
+double FTKSectorSlice::getAutotunePhiMax() {
+  return m_autotune_phi_max;
+}
+
+double FTKSectorSlice::getAutotuneCMax() {
+  return m_autotune_c_max;
+}
+
+double FTKSectorSlice::getAutotuneDMax() {
+  return m_autotune_d0_max;
+}
+
+double FTKSectorSlice::getAutotuneZ0Max() {
+  return m_autotune_z0_max;
+}
+
+double FTKSectorSlice::getAutotuneCthetaMax() {
+  return m_autotune_ctheta_max;
+}
+
+double FTKSectorSlice::getAutotuneEtaMax() {
+  return m_autotune_eta_max;
+}
+
+vector<int>* FTKSectorSlice::searchSectors(FTKTrack& track) {
+  
+  //std::vector<int> sectors;
+  Int_t bin;
+  //Int_t bin_phi, bin_c, bin_d0, bin_z0, bin_ctheta;
+  TBits *phi_bits;
+  TBits *c_bits;
+  TBits *d0_bits;
+  TBits *z0_bits;
+  TBits *ctheta_bits;
+
+  int error=0;
+
+  if ((track.getPhi()<m_phi_min) || (track.getPhi()>m_phi_max)) {
+    cout << "Error: wrong phi parameter " << track.getPhi() << '\n';
+    error++;
+  }
+  if ((2.*track.getHalfInvPt()<m_c_min) ||
+      (2.*track.getHalfInvPt()>m_c_max)) {
+    cout << "Error: wrong c parameter " << 2.*track.getHalfInvPt() << '\n';
+    error++;
+  }
+  if ((track.getIP()<m_d0_min) || (track.getIP()>m_d0_max)) {
+    cout << "Error: wrong d0 parameter " << track.getIP() << '\n';
+    error++;
+  }
+  if ((track.getZ0()<m_z0_min) || (track.getZ0()>m_z0_max)) {
+    cout << "Error: wrong z0 parameter " << track.getZ0() << '\n';
+    error++;
+  }
+  if ((track.getCotTheta()<m_ctheta_min) || (track.getCotTheta()>m_ctheta_max)) {
+    cout << "Error: wrong ctheta parameter " << track.getCotTheta() << '\n';
+    error++;
+  }
+  //if(error) exit(0);
+
+
+  bin = (Int_t)((track.getPhi()-m_phi_min)/m_step_phi);
+  bin = (bin+ m_phi_nbins)% m_phi_nbins; // modulo operator: phi wraps around
+  //bin_phi = bin;
+  phi_bits = (TBits*)(bits_phi->UncheckedAt(bin));
+  //phi_bits = (TBits*)(bits_phi->At(bin));
+  
+  bin = (Int_t)((2.*track.getHalfInvPt()-m_c_min)/m_step_c);
+  // If the bin underrun or overrun set to min or max bin
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > m_c_nbins-1) ? m_c_nbins-1 : bin;
+  //bin_c = bin;
+  c_bits = (TBits*)(bits_c->UncheckedAt(bin));
+  //c_bits = (TBits*)(bits_c->At(bin));
+
+  bin = (Int_t)((track.getIP()-m_d0_min)/m_step_d0);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > m_d0_nbins-1) ? m_d0_nbins-1 : bin;
+  //bin_d0 = bin;
+  d0_bits = (TBits*)(bits_d->UncheckedAt(bin));
+  //d0_bits = (TBits*)(bits_d->At(bin));
+
+  bin = (Int_t)((track.getZ0()-m_z0_min)/m_step_z0);
+  bin = (bin < 0) ? 0 : bin;
+  //bin = (bin > m_z0_nbins) ? m_z0_nbins-1 : bin;
+  bin = (bin > m_z0_nbins-1) ? m_z0_nbins-1 : bin;
+  //bin_z0 = bin;
+  z0_bits = (TBits*)(bits_z0->UncheckedAt(bin));
+  //z0_bits = (TBits*)(bits_z0->At(bin));
+
+  bin = (Int_t)((track.getCotTheta()-m_ctheta_min)/m_step_ctheta);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > m_ctheta_nbins-1) ? m_ctheta_nbins-1 : bin;
+  //bin_ctheta = bin;
+  ctheta_bits = (TBits*)(bits_ctheta->UncheckedAt(bin));
+  //ctheta_bits = (TBits*)(bits_ctheta->At(bin));
+
+  TBits result_bits(c_bits->GetNbits());
+
+  // AND of all TBits
+  /// c-slices are ill-defined ???
+  /// remove 29.11.2016, STS
+  ///  result_bits = *c_bits;
+  ///  result_bits &= *d0_bits;
+  result_bits = *d0_bits;
+  result_bits &= *phi_bits;
+  result_bits &= *z0_bits;
+  result_bits &= *ctheta_bits;
+  
+  vector<int> *sectors = new vector<int>();
+  unsigned int curPos = result_bits.FirstSetBit(0);
+  while (curPos != result_bits.GetNbits()) {
+    sectors->push_back((int) curPos);
+
+    curPos = result_bits.FirstSetBit(curPos+1);
+  }
+  
+  return sectors;
+}
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/PattMergeRootAlgo.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/PattMergeRootAlgo.cxx
new file mode 100644
index 00000000000..fa8c83e4356
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/PattMergeRootAlgo.cxx
@@ -0,0 +1,116 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/PattMergeRootAlgo.h"
+#include "TString.h"
+#include "TrigFTKSim/FTKMergeRoot.h"
+
+
+// #include "TrigFTKSim/FTKRootFile.h"
+// #include "TrigFTKSim/FTKPatternBySector.h"
+// #include "TrigFTKSim/FTKPatternWithCoverage.h"
+
+using namespace std;
+/////////////////////////////////////////////////////////////////////////////
+
+PattMergeRootAlgo::PattMergeRootAlgo(const std::string& name, ISvcLocator* pSvcLocator):
+   AthAlgorithm(name, pSvcLocator), m_MinCov(0),m_Compression(-1)
+{
+   SetLogger(this);
+   declareProperty("MinCoverage",m_MinCov);
+   declareProperty("Compression",m_Compression);
+   declareProperty("TextImportRootFile",m_TextImportRootFile);
+   declareProperty("RootOutFile",m_RootOutFile);
+   declareProperty("TextOutFile",m_TextOutFile);
+   declareProperty("NSub",m_NSub);
+   declareProperty("InputFiles",m_InputFiles, "Input files.");
+   declareProperty("WhereToRunMerging",m_WhereToRunMerging);
+   declareProperty("DeleteFilesAfterMerging",m_DeleteAfterMerging);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+PattMergeRootAlgo::~PattMergeRootAlgo() {
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode PattMergeRootAlgo::initialize() {
+ 
+   if ( !( TString(m_WhereToRunMerging).BeginsWith("i") 
+	   || TString(m_WhereToRunMerging).BeginsWith("f") 
+	   || TString(m_WhereToRunMerging).BeginsWith("e")) ) {
+      ATH_MSG_WARNING("PattMergeRootAlgo() "<< "WhereToRunMerging must start with 'i', 'e' or 'f' referring to the three steps of an athena algorithm (initialize, execute, finalize), but is: "<<m_WhereToRunMerging);
+      return StatusCode::FAILURE;
+   }   
+
+   SetLogger(this);
+   ATH_MSG_INFO ("initialize()");
+   if ( TString(m_WhereToRunMerging).BeginsWith("i") ) return RunMerging();
+   else return StatusCode::SUCCESS;
+} 
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+StatusCode PattMergeRootAlgo::execute() {
+   ATH_MSG_INFO ("execute()");
+   if ( TString(m_WhereToRunMerging).BeginsWith("e") ) return RunMerging();
+   else return StatusCode::SUCCESS;
+} 
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+StatusCode PattMergeRootAlgo::finalize() {
+   ATH_MSG_INFO ("finalize()");
+   if ( TString(m_WhereToRunMerging).BeginsWith("f") ) return RunMerging();
+   else return StatusCode::SUCCESS;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+StatusCode PattMergeRootAlgo::RunMerging() {
+   //! Do merging.
+   int error=0;
+   FTKMergeRoot merger(m_RootOutFile);
+   merger.SetDeleteFilesAfterMerging(m_DeleteAfterMerging);
+   // set text-import name if available
+   if ( m_TextImportRootFile!="" && TString(m_TextImportRootFile).EndsWith(".root") )
+      merger.SetTempRootFileName(m_TextImportRootFile);
+   else if ( m_TextImportRootFile!="" && TString(m_TextImportRootFile).EndsWith(".root") )
+      ATH_MSG_WARNING("TextImportRootFile does not end with .root. Using default TextImportName instead for temporary file.");
+   // add files to merger
+   merger.AddFiles(m_InputFiles);
+   // set number of sub regions (only supported by 'text-output')
+   //ATH_MSG_INFO ("RunMerging(). SetNSubregions: "<<m_NSub);
+   merger.SetNSubregions(m_NSub);
+   // do merging
+   error += merger.DoMerge(m_MinCov,m_Compression);
+   // write out in addition ascii-file if output file did not ended with '.root'
+   if ( m_TextOutFile!="" && !TString(m_TextOutFile).EndsWith(".root") ) 
+      merger.DoTextExport(m_TextOutFile);
+   //done
+   return error>0? StatusCode::FAILURE : StatusCode::SUCCESS;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
+void PattMergeRootAlgo::PostMessage(void) {
+   if(FTKLogger::m_type==0)  ATH_MSG_FATAL(m_buffer->str());
+   else if(FTKLogger::m_type==1)  ATH_MSG_ERROR(m_buffer->str());
+   else if(FTKLogger::m_type==2)  ATH_MSG_WARNING(m_buffer->str());
+   else if(FTKLogger::m_type==3)  ATH_MSG_INFO(m_buffer->str());
+   else if(FTKLogger::m_type==4)  ATH_MSG_DEBUG(m_buffer->str());
+}
+
+
+// // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/atlparslice_root.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/atlparslice_root.cxx
new file mode 100644
index 00000000000..7ce390a52ff
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/atlparslice_root.cxx
@@ -0,0 +1,459 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "TrigFTKBankGen/atlparslice_root.h"
+#include <cstdlib>
+
+TSlices **s;
+
+TSlices::TSlices(int *nslices, double *minvals, double *maxvals) {
+  curPos=0;
+  result_bits=0;
+  ofile=0;
+  par_c_slices = nslices[0];
+  par_c_max = maxvals[0];
+  par_c_min = minvals[0];
+  
+  par_d_slices = nslices[1];
+  par_d_max = maxvals[1];
+  par_d_min = minvals[1];
+
+  par_phi_slices = nslices[2];
+  par_phi_max = maxvals[2];
+  par_phi_min = minvals[2];
+  
+  par_z0_slices = nslices[3];
+  par_z0_max = maxvals[3];
+  par_z0_min = minvals[3];
+  
+  par_ctheta_slices = nslices[4];
+  par_ctheta_max = maxvals[4];
+  par_ctheta_min = minvals[4];
+}
+
+TSlices::~TSlices() {
+  if(ofile) if(ofile->IsOpen()) ofile->Close();
+  return;
+}
+
+void initNSlices(int N, int *nslices, double *minvals, double *maxvals) {
+  s = new TSlices*[N];
+  if(!s) {
+    std::cout << "Failed to allocate TSlices*[] of size " << N << "; exiting..." << std::endl;
+    exit(-1);
+  }
+  for(int i=0;i<N;i++) {
+    s[i] = new TSlices(nslices,minvals,maxvals);
+    if(!s) {
+      std::cout << "Failed to allocate TSlices[" << i << "]; exiting..." << std::endl;
+      exit(-1);
+    }
+  }
+}
+
+void initSlices(int index, int nsectors) {
+  s[index]->c_bits_c = new TClonesArray("TBits",s[index]->par_c_slices);
+  for(Int_t i = 0; i < s[index]->par_c_slices; ++i) {
+    new((*s[index]->c_bits_c)[i]) TBits(nsectors);
+  }
+  s[index]->c_bits_d = new TClonesArray("TBits",s[index]->par_d_slices);
+  for(Int_t i = 0; i < s[index]->par_d_slices; ++i) {
+    new((*s[index]->c_bits_d)[i]) TBits(nsectors);
+  }
+  s[index]->c_bits_phi = new TClonesArray("TBits",s[index]->par_phi_slices);
+  for(Int_t i = 0; i < s[index]->par_phi_slices; ++i) {
+    new((*s[index]->c_bits_phi)[i]) TBits(nsectors);
+  }
+  s[index]->c_bits_z0 = new TClonesArray("TBits",s[index]->par_z0_slices);
+  for(Int_t i = 0; i < s[index]->par_z0_slices; ++i) {
+    new((*s[index]->c_bits_z0)[i]) TBits(nsectors);
+  }
+  s[index]->c_bits_ctheta = new TClonesArray("TBits",s[index]->par_ctheta_slices);
+  for(Int_t i = 0; i < s[index]->par_ctheta_slices; ++i) {
+    new((*s[index]->c_bits_ctheta)[i]) TBits(nsectors);
+  }
+}
+void addSectorToSlice(int index, int sector, int c, int d, int phi, int z0, int ctheta) {
+  Int_t bin;
+  TBits *t;
+
+#ifdef DEBUG_ADDSECTORTOSLICE
+  Int_t bin_c,bin_d,bin_phi,bin_z0,bin_ctheta;
+#endif
+    bin =c;
+    bin = (bin < 0) ? 0 : bin;
+    bin = (bin > s[index]->par_c_slices-1) ? s[index]->par_c_slices-1 : bin;
+#ifdef DEBUG_ADDSECTORTOSLICE
+    bin_c = bin;
+#endif
+    t = (TBits *)(s[index]->c_bits_c->UncheckedAt(bin));
+    t->SetBitNumber(sector);
+        
+    bin = d;
+    bin = (bin < 0) ? 0 : bin;
+    bin = (bin > s[index]->par_d_slices-1) ? s[index]->par_d_slices-1 : bin;
+#ifdef DEBUG_ADDSECTORTOSLICE
+    bin_d = bin;
+#endif
+    t = (TBits *)(s[index]->c_bits_d->UncheckedAt(bin));
+    t->SetBitNumber(sector);
+    
+    bin= phi;
+    bin = (bin < 0) ? 0 : bin;
+    bin = (bin > s[index]->par_phi_slices-1) ? s[index]->par_phi_slices-1 : bin;
+#ifdef DEBUG_ADDSECTORTOSLICE
+    bin_phi = bin;
+#endif
+    t = (TBits *)(s[index]->c_bits_phi->UncheckedAt(bin));
+    t->SetBitNumber(sector);
+
+    
+    bin =z0;
+    bin = (bin < 0) ? 0 : bin;
+    bin = (bin > s[index]->par_z0_slices-1) ? s[index]->par_z0_slices-1 : bin;
+#ifdef DEBUG_ADDSECTORTOSLICE
+    bin_z0 = bin;
+#endif
+    t = (TBits *)(s[index]->c_bits_z0->UncheckedAt(bin));
+    t->SetBitNumber(sector);
+      
+    bin = ctheta;
+    bin = (bin < 0) ? 0 : bin;
+    bin = (bin > s[index]->par_ctheta_slices-1) ? s[index]->par_ctheta_slices-1 : bin;
+#ifdef DEBUG_ADDSECTORTOSLICE
+    bin_ctheta = bin;
+#endif
+    t = (TBits *)(s[index]->c_bits_ctheta->UncheckedAt(bin));
+    t->SetBitNumber(sector);
+
+#ifdef DEBUG_ADDSECTORTOSLICE
+    printf("AK %d %d %f %d %f %d %f %d %f %d %f\n",sector,bin_c,1/2.0/c,bin_d,d,bin_phi,phi,bin_z0,z0,bin_ctheta,ctheta);
+#endif
+}
+
+void saveSlices(int index, char *slice_file) {
+  s[index]->ofile = new TFile(slice_file,"recreate");
+  s[index]->c_bits_c->Write("c_bits_c",TObject::kSingleKey);
+  s[index]->c_bits_d->Write("c_bits_d",TObject::kSingleKey);
+  s[index]->c_bits_phi->Write("c_bits_phi",TObject::kSingleKey);
+  s[index]->c_bits_z0->Write("c_bits_z0",TObject::kSingleKey);
+  s[index]->c_bits_ctheta->Write("c_bits_ctheta",TObject::kSingleKey);
+  s[index]->ofile->Close();
+}
+
+void loadSlices(int index, char *slice_file) {
+  s[index]->ofile = new TFile(slice_file);
+  s[index]->c_bits_c = (TClonesArray*)s[index]->ofile->Get("c_bits_c");
+  s[index]->c_bits_d = (TClonesArray*)s[index]->ofile->Get("c_bits_d");
+  s[index]->c_bits_phi = (TClonesArray*)s[index]->ofile->Get("c_bits_phi");
+  s[index]->c_bits_z0 = (TClonesArray*)s[index]->ofile->Get("c_bits_z0");
+  s[index]->c_bits_ctheta = (TClonesArray*)s[index]->ofile->Get("c_bits_ctheta");
+}
+
+void searchSectors(int index, double c, double d, double phi, double z0, double ctheta) {
+  TBits *c_bits;
+  TBits *d_bits;
+  TBits *phi_bits;
+  TBits *z0_bits;
+  TBits *ctheta_bits;
+  Int_t bin;
+  Double_t step;
+
+#ifdef DEBUG_SEARCH_SECTORS
+  Int_t bin1,bin2,bin3,bin4,bin5;
+#endif
+  
+  // Find bit arrays
+  // Compute form parameters the step size
+  step = (s[index]->par_c_max - s[index]->par_c_min)/s[index]->par_c_slices;
+  // Compute the bin
+  bin = (Int_t)((c - s[index]->par_c_min)/step);
+  // If the bin underrun or overrun set to min or max bin
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_c_slices-1) ? s[index]->par_c_slices-1 : bin;
+#ifdef DEBUG_SEARCH_SECTORS
+  bin1=bin;
+#endif
+  // Fetch TBits for the bin, the use of UncheckedAt is fast but risky
+  c_bits = (TBits *)(s[index]->c_bits_c->UncheckedAt(bin));
+  // Same for other parameters
+  step = (s[index]->par_d_max - s[index]->par_d_min)/s[index]->par_d_slices;
+  bin = (Int_t)((d - s[index]->par_d_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_d_slices-1) ? s[index]->par_d_slices-1 : bin;
+#ifdef DEBUG_SEARCH_SECTORS
+  bin2=bin;
+#endif
+  d_bits = (TBits *)(s[index]->c_bits_d->UncheckedAt(bin));
+  step = (s[index]->par_phi_max - s[index]->par_phi_min)/s[index]->par_phi_slices;
+  bin = (Int_t)((phi - s[index]->par_phi_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_phi_slices-1) ? s[index]->par_phi_slices-1 : bin;
+#ifdef DEBUG_SEARCH_SECTORS
+  bin3=bin;
+#endif
+  phi_bits = (TBits *)(s[index]->c_bits_phi->UncheckedAt(bin));
+  step = (s[index]->par_z0_max - s[index]->par_z0_min)/s[index]->par_z0_slices;
+  bin = (Int_t)((z0 - s[index]->par_z0_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_z0_slices-1) ? s[index]->par_z0_slices-1 : bin;
+#ifdef DEBUG_SEARCH_SECTORS
+  bin4=bin;
+#endif
+  z0_bits = (TBits *)(s[index]->c_bits_z0->UncheckedAt(bin));
+  step = (s[index]->par_ctheta_max - s[index]->par_ctheta_min)/s[index]->par_ctheta_slices;
+  bin = (Int_t)((ctheta - s[index]->par_ctheta_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_ctheta_slices-1) ? s[index]->par_ctheta_slices-1 : bin;
+#ifdef DEBUG_SEARCH_SECTORS
+  bin5=bin;
+#endif
+  ctheta_bits = (TBits *)(s[index]->c_bits_ctheta->UncheckedAt(bin));
+
+  // Initialize result bits
+  if(s[index]->result_bits == NULL)
+    s[index]->result_bits = new TBits(c_bits->GetNbits());
+
+  // AND of all TBits
+  *s[index]->result_bits = *c_bits;
+  *s[index]->result_bits &= *d_bits;
+  *s[index]->result_bits &= *phi_bits;
+  *s[index]->result_bits &= *z0_bits;
+  *s[index]->result_bits &= *ctheta_bits;
+
+#ifdef DEBUG_SEARCH_SECTORS
+   printf("pt=%.2f\td0=%.2f\tphi=%.2f\tz0=%.2f\tctheta=%.2f\n",1/(2*c),d,phi,z0,ctheta);
+   printf("bins = %d\t%d\t%d\t%d\t%d\n",bin1,bin2,bin3,bin4,bin5);
+   std::cout << c_bits->CountBits() << std::endl;
+   std::cout << d_bits->CountBits() << std::endl;
+   std::cout << phi_bits->CountBits() << std::endl;
+   std::cout << z0_bits->CountBits() << std::endl;
+   std::cout << ctheta_bits->CountBits() << std::endl;
+   std::cout << "FINAL: " << (*s[index]->result_bits).CountBits() << std::endl;
+#endif
+
+  // Reset position
+  s[index]->curPos=0;
+  // printf("phi=%f, bins = %d,%d,%d,%d,%d\n",phi,bin1,bin2,bin3,bin4,bin5);
+
+}
+
+int checkSector(int index, int sector, double c, double d, double phi, double z0, double ctheta) {
+  TBits *c_bits;
+  TBits *d_bits;
+  TBits *phi_bits;
+  TBits *z0_bits;
+  TBits *ctheta_bits;
+  Double_t step;
+  Int_t bin;
+
+  // Find bit arrays
+  step = (s[index]->par_c_max - s[index]->par_c_min)/s[index]->par_c_slices;
+  bin = (Int_t)((c - s[index]->par_c_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_c_slices-1) ? s[index]->par_c_slices-1 : bin;
+  c_bits = (TBits *)(s[index]->c_bits_c->UncheckedAt(bin));
+  step = (s[index]->par_d_max - s[index]->par_d_min)/s[index]->par_d_slices;
+  bin = (Int_t)((d - s[index]->par_d_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_d_slices-1) ? s[index]->par_d_slices-1 : bin;
+  d_bits = (TBits *)(s[index]->c_bits_d->UncheckedAt(bin));
+  step = (s[index]->par_phi_max - s[index]->par_phi_min)/s[index]->par_phi_slices;
+  bin = (Int_t)((phi - s[index]->par_phi_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_phi_slices-1) ? s[index]->par_phi_slices-1 : bin;
+  phi_bits = (TBits *)(s[index]->c_bits_phi->UncheckedAt(bin));
+  step = (s[index]->par_z0_max - s[index]->par_z0_min)/s[index]->par_z0_slices;
+  bin = (Int_t)((z0 - s[index]->par_z0_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_z0_slices-1) ? s[index]->par_z0_slices-1 : bin;
+  z0_bits = (TBits *)(s[index]->c_bits_z0->UncheckedAt(bin));
+  step = (s[index]->par_ctheta_max - s[index]->par_ctheta_min)/s[index]->par_ctheta_slices;
+  bin = (Int_t)((ctheta - s[index]->par_ctheta_min)/step);
+  bin = (bin < 0) ? 0 : bin;
+  bin = (bin > s[index]->par_ctheta_slices-1) ? s[index]->par_ctheta_slices-1 : bin;
+  ctheta_bits = (TBits *)(s[index]->c_bits_ctheta->UncheckedAt(bin));
+
+  if(c_bits->TestBitNumber(sector) &&
+     d_bits->TestBitNumber(sector) &&
+     phi_bits->TestBitNumber(sector) &&
+     z0_bits->TestBitNumber(sector) &&
+     ctheta_bits->TestBitNumber(sector))
+    return 1;
+  return 0;
+  // done
+}
+
+/*
+double autotuneMinC(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = 0; i < s[index]->c_bits_c->GetEntries(); ++i) {
+    tb = (TBits *)(s[index]->c_bits_c->UncheckedAt(i));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_c_max - s[index]->par_c_min)/s[index]->par_c_slices;
+	return s[index]->par_c_min + step*i;
+    }
+  }
+}
+double autotuneMinD(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = 0; i < s[index]->c_bits_d->GetEntries(); ++i) {
+    tb = (TBits *)(s[index]->c_bits_d->UncheckedAt(i));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_d_max - s[index]->par_d_min)/s[index]->par_d_slices;
+	return s[index]->par_d_min + step*i;
+    }
+  }
+}
+double autotuneMinPhi(int index) {
+  Double_t step;
+  Double_t val;
+  bool ignore_neg = false;
+  TBits *tb;
+  for(Int_t i = 0; i < s[index]->c_bits_phi->GetEntries(); ++i) {
+    tb = (TBits *)(s[index]->c_bits_phi->UncheckedAt(i));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+      if(i==0) ignore_neg=true; // Special fix at the boundary -pi
+      step = (s[index]->par_phi_max - s[index]->par_phi_min)/s[index]->par_phi_slices;
+      val = (double)s[index]->par_phi_min + (double)step*i;
+      if(ignore_neg && val<0) continue;
+      return val;
+    }
+  }
+}
+double autotuneMinZ0(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = 0; i < s[index]->c_bits_z0->GetEntries(); ++i) {
+    tb = (TBits *)(s[index]->c_bits_z0->UncheckedAt(i));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+      step = (s[index]->par_z0_max - s[index]->par_z0_min)/s[index]->par_z0_slices;
+      return s[index]->par_z0_min + step*i;
+    }
+  }
+}
+double autotuneMinCtheta(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = 0; i < s[index]->c_bits_ctheta->GetEntries(); ++i) {
+    tb = (TBits *)(s[index]->c_bits_ctheta->UncheckedAt(i));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_ctheta_max - s[index]->par_ctheta_min)/s[index]->par_ctheta_slices;
+	return s[index]->par_ctheta_min + step*i;
+    }
+  }
+}
+double autotuneMinEta(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = 0; i < s[index]->c_bits_ctheta->GetEntries(); ++i) {
+    tb = (TBits *)(s[index]->c_bits_ctheta->UncheckedAt(i));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_ctheta_max - s[index]->par_ctheta_min)/s[index]->par_ctheta_slices;
+	return TMath::ASinH(s[index]->par_ctheta_min + step*i);
+    }
+  }
+}
+
+double autotuneMaxC(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = s[index]->c_bits_c->GetEntries(); i > 0; --i) {
+    tb = (TBits *)(s[index]->c_bits_c->UncheckedAt(i-1));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_c_max - s[index]->par_c_min)/s[index]->par_c_slices;
+	return s[index]->par_c_max - step*(s[index]->c_bits_c->GetEntries() - i);
+    }
+  }
+}
+double autotuneMaxD(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = s[index]->c_bits_d->GetEntries(); i > 0; --i) {
+    tb = (TBits *)(s[index]->c_bits_d->UncheckedAt(i-1));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_d_max - s[index]->par_d_min)/s[index]->par_d_slices;
+	return s[index]->par_d_max - step*(s[index]->c_bits_d->GetEntries() - i);
+    }
+  }
+}
+// this magic is needed to properly handle +/- Pi boundary. I won't work with <=4 regions
+double autotuneMaxPhi(int index) {
+  Double_t step;
+  Double_t val;
+  bool ignore_pos = false;
+  Int_t entries = s[index]->c_bits_phi->GetEntries();
+  TBits *tb;
+  step = (s[index]->par_phi_max - s[index]->par_phi_min)/s[index]->par_phi_slices;
+  for(Int_t i = entries; i > 0; --i) {
+    tb = (TBits *)(s[index]->c_bits_phi->UncheckedAt(i-1));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+      if(i==entries) ignore_pos=true; // Special fix at the boundary +pi
+      val = s[index]->par_phi_max - step*(s[index]->c_bits_phi->GetEntries() - i);
+      if(ignore_pos && val>0) continue;
+      return (ignore_pos ? val + 2*TMath::Pi() : val);
+    }
+  }
+}
+double autotuneMaxZ0(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = s[index]->c_bits_z0->GetEntries(); i > 0; --i) {
+    tb = (TBits *)(s[index]->c_bits_z0->UncheckedAt(i-1));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_z0_max - s[index]->par_z0_min)/s[index]->par_z0_slices;
+	return s[index]->par_z0_max - step*(s[index]->c_bits_z0->GetEntries() - i);
+    }
+  }
+}
+double autotuneMaxCtheta(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = s[index]->c_bits_ctheta->GetEntries(); i > 0; --i) {
+    tb = (TBits *)(s[index]->c_bits_ctheta->UncheckedAt(i-1));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_ctheta_max - s[index]->par_ctheta_min)/s[index]->par_ctheta_slices;
+	return s[index]->par_ctheta_max - step*(s[index]->c_bits_ctheta->GetEntries() - i);
+    }
+  }
+}
+double autotuneMaxEta(int index) {
+  Double_t step;
+  TBits *tb;
+  for(Int_t i = s[index]->c_bits_ctheta->GetEntries(); i > 0; --i) {
+    tb = (TBits *)(s[index]->c_bits_ctheta->UncheckedAt(i-1));
+    if(tb->FirstSetBit() != tb->GetNbits()) {
+        step = (s[index]->par_ctheta_max - s[index]->par_ctheta_min)/s[index]->par_ctheta_slices;
+	return TMath::ASinH(s[index]->par_ctheta_max - step*(s[index]->c_bits_ctheta->GetEntries() - i));
+    }
+  }
+}
+
+
+void printSectors(int index) {
+  unsigned int pos = 0;
+  printf("Matched these sectors: ");
+  while(1) {
+    pos = s[index]->result_bits->FirstSetBit(pos+1);
+    if(pos == s[index]->result_bits->GetNbits()) {
+      pos = 0;
+      break;
+    }
+    printf("%d ",pos);
+  }
+  printf("\n");
+}
+
+int popSector(int index) {
+  unsigned int pbup = s[index]->curPos;
+  s[index]->curPos = s[index]->result_bits->FirstSetBit(s[index]->curPos+1);
+  if(s[index]->curPos == s[index]->result_bits->GetNbits()) {
+    s[index]->curPos = 0;
+    return -1;
+  } else {
+    return s[index]->curPos;
+  }
+}
+*/
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_entries.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_entries.cxx
new file mode 100644
index 00000000000..da304f527c2
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_entries.cxx
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+#include "TrigFTKBankGen/FTKBankGenAlgo.h"
+#include "TrigFTKBankGen/FTKConstGenAlgo.h"
+
+#include "TrigFTKBankGen/PattMergeRootAlgo.h"
+
+#include "TrigFTKBankGen/FTKPattGenRootAlgo.h"
+
+#include "TrigFTKBankGen/FTKCachedBankGenAlgo.h"
+
+DECLARE_ALGORITHM_FACTORY(FTKBankGenAlgo)
+DECLARE_ALGORITHM_FACTORY(FTKConstGenAlgo)
+
+DECLARE_ALGORITHM_FACTORY(PattMergeRootAlgo)
+
+DECLARE_ALGORITHM_FACTORY(FTKPattGenRootAlgo)
+
+DECLARE_ALGORITHM_FACTORY(FTKCachedBankGenAlgo)
+
+DECLARE_FACTORY_ENTRIES(TrigFTKBankGen) {
+  DECLARE_ALGORITHM(FTKBankGenAlgo);
+  DECLARE_ALGORITHM(FTKConstGenAlgo);
+
+  DECLARE_ALGORITHM(PattMergeRootAlgo);
+
+  DECLARE_ALGORITHM(FTKTSPBankGenAlgo);
+
+  DECLARE_ALGORITHM(FTKCachedBankGenAlgo);
+}
diff --git a/Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_load.cxx b/Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_load.cxx
new file mode 100644
index 00000000000..156d43e6928
--- /dev/null
+++ b/Trigger/TrigFTK/TrigFTKBankGen/src/components/TrigFTKBankGen_load.cxx
@@ -0,0 +1,6 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES(TrigFTKBankGen)
diff --git a/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorTool.h b/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorTool.h
index e1624c1bc0e..8e00b412847 100644
--- a/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorTool.h
+++ b/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorTool.h
@@ -136,6 +136,8 @@ public:
   virtual void dumpGlobalToLocalModuleMap();
 
   virtual void dumpIDMap();
+
+  virtual void dumpModulePositions();
 };
 
 #endif // FTKDetectorTool_h
diff --git a/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorToolI.h b/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorToolI.h
index d265d44ce04..6b1f1525c86 100644
--- a/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorToolI.h
+++ b/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDetectorToolI.h
@@ -32,6 +32,8 @@ class FTKDetectorToolI : virtual public IAlgTool
 
   virtual void dumpGlobalToLocalModuleMap() = 0;
 
+  virtual void dumpModulePositions() =0;
+
   virtual void dumpIDMap() = 0;
 };
 
diff --git a/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDumpCondAlgo.h b/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDumpCondAlgo.h
index d53a2eda02b..377191f190b 100644
--- a/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDumpCondAlgo.h
+++ b/Trigger/TrigFTK/TrigFTKSim/TrigFTKSim/FTKDumpCondAlgo.h
@@ -38,6 +38,8 @@ private:
 
   bool m_DumpIDMap;
 
+  bool m_DumpModulePositions;
+
   int m_IBLMode;
   bool m_ITkMode;
   bool m_fixEndcapL0; //fix for endcap L0 in clustering
diff --git a/Trigger/TrigFTK/TrigFTKSim/scripts/TrigFTKSim_tf.py b/Trigger/TrigFTK/TrigFTKSim/scripts/TrigFTKSim_tf.py
index de82fcfe1cf..9210adc7d1c 100755
--- a/Trigger/TrigFTK/TrigFTKSim/scripts/TrigFTKSim_tf.py
+++ b/Trigger/TrigFTK/TrigFTKSim/scripts/TrigFTKSim_tf.py
@@ -198,6 +198,8 @@ def addFTKSimulationArgs(parser):
                         help='6/8 option for transition region', group='TrigFTKSim')
     parser.add_argument('--Save1stStageTrks', default=False, type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True),
                         help='keep 1st stage tracks', group='TrigFTKSim')
+    parser.add_argument('--dumpModuleGeom', default=False, type=trfArgClasses.argFactory(trfArgClasses.argBool, runarg=True),
+                        help='dump module geometry', group='TrigFTKSim')
     #end JDC
 
 
diff --git a/Trigger/TrigFTK/TrigFTKSim/share/FTKDumpCond_8LcIbl123_jobOptions.py b/Trigger/TrigFTK/TrigFTKSim/share/FTKDumpCond_8LcIbl123_jobOptions.py
index fbe387c73d4..100e31caef9 100644
--- a/Trigger/TrigFTK/TrigFTKSim/share/FTKDumpCond_8LcIbl123_jobOptions.py
+++ b/Trigger/TrigFTK/TrigFTKSim/share/FTKDumpCond_8LcIbl123_jobOptions.py
@@ -14,14 +14,15 @@ print "Add FTKDetector tool"
 FTKDet = FTKDetectorTool()
 FTKDet.FTK_BadModuleMapPath = "badModulemap_8Lc_FTK.bmap"
 FTKDet.ATLAS_BadModuleMapPath = "badModulemap_8Lc_ATLAS.bmap"
-FTKDet.pmap_path = "../Trigger/TrigFTK/TrigFTKSim/config/map_file/raw_8LcIbl123.pmap"
-FTKDet.rmap_path = "../Trigger/TrigFTK/TrigFTKSim/config/map_file/raw_12Libl.tmap"
+FTKDet.pmap_path = "x86_64-slc6-gcc62-opt/share/ftk_configuration/map_files/raw_8LcIbl123.pmap"
+FTKDet.rmap_path = "x86_64-slc6-gcc62-opt/share/ftk_configuration/map_files/raw_12Libl.tmap"
 ToolSvc += FTKDet
 
 FTKDumpCond = FTKDumpCondAlgo( "FTKDumpCondAlgo" , OutputLevel=INFO)
 FTKDumpCond.IBLMode = 1
 FTKDumpCond.DumpBadModules = True
 FTKDumpCond.DumpGlobalToLocalMap = True
+FTKDumpCond.DumpModulePositions = True
 theJob += FTKDumpCond  
 
 print theJob
diff --git a/Trigger/TrigFTK/TrigFTKSim/share/skeleton.FTKStandaloneSim.py b/Trigger/TrigFTK/TrigFTKSim/share/skeleton.FTKStandaloneSim.py
index cc3fca21ad6..a74b0b1a722 100644
--- a/Trigger/TrigFTK/TrigFTKSim/share/skeleton.FTKStandaloneSim.py
+++ b/Trigger/TrigFTK/TrigFTKSim/share/skeleton.FTKStandaloneSim.py
@@ -1106,8 +1106,26 @@ for runArgName in (runArgsFromTrfMandatory
         raise RuntimeError("Failed to find mandatory FTKTrackFitter runtime "
                            "argument for transform %s" % runArgName)
 
-alg += FTKRoadFinder
-alg += FTKTrackFitter
+if hasattr(runArgs,"dumpModuleGeom"):
+    from TrigFTKSim.TrigFTKSimConf import FTKDetectorTool, FTKDumpCondAlgo 
+    FTKDet = FTKDetectorTool()
+    FTKDet.FTK_BadModuleMapPath = "badModulemap_FTK.bmap"
+    FTKDet.ATLAS_BadModuleMapPath = "badModulemap_ATLAS.bmap"
+    FTKDet.pmap_path = runArgs.pmap_path
+    FTKDet.rmap_path = runArgs.rmap_path
+    ToolSvc += FTKDet
+
+    FTKDumpCond = FTKDumpCondAlgo("FTKDumpCondAlgo" , OutputLevel=INFO)
+    FTKDumpCond.IBLMode = runArgs.IBLMode
+    FTKDumpCond.DumpBadModules = False
+    FTKDumpCond.DumpGlobalToLocalMap = False
+    FTKDumpCond.DumpModulePositions = True
+
+    alg += FTKDumpCond
+
+else :
+    alg += FTKRoadFinder
+    alg += FTKTrackFitter
 
 if not FTKTrackFitter.doTrackFile :
     from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
diff --git a/Trigger/TrigFTK/TrigFTKSim/src/FTKDetectorTool.cxx b/Trigger/TrigFTK/TrigFTKSim/src/FTKDetectorTool.cxx
index e75119647b3..5bf579032ae 100644
--- a/Trigger/TrigFTK/TrigFTKSim/src/FTKDetectorTool.cxx
+++ b/Trigger/TrigFTK/TrigFTKSim/src/FTKDetectorTool.cxx
@@ -10,6 +10,10 @@
 #include <fstream>
 #include <iostream>
 
+#include <TFile.h>
+#include <TTree.h>
+#include <TMath.h>
+
 using namespace std;
 
 FTKDetectorTool::FTKDetectorTool(const std::string &algname,const std::string &name, const IInterface *ifc)
@@ -471,3 +475,39 @@ void FTKDetectorTool::dumpIDMap()
   }
 
 }
+
+void FTKDetectorTool::dumpModulePositions() {
+   m_log << MSG::INFO << "dumpModulePositions"<< endmsg; 
+   TFile *output=new TFile("FTKmodulePositions.root","recreate");
+   TTree *t=new TTree("modulePositions","modulePositions");
+   int idhash;
+   Float_t phi[2],r[2],z[2];
+   t->Branch("id",&idhash,"id/I");
+   t->Branch("phi",phi,"phi[2]/F");
+   t->Branch("r",r,"r[2]/F");
+   t->Branch("z",z,"z[2]/F");
+   for( InDetDD::SiDetectorElementCollection::const_iterator i=m_PIX_mgr->getDetectorElementBegin(), f=m_PIX_mgr->getDetectorElementEnd() ; i!=f; ++i ) {
+      const InDetDD::SiDetectorElement* sielement( *i );
+      idhash=sielement->identifyHash();
+      r[0]=sielement->rMin();
+      r[1]=sielement->rMax();
+      z[0]=sielement->zMin();
+      z[1]=sielement->zMax();
+      phi[0]=sielement->phiMin();
+      phi[1]=sielement->phiMax();
+      t->Fill();
+   }
+   for( InDetDD::SiDetectorElementCollection::const_iterator i=m_SCT_mgr->getDetectorElementBegin(), f=m_SCT_mgr->getDetectorElementEnd() ; i!=f; ++i ) {
+      const InDetDD::SiDetectorElement* sielement( *i );
+      idhash=sielement->identifyHash();
+      r[0]=sielement->rMin();
+      r[1]=sielement->rMax();
+      z[0]=sielement->zMin();
+      z[1]=sielement->zMax();
+      phi[0]=sielement->phiMin();
+      phi[1]=sielement->phiMax();
+      t->Fill();
+   }
+   t->Write();
+   delete output;
+}
diff --git a/Trigger/TrigFTK/TrigFTKSim/src/FTKDumpCondAlgo.cxx b/Trigger/TrigFTK/TrigFTKSim/src/FTKDumpCondAlgo.cxx
index ae1631bc851..777f864b290 100644
--- a/Trigger/TrigFTK/TrigFTKSim/src/FTKDumpCondAlgo.cxx
+++ b/Trigger/TrigFTK/TrigFTKSim/src/FTKDumpCondAlgo.cxx
@@ -27,6 +27,7 @@ FTKDumpCondAlgo::FTKDumpCondAlgo(const std::string& name, ISvcLocator* pSvcLocat
   m_DumpModuleIDMap(false),
   m_DumpGlobalToLocalMap(false),
   m_DumpIDMap(false),
+  m_DumpModulePositions(false),
   m_IBLMode(0),
   m_ITkMode(false),
   m_fixEndcapL0(false)
@@ -35,6 +36,7 @@ FTKDumpCondAlgo::FTKDumpCondAlgo(const std::string& name, ISvcLocator* pSvcLocat
   declareProperty("DumpModuleIDMap", m_DumpModuleIDMap, "If true dumps the map of the modules in each tower");
   declareProperty("DumpGlobalToLocalMap",m_DumpGlobalToLocalMap, "True if you want to produce the Global-to-Local map");
   declareProperty("DumpIDMap",m_DumpIDMap);
+  declareProperty("DumpModulePositions",m_DumpModulePositions,"To dump the corner positions of the modules");
   declareProperty("IBLMode",m_IBLMode);
   declareProperty("ITkMode",m_ITkMode,"True if you want to assume ITk geometry for FTK plane/tower maps");
   declareProperty("FixEndCapL0",m_fixEndcapL0, "Fix endcap L0 clustering");
@@ -94,6 +96,7 @@ StatusCode FTKDumpCondAlgo::execute() {
 
   if (m_DumpGlobalToLocalMap) {
     m_detectorTool->dumpGlobalToLocalModuleMap(); // Dump the map of the module of each tower
+    m_DumpGlobalToLocalMap=false;
   }
 
   if (m_DumpIDMap) {
@@ -101,6 +104,11 @@ StatusCode FTKDumpCondAlgo::execute() {
     m_DumpIDMap = false; // in case you run on more than 1 event, only dump once
   }
 
+  if(m_DumpModulePositions) {
+     m_detectorTool->dumpModulePositions();
+     m_DumpModulePositions=false;
+  }
+
   return StatusCode::SUCCESS;
 }
 
diff --git a/Trigger/TrigFTK/TrigFTKSim/src/FTKMergerAlgo.cxx b/Trigger/TrigFTK/TrigFTKSim/src/FTKMergerAlgo.cxx
index d94576ec2ca..607b89de53b 100644
--- a/Trigger/TrigFTK/TrigFTKSim/src/FTKMergerAlgo.cxx
+++ b/Trigger/TrigFTK/TrigFTKSim/src/FTKMergerAlgo.cxx
@@ -782,7 +782,12 @@ StatusCode FTKMergerAlgo::initStandaloneTracks()
               if(m_ftktrack_tomerge_tree[ireg][isub]->FindBranch(Form("FTKTracksStream%d.",regNum))){
                  log << MSG::VERBOSE << "Setting branch with region number: " << regNum << " ireg: " << ireg << " isub: " << isub << endmsg;
                  m_ftktrack_tomerge_tree[ireg][isub]->SetBranchAddress(Form("FTKTracksStream%d.",regNum),&m_ftktrack_tomerge_stream[ireg][isub],&m_ftktrack_tomerge_branch[ireg][isub]);
-                 
+                 if( m_MergeRoads) {
+                     m_ftktrack_tomerge_tree[ireg][isub]->SetBranchAddress
+                        (Form("FTKRoadsStream%d.",regNum),
+                         &m_srbanks[ireg][isub],
+                         &m_ftkroad_tomerge_branch[ireg][isub]);
+                 }
               //
               // If not, Try to find branches named after merging has been done
               //
@@ -790,9 +795,21 @@ StatusCode FTKMergerAlgo::initStandaloneTracks()
               } else if (m_ftktrack_tomerge_tree[ireg][isub]->FindBranch(Form("FTKMergedTracksStream%d",regNum))) {
                   log << MSG::VERBOSE << "Setting merged branch with region number: " << regNum << " ireg: " << ireg << " isub: " << isub << endmsg;
                  m_ftktrack_tomerge_tree[ireg][isub]->SetBranchAddress(Form("FTKMergedTracksStream%d",regNum),&m_ftktrack_tomerge_stream[ireg][isub],&m_ftktrack_tomerge_branch[ireg][isub]);
+                  if( m_srbanks[ireg][isub]) {
+                     m_ftktrack_tomerge_tree[ireg][isub]->SetBranchAddress
+                        (Form("FTKMergedRoadsStream%d.",regNum),
+                         &m_srbanks[ireg][isub],
+                         &m_ftkroad_tomerge_branch[ireg][isub]);
+                  }
               } else {
                  log << MSG::DEBUG << "Setting branch with name: FTKMergedTracksStream" << endmsg;
                  m_ftktrack_tomerge_tree[ireg][isub]->SetBranchAddress("FTKMergedTracksStream",&m_ftktrack_tomerge_stream[ireg][isub],&m_ftktrack_tomerge_branch[ireg][isub]);
+                 if( m_srbanks[ireg][isub]) {
+                     m_ftktrack_tomerge_tree[ireg][isub]->SetBranchAddress
+                        ("FTKMergedRoadsStream.",
+                         &m_srbanks[ireg][isub],
+                         &m_ftkroad_tomerge_branch[ireg][isub]);
+                 }
               }
 ///           } // from not used else
            
diff --git a/Trigger/TrigFTK/TrigFTKSim/src/FTK_CompressedAMBank.cxx b/Trigger/TrigFTK/TrigFTKSim/src/FTK_CompressedAMBank.cxx
index 30e81e25e26..d6a4b3bdf70 100644
--- a/Trigger/TrigFTK/TrigFTKSim/src/FTK_CompressedAMBank.cxx
+++ b/Trigger/TrigFTK/TrigFTKSim/src/FTK_CompressedAMBank.cxx
@@ -1419,7 +1419,34 @@ void FTK_CompressedAMBank::importDCpatterns
    for(int ilamb=0;ilamb<nlamb;ilamb++) {
       //
       // sector loop
-      for(unsigned sector=ilamb;sector<sectorPointer.size();sector+=nlamb) {
+      unsigned max_sectorByNlamb=(sectorPointer.size()-1)/nlamb;
+      unsigned top_sectorByNlamb=0;
+      while(top_sectorByNlamb+1 <= max_sectorByNlamb) top_sectorByNlamb=(top_sectorByNlamb+1)*2-1;
+      // here: top_sectorByLamb has all bits set to one and is larger or equal the largest sector/nlamb
+      unsigned leadingBitMask=(top_sectorByNlamb>>1)+1;
+      unsigned sectorByLamb=0;
+      while(true) {
+         //for(unsigned sector=ilamb;sector<sectorPointer.size();sector+=nlamb) {
+         unsigned sector=sectorByLamb*nlamb+ilamb;
+
+         // count sectorByLamb from zero to top_sectorByNlamb
+         // bits are counted in reverse order: MSB first, then next, etc:
+         //  e.g. if top_sectorByNlamb has 12 bit:
+         //   0x000, 0x800, 0x400, 0xc00, 0x200, 0xa00, 0x600, 0xe00, 0x100, ... 0xfff
+         // This randomizes the sector ordering, for better load-balancing of patterns
+         // in the hardware
+         for(unsigned mask=leadingBitMask;mask;mask>>=1) {
+            // count the bit indicated in "mask"
+            sectorByLamb^=mask;
+            // if the it is set, we are done
+            if(sectorByLamb & mask) break;
+            // if the bit is zero, have to count the next bit
+         }
+         if(!sectorByLamb) break; // all bits were counted, stop
+         // when counting in reverse bit order, sectors are not produced in sequence
+         // high (invalid) sector numbers are produced in random order and have
+         // to be skipped
+         if(sector>=sectorPointer.size()) continue; // skip sector numbers outside range
          int nPattern=(sectorPointer[sector].second-
                        sectorPointer[sector].first)/offsetSSID;
          if(!nPattern) continue;
diff --git a/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_entries.cxx b/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_entries.cxx
index e3bb6ec4e8c..01027cba285 100644
--- a/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_entries.cxx
+++ b/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_entries.cxx
@@ -1,3 +1,6 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
 #include "GaudiKernel/DeclareFactoryEntries.h"
 #include "TrigFTKSim/FTKRoadFinderAlgo.h"
 #include "TrigFTKSim/FTKDumpCondAlgo.h"
diff --git a/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_load.cxx b/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_load.cxx
index cc17e7785b5..53f50a648f9 100644
--- a/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_load.cxx
+++ b/Trigger/TrigFTK/TrigFTKSim/src/components/TrigFTKSim_load.cxx
@@ -1,3 +1,6 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
 #include "GaudiKernel/LoadFactoryEntries.h"
 
 LOAD_FACTORY_ENTRIES(TrigFTKSim)
diff --git a/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.cc b/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.cc
index f4288abc6da..11a4319ccab 100644
--- a/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.cc
+++ b/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.cc
@@ -6,6 +6,7 @@
 #include "boost/program_options.hpp"
 #include "boost/filesystem.hpp"
 #include <iomanip>
+#include <cmath>
 #include <TFile.h>
 
 int SIGDIGITS=2;
@@ -55,7 +56,7 @@ int main(int argc, char **argv) {
           Process(ientry);
        }
     } else {
-       // loop over indifidual files (towers spread over files)
+       // loop over individual files (towers spread over files)
        vector<unsigned> processed(ntower);
        processedTower.resize(ntower);
        for (size_t ifile=0; ifile < files.size(); ++ifile) {
@@ -262,9 +263,14 @@ void Init() {
      }
      cout<<"nloop="<<nloop<<"\n"; 
   
+  } else {
+     cout<<"Merged file with "<<ntower<<" towers\n";
   }
   divide = 1./nloop;
-
+  for(int i=0;i<ntower;i++) {
+     nRoad_tow_evt[i].reserve(nloop);
+     nFitI_tow_evt[i].reserve(nloop);
+  }
 }
 
 void Process(unsigned int ientry) {
@@ -277,7 +283,10 @@ void Process(unsigned int ientry) {
      thisevt = stream[itower]->eventNumber();
      break;
   }
-  if (ientry % 50 == 0) cerr << "ientry = " << ientry << " and run = " << thisrun << " and event = " << thisevt << endl;
+  if (ientry % 50 == 0)
+     cerr << "ientry = " << ientry << " and run = " << thisrun
+          << " and event = " << thisevt
+          << endl;
 
   static int first=true;
 
@@ -290,9 +299,9 @@ void Process(unsigned int ientry) {
     outputHistMin->SetBinContent(itower+1,ibin,x);                      \
   if(first) { outputHistAvg->GetYaxis()->SetBinLabel(ibin,name);        \
               outputHistMin->GetYaxis()->SetBinLabel(ibin,name);        \
-              outputHistMax->GetYaxis()->SetBinLabel(ibin,name); }
-
-  vector<float> nRoad_pertow, nFitI_pertow;
+              outputHistMax->GetYaxis()->SetBinLabel(ibin,name);        \
+              cout<<"fill "<<name<<" at "<<ibin<<" val="<<x<<"\n";      \
+  }
 
   for (int itower = 0; itower < ntower; itower++) {
      if(!activeTower[itower]) continue;
@@ -300,26 +309,25 @@ void Process(unsigned int ientry) {
     if (stream[itower] == 0) { cerr << "ERROR: Road stream " << itower << " = 0 " << std::endl; return;}
 
     int ibin=0;
+    int nRoads=stream[itower]->naoGetNroadsAM();
+    if(!nRoads) nRoads=stream[itower]->getNRoads();
     ADD_TO_HIST(1,"nevent");
-    ADD_TO_HIST( stream[itower]->naoGetNroadsAM(),"nRoad");
+    ADD_TO_HIST( nRoads,"nRoad");
     ADD_TO_HIST( trackstream[itower]->getNFits(),"nFit");
     ADD_TO_HIST( trackstream[itower]->getNFitsI(),"nFitI");
     ADD_TO_HIST( trackstream[itower]->getNTracks(),"nTrack");
     ADD_TO_HIST( trackstream[itower]->getNTracks(),"nTrackI");
     
-      nRoad[itower] += stream[itower]->naoGetNroadsAM()*divide;
+      nRoad[itower] += nRoads*divide;
       nFit[itower] += trackstream[itower]->getNFits()*divide;
       nFitI[itower] += trackstream[itower]->getNFitsI()*divide;
       nTrack[itower] += trackstream[itower]->getNTracks()*divide;
       nTrackI[itower] += trackstream[itower]->getNTracksI()*divide;
 
-      nRoad_pertow.push_back(stream[itower]->naoGetNroadsAM());
-      nFitI_pertow.push_back(trackstream[itower]->getNFitsI());
-	    
+      nRoad_tow_evt[itower].push_back(nRoads);
+      nFitI_tow_evt[itower].push_back(trackstream[itower]->getNFitsI());
 
     // for each tower and each entry register the value to extract later the deciles
-    
-
 
       Int_t ntrackBeforeHW = trackstream[itower]->getNTracks() + trackstream[itower]->getNFitsHWRejected();
 
@@ -359,7 +367,7 @@ void Process(unsigned int ientry) {
       for (int il = 0; il < 8; il++) {
          nCluster[il][itower] += stream[itower]->naoGetNclus(il)*divide;
          nCluster_road[il][itower] += stream[itower]->naoGetNclus_road(il)*divide;
-         nSSID[il][itower] += stream[itower]->naoGetNss(il)*divide;
+         //SSID[il][itower] += stream[itower]->naoGetNss(il)*divide;
       }
    ADD_TO_HIST( stream[itower]->naoGetNclus(0),"nCluster0");
    ADD_TO_HIST( stream[itower]->naoGetNclus(1),"nCluster1");
@@ -381,20 +389,17 @@ void Process(unsigned int ientry) {
    ADD_TO_HIST( stream[itower]->naoGetNclus_road(7),"nCluster(road7)");
 
 
-   ADD_TO_HIST( stream[itower]->naoGetNss(0),"nSSID0");
+   /* ADD_TO_HIST( stream[itower]->naoGetNss(0),"nSSID0");
    ADD_TO_HIST( stream[itower]->naoGetNss(1),"nSSID1");
    ADD_TO_HIST( stream[itower]->naoGetNss(2),"nSSID2");
    ADD_TO_HIST( stream[itower]->naoGetNss(3),"nSSID3");
    ADD_TO_HIST( stream[itower]->naoGetNss(4),"nSSID4");
    ADD_TO_HIST( stream[itower]->naoGetNss(5),"nSSID5");
    ADD_TO_HIST( stream[itower]->naoGetNss(6),"nSSID6");
-   ADD_TO_HIST( stream[itower]->naoGetNss(7),"nSSID7");  
+   ADD_TO_HIST( stream[itower]->naoGetNss(7),"nSSID7");  */
 
   }
 
-  nRoadArr.push_back(nRoad_pertow);
-  nFitIArr.push_back(nFitI_pertow);
-
   first=false;
 }
 
@@ -434,52 +439,60 @@ void Terminate() {
   printinfo (nFitMajority, "NFitSSB Majority");
   printinfo (nFitMajoritySCT, "NFitSSB Majority missing SCT");
   printinfo (nFitMajorityPix, "NFitSSB Majority missing Pix");
- int size_nRoad, first_decile_pos_nRoad, last_decile_pos_nRoad, max_quickselect_nRoad, first_decile_nRoad, last_decile_nRoad ;
-  int size_nFitI, first_decile_pos_nFitI, last_decile_pos_nFitI, max_quickselect_nFitI, first_decile_nFitI, last_decile_nFitI ;
-  // definition of the quartiles
-  size_nRoad = nRoadArr.size();
-  first_decile_pos_nRoad = size_nRoad/10;
-  last_decile_pos_nRoad = 9*first_decile_pos_nRoad;
-  max_quickselect_nRoad = size_nRoad - 1;
-  size_nFitI = nFitIArr.size();
-  first_decile_pos_nFitI = size_nFitI/10;
-  last_decile_pos_nFitI = 9*first_decile_pos_nFitI;
-  max_quickselect_nFitI = size_nFitI - 1;
+
   for (int itower = 0; itower < ntower; itower++) {
-    //    if(!processedTower[itower]) continue;
-     
-    // to generalize in case we run on multiple towers
-     vector<int> nRoad_perevt; nRoad_perevt.resize(size_nRoad);
-     vector<int> nFitI_perevt; nRoad_perevt.resize(size_nFitI);
-     AddBreak();
-     for(int i = 0; i < size_nRoad; i++){     
-        nRoad_perevt[i]=nRoadArr[i][0];      
+     if(!processedTower[itower]) continue;
+     int first_decile_nRoad=0;
+     int last_decile_nRoad=0;
+     int first_decile_pos_nRoad=nRoad_tow_evt[itower].size()/10;
+     int last_decile_pos_nRoad=nRoad_tow_evt[itower].size()*9/10;
+     if(nRoad_tow_evt[itower].size()) {
+        vector<float>::iterator nth;
+        nth=nRoad_tow_evt[itower].begin()+first_decile_pos_nRoad;
+        nth_element(nRoad_tow_evt[itower].begin(),nth,
+                    nRoad_tow_evt[itower].end());
+        first_decile_nRoad=(*nth);
+        nth=nRoad_tow_evt[itower].begin()+last_decile_pos_nRoad;
+        nth_element(nRoad_tow_evt[itower].begin(),nth,
+                    nRoad_tow_evt[itower].end());
+        last_decile_nRoad=(*nth);
      }
-     for(int i = 0; i < size_nFitI; i++){     
-        nFitI_perevt[i]=nFitIArr[i][0];     
-     }    
-   
-    first_decile_nRoad = quick_select(nRoad_perevt, 0, max_quickselect_nRoad, first_decile_pos_nRoad);
-    last_decile_nRoad = quick_select(nRoad_perevt, 0, max_quickselect_nRoad, last_decile_pos_nRoad);
-
-    AddBreak();
-  myfile << " nRoad first decile position is " << first_decile_pos_nRoad << " for a value of " << first_decile_nRoad << endl;
-
-  myfile << "nRoad  last decile position is " << last_decile_pos_nRoad << " for a value of " << last_decile_nRoad << endl;  
+     int first_decile_nFitI=0;
+     int last_decile_nFitI=0;
+     int first_decile_pos_nFitI=nFitI_tow_evt[itower].size()/10;
+     int last_decile_pos_nFitI=nFitI_tow_evt[itower].size()*9/10;
+     if(nFitI_tow_evt[itower].size()) {
+        vector<float>::iterator nth;
+        nth=nFitI_tow_evt[itower].begin()+
+           nFitI_tow_evt[itower].size()/10;
+        nth_element(nFitI_tow_evt[itower].begin(),nth,
+                    nFitI_tow_evt[itower].end());
+        first_decile_nFitI=(*nth);
+        nth=nFitI_tow_evt[itower].begin()+
+           nFitI_tow_evt[itower].size()*9/10;
+        nth_element(nFitI_tow_evt[itower].begin(),nth,
+                    nFitI_tow_evt[itower].end());
+        last_decile_nFitI=(*nth);
+     }
+     AddBreak();
+     AddBreak();
+     myfile << " nRoad first decile position is " << first_decile_pos_nRoad
+            << " for a value of " << first_decile_nRoad << endl;
 
+     myfile << "nRoad  last decile position is " << last_decile_pos_nRoad
+            << " for a value of " << last_decile_nRoad << endl;  
     
-    first_decile_nFitI = quick_select(nFitI_perevt, 0, max_quickselect_nFitI, first_decile_pos_nFitI);
-    last_decile_nFitI = quick_select(nFitI_perevt, 0, max_quickselect_nFitI, last_decile_pos_nFitI);
+     myfile << " nFitI first decile position is " << first_decile_pos_nFitI
+            << " for a value of " << first_decile_nFitI << endl;
 
-    myfile << " nFitI first decile position is " << first_decile_pos_nFitI << " for a value of " << first_decile_nFitI << endl;
-
-  myfile << " nFitI last decile position is " << last_decile_pos_nFitI << " for a value of " << last_decile_nFitI << endl;  
+     myfile << " nFitI last decile position is " << last_decile_pos_nFitI
+            << " for a value of " << last_decile_nFitI << endl;  
  
-  //fill out histo with values
-    outputHistFirstDecile->SetBinContent(itower+1, 1, first_decile_nRoad);
-    outputHistLastDecile->SetBinContent(itower+1, 1, last_decile_nRoad);
-    outputHistFirstDecile->SetBinContent(itower+1, 2, first_decile_nFitI);
-    outputHistLastDecile->SetBinContent(itower+1, 2, last_decile_nFitI);
+     //fill out histo with values
+     outputHistFirstDecile->SetBinContent(itower+1, 1, first_decile_nRoad);
+     outputHistLastDecile->SetBinContent(itower+1, 1, last_decile_nRoad);
+     outputHistFirstDecile->SetBinContent(itower+1, 2, first_decile_nFitI);
+     outputHistLastDecile->SetBinContent(itower+1, 2, last_decile_nFitI);
   } 
 
    //myfile << " first decile position is cool " << endl;
@@ -507,38 +520,40 @@ void Terminate() {
   outputRootFile=0;
 }
 
+double roundTo(double x,int precision) {
+   int significantDigit=0;
+   if(x!=0) significantDigit=trunc(log10(fabs(x)));
+   if(precision>=1) {
+      double factor=pow(10.,precision-1-significantDigit);
+      return round(x*factor)/factor;
+   }
+   return x;
+}
 
 void printinfo(float towers[MAXTOWER], TString text) {
 
+   int barrelN=0,endcapN=0;
   float barrelmean(0), endcapmean(0), barrelmax(0), endcapmax(0);
   for (int i = 0; i<ntower; i++) {
+     if(!processedTower[i]) continue;
     if (i < (ntower/4) || i >= 3*(ntower/4.)) { // kludge not always (?) guaranteed to work
       if (towers[i] > endcapmax) endcapmax = towers[i];
-      endcapmean += towers[i]/(ntower/2.);
+      endcapmean += towers[i];
+      endcapN++;
     }
     else {
       if (towers[i] > barrelmax) barrelmax = towers[i];
-      barrelmean += towers[i]/(ntower/2.);
+      barrelmean += towers[i];
+      barrelN++;
     }
   }
+  if(barrelN) barrelmean/=  barrelN;
+  if(endcapN) endcapmean /=  endcapN;
 
-  barrelmean = ([barrelmean](int SIGDIGITS)->double{
-      std::stringstream lStream;
-      lStream << std::setprecision(SIGDIGITS) << barrelmean; return std::stod(lStream.str());
-    })(SIGDIGITS);
-  barrelmax = ([barrelmax](int SIGDIGITS)->double{
-      std::stringstream lStream;
-      lStream << std::setprecision(SIGDIGITS) << barrelmax; return std::stod(lStream.str());
-    })(SIGDIGITS);
-  endcapmean = ([endcapmean](int SIGDIGITS)->double{
-      std::stringstream lStream;
-      lStream << std::setprecision(SIGDIGITS) << endcapmean; return std::stod(lStream.str());
-    })(SIGDIGITS);
-  endcapmax = ([endcapmax](int SIGDIGITS)->double{
-      std::stringstream lStream;
-      lStream << std::setprecision(SIGDIGITS) << endcapmax; return std::stod(lStream.str());
-    })(SIGDIGITS);
-
+  barrelmean = roundTo(barrelmean,SIGDIGITS);
+  barrelmax = roundTo(barrelmax,SIGDIGITS);
+  endcapmean = roundTo(endcapmean,SIGDIGITS);
+  endcapmax = roundTo(endcapmax,SIGDIGITS);
 
   myfile << text << "\t\t" << barrelmean << "\t\t" << barrelmax << "\t\t" << endcapmean << "\t\t" << endcapmax << endl;
   myfileTeX << text << "&" << barrelmean << "&" << barrelmax << "&" << endcapmean << "&" << endcapmax << " \\\\" << endl;
@@ -551,39 +566,3 @@ void AddBreak(int n) {
   }
 }
 
-// some functions used for the calculation of the k^th value of an r+1 long array called input with the method called quick_select.
-//int partition(vector<float> input, int p, int r)
-//int partition(int* input, int p, int r)
-int partition(vector<int> input, int p, int r)
-{
-  int pivot = input[r];
-    
-  while ( p < r )
-    {
-      while ( input[p] < pivot )
-	p++;
-        
-      while ( input[r] > pivot )
-	r--;
-        
-      if ( input[p] == input[r] )
-	p++;
-      else if ( p < r ) {
-	int tmp = input[p];
-	input[p] = input[r];
-	input[r] = tmp;
-      }
-    }
-    
-  return r;
-}
-
-int quick_select(vector<int> input, int p, int r, int k)
-{
-  if ( p == r ) return input[p];
-  int j = partition(input, p, r);
-  int length = j - p + 1;
-  if ( length == k ) return input[j];
-  else if ( k < length ) return quick_select(input, p, j - 1, k);
-  else  return quick_select(input, j + 1, r, k - length);
-}
diff --git a/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.h b/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.h
index 9e62f224106..ef22c9466f4 100644
--- a/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.h
+++ b/Trigger/TrigFTK/TrigFTKSim/standalone/dataflow.h
@@ -33,7 +33,7 @@ float nConn[MAXTOWER], nExtrapAUX[MAXTOWER];
 FTKRoadStream *stream[MAXTOWER];
 FTKTrackStream *trackstream[MAXTOWER];
 
-vector< vector<float>> nRoadArr, nFitIArr;
+vector<float> nRoad_tow_evt[MAXTOWER], nFitI_tow_evt[MAXTOWER];
 
 
 // events to run over
@@ -73,13 +73,3 @@ void Process(unsigned int ientry);
 void Terminate();
 void printinfo(float towers[MAXTOWER], TString text);
 void AddBreak(int n = 1);
-
-/*int quick_select(vector<float> input, int p, int r, int k);
-  int partition(vector<float> input, int p, int r);*/
-
-//int quick_select(int* input, int p, int r, int k);
-
-int quick_select(vector<int> input, int p, int r, int k);
-
-int partition(vector<int> input, int p, int r);
-//int partition(int* input, int p, int r);
-- 
GitLab