diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude.py b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude.py
index 2d1cf6aa835503616f2881c67a1b3eeec2eb0234..d83a177b86b6ba833016980f76749750b6675c30 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude.py
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude.py
@@ -2,3 +2,19 @@ from G4AtlasApps.SimFlags import simFlags
 simFlags.OptionalUserActionList.addAction('G4UA::FastCaloSimParamActionTool',['Event','Run','Step'])
 simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"shift_lar_subhit",True)
 simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"shorten_lar_step",True)
+# optimised merging scheme parameters
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxEtaPS",1)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxPhiPS",5)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxrPS",0)
+
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxEtaEM1",1)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxPhiEM1",5)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxrEM1",15)
+
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxEtaEM2",1)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxPhiEM2",5)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxrEM2",60)
+
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxEtaEM3",1)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxPhiEM3",5)
+simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxrEM3",8)
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude_1mm.py b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude_1mm.py
index 208baab991cee88d38f273a0ca278d65bc2160f5..80367e58f00397c97c3c014b1c559a9aa5fdc0fb 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude_1mm.py
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_FastCaloSimParametrization_SimPreInclude_1mm.py
@@ -3,3 +3,4 @@ simFlags.OptionalUserActionList.addAction('G4UA::FastCaloSimParamActionTool',['E
 simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"shift_lar_subhit",True)
 simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"shorten_lar_step",True)
 simFlags.UserActionConfig.addConfig('G4UA::FastCaloSimParamActionTool',"maxRadiusLAr",1)
+# optimised merging scheme parameters are not required for 1mm merging
diff --git a/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/ISF_Geant4UserActions/FastCaloSimParamAction.h b/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/ISF_Geant4UserActions/FastCaloSimParamAction.h
index 24d33e57603b138081300078be98dbf8191f3306..591684b64162da76b10cd5989bfa1b336a3bea37 100755
--- a/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/ISF_Geant4UserActions/FastCaloSimParamAction.h
+++ b/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/ISF_Geant4UserActions/FastCaloSimParamAction.h
@@ -99,13 +99,30 @@ namespace G4UA{
       DoubleProperty            m_maxRadiusHEC=100.;             //!< property, see @link LArG4GenShowerLib::LArG4GenShowerLib @endlink
       DoubleProperty            m_maxRadiusFCAL=100.;            //!< property, see @link LArG4GenShowerLib::LArG4GenShowerLib @endlink
       DoubleProperty            m_maxRadiusTile=100.;            //!< property, see @link LArG4GenShowerLib::LArG4GenShowerLib @endlink
- 
+
       DoubleProperty            m_maxTime=25.;
       DoubleProperty            m_maxTimeLAr=25.;
       DoubleProperty            m_maxTimeHEC=25.;
       DoubleProperty            m_maxTimeFCAL=25.;
       DoubleProperty            m_maxTimeTile=25.;
 
+      // Optimised merging scheme
+      DoubleProperty            m_maxEtaPS=1.;
+      DoubleProperty            m_maxPhiPS=5.;
+      DoubleProperty            m_maxrPS=0.;
+
+      DoubleProperty            m_maxEtaEM1=1.;
+      DoubleProperty            m_maxPhiEM1=5.;
+      DoubleProperty            m_maxrEM1=15.;
+
+      DoubleProperty            m_maxEtaEM2=1.;
+      DoubleProperty            m_maxPhiEM2=5.;
+      DoubleProperty            m_maxrEM2=60.;
+
+      DoubleProperty            m_maxEtaEM3=1.;
+      DoubleProperty            m_maxPhiEM3=5.;
+      DoubleProperty            m_maxrEM3=8.;
+
     };
 
     FastCaloSimParamAction(const Config& config);
diff --git a/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamAction.cxx b/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamAction.cxx
index 91c3398b13f20ef0ec3484a67c2f7a712cfe1858..2188be3d9a4da09f3216579e15b0bea1149322f0 100755
--- a/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamAction.cxx
+++ b/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamAction.cxx
@@ -166,7 +166,7 @@ namespace G4UA{
       delete it.second;
     } // Vector of IDs in the map
     m_hit_map.clear();
-  
+
     if (m_eventSteps->size()==0) return; //don't need to play with it
     G4cout << "FastCaloSimParamAction::EndOfEventAction: After initial cleanup, N=" << m_eventSteps->size() << G4endl;
 
@@ -634,7 +634,7 @@ namespace G4UA{
                 //std::cout <<"Something wrong in identifier: One tile pmt: "<<micHit.pmt_up<<" "<<micHit.pmt_down<<std::endl;
                 //std::cout <<"E up: "<<micHit.e_up<<" E down: "<<micHit.e_down<<" T up: "<<micHit.time_up<<" T down: "<<micHit.time_down<<std::endl;
               }
-            update_map(pos, micHit.pmt_up, micHit.e_up, micHit.time_up, true,1); 
+            update_map(pos, micHit.pmt_up, micHit.e_up, micHit.time_up, true,1);
             // ISF_FCS_Parametrization::FCS_StepInfo* theInfo_Tile_up = new ISF_FCS_Parametrization::FCS_StepInfo(pos, micHit.pmt_up, micHit.e_up, micHit.time_up, true,1);
             //Commented out version needs ISF_Event which is not yet in SVN..
             //      ISF_FCS_Parametrization::FCS_StepInfo* theInfo_Tile_up = new ISF_FCS_Parametrization::FCS_StepInfo(pos, micHit.pmt_up, micHit.e_up, micHit.time_up, true,1,StepLength);
@@ -676,7 +676,7 @@ void FastCaloSimParamAction::update_map(const CLHEP::Hep3Vector & l_vec, const I
   if (map_item==m_hit_map.end()){
     m_hit_map[l_cell] = new std::vector< ISF_FCS_Parametrization::FCS_StepInfo* >;
     m_hit_map[l_cell]->push_back( new ISF_FCS_Parametrization::FCS_StepInfo( l_vec , l_cell , l_energy , l_time , l_valid , l_detector ) );
-  } 
+  }
   else {
 
     // Get the appropriate merging limits
@@ -697,41 +697,54 @@ void FastCaloSimParamAction::update_map(const CLHEP::Hep3Vector & l_vec, const I
     bool match = false;
     for (auto map_it : * map_item->second){
       // Time check is straightforward
-      if ( fabs(map_it->time()-l_time)>=tsame ) continue;
+      double delta_t = fabs(map_it->time()-l_time);
+      if ( delta_t >= tsame ) continue;
+
       // Distance check is less straightforward
       CLHEP::Hep3Vector a_diff = l_vec - map_it->position();
       double a_inv_length = 1./a_diff.mag();
-      if (layer==CaloCell_ID::PreSamplerB || layer==CaloCell_ID::PreSamplerE){
-        // 5mm in eta, 5mm in phi, no cut in r
-        if (fabs(sin(l_vec.phi()-map_it->position().phi())*a_diff.mag())>=5) continue; // phi
-        if (fabs(sin(l_vec.theta()-map_it->position().theta())*a_diff.mag())>=5) continue; // eta
-      } else if (layer==CaloCell_ID::EMB1 || layer==CaloCell_ID::EME1){
-        // 1mm in eta, 5mm in phi, 15mm in r
-        if ( a_diff.dot( l_vec ) * a_inv_length >= 15 ) continue; // r
-        if (fabs(sin(l_vec.phi()-map_it->position().phi())*a_diff.mag())>=5) continue; // phi
-        if (fabs(sin(l_vec.theta()-map_it->position().theta())*a_diff.mag())>=1) continue; // eta
-      } else if (layer==CaloCell_ID::EMB2 || layer==CaloCell_ID::EME2){
-        // 5mm in eta, 5mm in phi, 60mm in r
-        if ( a_diff.dot( l_vec ) * a_inv_length >= 60 ) continue; // r
-        if (fabs(sin(l_vec.phi()-map_it->position().phi())*a_diff.mag())>=5) continue; // phi
-        if (fabs(sin(l_vec.theta()-map_it->position().theta())*a_diff.mag())>=5) continue; // eta
-      } else if (layer==CaloCell_ID::EMB3 || layer==CaloCell_ID::EMB3){
-        // 5mm in eta, 5mm in phi, 8mm in r
-        if ( a_diff.dot( l_vec ) * a_inv_length >= 8 ) continue; // r
-        if (fabs(sin(l_vec.phi()-map_it->position().phi())*a_diff.mag())>=5) continue; // phi
-        if (fabs(sin(l_vec.theta()-map_it->position().theta())*a_diff.mag())>=5) continue; // eta
-      } else if (layer >= CaloCell_ID::PreSamplerB && layer <= CaloCell_ID::EME3){
-        if ( map_it->position().diff2( l_vec ) >= m_config.m_maxRadiusLAr ) continue;
+      double delta_phi = fabs(sin(l_vec.phi()-map_it->position().phi())*a_diff.mag());
+      double delta_eta = fabs(sin(l_vec.theta()-map_it->position().theta())*a_diff.mag());
+      double delta_r = fabs(a_diff.dot( l_vec ) * a_inv_length);
+      double hit_diff2 = map_it->position().diff2( l_vec );
+
+      // Overall merging scheme
+      if (layer >= CaloCell_ID::PreSamplerB && layer <= CaloCell_ID::EME3){
+        // Customized merging scheme for LAr barrel and endcap, use only if we're not changing maxRadiusLAr value
+        if(m_config.m_maxRadiusLAr == 25){
+          if (layer==CaloCell_ID::PreSamplerB || layer==CaloCell_ID::PreSamplerE){
+            // PS default is 1mm in eta, 5mm in phi, no cut in r
+            if (delta_r >= m_config.m_maxrPS) continue;
+            if (delta_eta >= m_config.m_maxEtaPS) continue;
+            if (delta_phi >= m_config.m_maxPhiPS) continue;
+          } else if (layer==CaloCell_ID::EMB1 || layer==CaloCell_ID::EME1){
+            // EM1 default is 1mm in eta, 5mm in phi, 15mm in r
+            if (delta_r >= m_config.m_maxrEM1) continue;
+            if (delta_eta >= m_config.m_maxEtaEM1) continue;
+            if (delta_phi >= m_config.m_maxPhiEM1) continue;
+          } else if (layer==CaloCell_ID::EMB2 || layer==CaloCell_ID::EME2){
+            // EM2 default is 1mm in eta, 5mm in phi, 60mm in r
+            if (delta_r >= m_config.m_maxrEM2) continue;
+            if (delta_eta >= m_config.m_maxEtaEM2) continue;
+            if (delta_phi >= m_config.m_maxPhiEM2) continue;
+          } else if (layer==CaloCell_ID::EMB3 || layer==CaloCell_ID::EME3){
+            // EM3 default is 1mm in eta, 5mm in phi, 8mm in r
+            if (delta_r >= m_config.m_maxrEM3) continue;
+            if (delta_eta >= m_config.m_maxEtaEM3) continue;
+            if (delta_phi >= m_config.m_maxPhiEM3) continue;
+          }
+        } else{ // Merging schemes done by changing maxRadiusLAr
+            if ( hit_diff2 >= m_config.m_maxRadiusLAr ) continue;
+        }
       } else if (layer >= CaloCell_ID::HEC0  && layer <= CaloCell_ID::HEC3){
-        if ( map_it->position().diff2( l_vec ) >= m_config.m_maxRadiusHEC ) continue;
+        if ( hit_diff2 >= m_config.m_maxRadiusHEC ) continue;
       } else if (layer >= CaloCell_ID::TileBar0 && layer <= CaloCell_ID::TileExt2){
-        if ( map_it->position().diff2( l_vec ) >= m_config.m_maxRadiusTile ) continue;
+        if ( hit_diff2 >= m_config.m_maxRadiusTile ) continue;
       } else if (layer >=CaloCell_ID::FCAL0 && layer <= CaloCell_ID::FCAL2){
-        if ( map_it->position().diff2( l_vec ) >= m_config.m_maxRadiusFCAL ) continue;
+        if ( hit_diff2 >= m_config.m_maxRadiusFCAL ) continue;
       } else {
-        if ( map_it->position().diff2( l_vec ) >= m_config.m_maxRadius ) continue;
+        if ( hit_diff2 >= m_config.m_maxRadius ) continue;
       }
-
       // Found a match.  Make a temporary that will be deleted!
       ISF_FCS_Parametrization::FCS_StepInfo my_info( l_vec , l_cell , l_energy , l_time , l_valid , l_detector );
       *map_it += my_info;
diff --git a/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamActionTool.cxx b/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamActionTool.cxx
index db4a0f028794dd46b707ce2beab41f3d5c845b33..f3dc27041714763ea5a125749fd70301f9326ea2 100644
--- a/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamActionTool.cxx
+++ b/Simulation/ISF/ISF_Geant4/ISF_Geant4UserActions/src/FastCaloSimParamActionTool.cxx
@@ -42,6 +42,22 @@ namespace G4UA{
     declareProperty("maxTimeFCAL",m_config.m_maxTimeFCAL, "");
     declareProperty("maxTimeTile",m_config.m_maxTimeTile, "");
 
+    declareProperty("maxEtaPS", m_config.m_maxEtaPS, "");
+    declareProperty("maxPhiPS", m_config.m_maxPhiPS, "");
+    declareProperty("maxrPS", m_config.m_maxrPS, "");
+
+    declareProperty("maxEtaEM1", m_config.m_maxEtaEM1, "");
+    declareProperty("maxPhiEM1", m_config.m_maxPhiEM1, "");
+    declareProperty("maxrEM1", m_config.m_maxrEM1, "");
+
+    declareProperty("maxEtaEM2", m_config.m_maxEtaEM2, "");
+    declareProperty("maxPhiEM2", m_config.m_maxPhiEM2, "");
+    declareProperty("maxrEM2", m_config.m_maxrEM2, "");
+
+    declareProperty("maxEtaEM3", m_config.m_maxEtaEM3, "");
+    declareProperty("maxPhiEM3", m_config.m_maxPhiEM3, "");
+    declareProperty("maxrEM3", m_config.m_maxrEM3, "");
+
     declareProperty("EMECPosIWCalculator", m_emepiwcalc);
     declareProperty("EMECNegIWCalculator", m_emeniwcalc);
     declareProperty("EMECPosOWCalculator", m_emepowcalc);
@@ -55,7 +71,7 @@ namespace G4UA{
     declareProperty("EMBPSCalculator",m_pscalc);
     declareProperty("EMECPSCalculator", m_emepscalc);
     declareProperty("TileCalculator", m_tileCalculator);
-    }
+  }
 
   StatusCode FastCaloSimParamActionTool::initialize()
   {