diff --git a/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_ElectronicsToolInput.h b/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_ElectronicsToolInput.h
index b818d16c7ea684ce7b4e1d8ee4e2d1dd54ce27a3..62683cca8507063d668ffaac19f30ae3fd56d673 100644
--- a/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_ElectronicsToolInput.h
+++ b/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_ElectronicsToolInput.h
@@ -24,9 +24,9 @@ class MM_ElectronicsToolInput {
 
     ~MM_ElectronicsToolInput() {}
 
-    std::vector<int> NumberOfStripsPos() const { return m_NumberOfStripsPos; }
-    std::vector<std::vector<float>> chipCharge() const { return m_chipCharge; }
-    std::vector<std::vector<float>> chipTime() const { return m_chipTime; }
+   const std::vector<int>& NumberOfStripsPos() const { return m_NumberOfStripsPos; }
+   const std::vector<std::vector<float>>& chipCharge() const { return m_chipCharge; }
+   const std::vector<std::vector<float>>& chipTime() const { return m_chipTime; }
     Identifier digitID() const { return m_digitID; }
     float kineticEnergy() const { return m_kineticEnergy; }
 
diff --git a/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_StripsResponseSimulation.h b/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_StripsResponseSimulation.h
index b879888dabe75e8682b830cdee757ff36533ab43..2ed48255b45b5c69f12b6fed4a51d221e8c11495 100644
--- a/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_StripsResponseSimulation.h
+++ b/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/MM_StripsResponseSimulation.h
@@ -181,5 +181,13 @@ private:
   //Declaring private message stream member.
   mutable Athena::MsgStreamMember m_msg = Athena::MsgStreamMember("MMStripResponseSimulation");
 
+  // seperate random number generation for performance monitoring
+  float getTransversDiffusion(float posY);
+  float getLongitudinalDiffusion(float posY);
+  float getEffectiveCharge();
+  float getPathLengthTraveled();
+
+
+
 };
 #endif
diff --git a/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/VMM_Shaper.h b/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/VMM_Shaper.h
index 4def653f55ca39a53c6d4ff82f3b8fe8a1e38a9f..8b4a6672c970cd217a60e7c777af46e2e8acea9b 100644
--- a/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/VMM_Shaper.h
+++ b/MuonSpectrometer/MuonDigitization/MM_Digitization/MM_Digitization/VMM_Shaper.h
@@ -37,8 +37,9 @@ class VMM_Shaper{
      double vmmResponse(const std::vector<float> &effectiveCharge, const std::vector<float> &electronsTime, double time) const;
      double findPeak(const std::vector<float> &effectiveCharge, const std::vector<float> &electronsTime, const double electronicsThreshold) const;
      bool aboveThresholdSimple(const std::vector<float> &effectiveCharge, const std::vector<float> &electronsTime, const double electronicsThreshold) const;
-
-
+     double m_pole0_ns;
+     double m_re_pole1_ns; 
+     double m_im_pole1_ns;
 };
 
 #endif  // MM_DIGITIZATION_VMM_SHAPER_H
diff --git a/MuonSpectrometer/MuonDigitization/MM_Digitization/src/MM_StripsResponseSimulation.cxx b/MuonSpectrometer/MuonDigitization/MM_Digitization/src/MM_StripsResponseSimulation.cxx
index 2e71f603fb9fc3bc183e9f498273aed4d4835e63..18216e7d3c9db0b79416d9b7b12e8544da4b8b83 100644
--- a/MuonSpectrometer/MuonDigitization/MM_Digitization/src/MM_StripsResponseSimulation.cxx
+++ b/MuonSpectrometer/MuonDigitization/MM_Digitization/src/MM_StripsResponseSimulation.cxx
@@ -114,7 +114,11 @@ void MM_StripsResponseSimulation::initFunctions()
 
 	m_longitudinalDiffusionFunction = new TF1("longdiff","gaus", -5., 5.);
 
-	m_transverseDiffusionFunction = new TF1("transdiff", "1.*TMath::Exp(-TMath::Power(x,2.)/(2.*[0]*[0])) + 0.001*TMath::Exp(-TMath::Power(x,2)/(2.*[1]*[1]))", -1., 1.);
+	//m_transverseDiffusionFunction = new TF1("transdiff", "1.*TMath::Exp(-TMath::Power(x,2.)/(2.*[0]*[0])) + 0.001*TMath::Exp(-TMath::Power(x,2)/(2.*[1]*[1]))", -1., 1.);
+	m_transverseDiffusionFunction = new TF1("transdiff", "gaus(0) + gaus(3)", -1., 1.);
+  m_transverseDiffusionFunction->SetParameters(1.,0.,1.,0.001,0.,1.);
+	//m_transverseDiffusionFunction = new TF1("transdiff", "gaus", -1., 1.);
+  //m_transverseDiffusionFunction->SetParameters(1.,0.,1.);
 
 	m_random = new TRandom3(0);
 
@@ -202,7 +206,7 @@ void MM_StripsResponseSimulation::whichStrips( const float & hitx,
 	ATH_MSG_DEBUG("LorentzAngle vs theta: " <<lorentzAngle <<" " <<theta);
     ATH_MSG_DEBUG("Function pointer points to " << m_interactionDensityFunction);
 
-	float pathLengthTraveled = ( 1. / m_interactionDensityFunction->GetRandom() ) * -1. * std::log( m_random->Uniform() );
+	float pathLengthTraveled = getPathLengthTraveled(); 
 
 	float pathLength  = m_driftGapWidth/std::cos(theta); // Increasing path length based on XZ angle
 	pathLength       /= std::cos(alpha);                 // Further increasing path length for YZ angle
@@ -231,19 +235,19 @@ void MM_StripsResponseSimulation::whichStrips( const float & hitx,
 
 		for (auto& Electron : IonizationCluster.getElectrons()){
 
-			m_longitudinalDiffusionFunction->SetParameters(1.0, 0., initialPosition.Y()*m_longitudinalDiffusionSigma);
+		//	m_longitudinalDiffusionFunction->SetParameters(1.0, 0., initialPosition.Y()*m_longitudinalDiffusionSigma);
 
-			if ( m_longitudinalDiffusionSigma == 0 || m_transverseDiffusionSigma == 0) {
+		//	if ( m_longitudinalDiffusionSigma == 0 || m_transverseDiffusionSigma == 0) {
 
-				m_transverseDiffusionFunction->SetParameters( initialPosition.Y()*m_transverseDiffusionSigma , 0.0);
+		//		m_transverseDiffusionFunction->SetParameters( initialPosition.Y()*m_transverseDiffusionSigma , 0.0);
 
-			} else {
+		//	} else {
 
-				m_transverseDiffusionFunction->SetParameters( initialPosition.Y()*m_transverseDiffusionSigma , 1.0);
+		//		m_transverseDiffusionFunction->SetParameters( initialPosition.Y()*m_transverseDiffusionSigma , 1.0);
 
-			}
+		//	}
 
-			Electron->setOffsetPosition(m_transverseDiffusionFunction->GetRandom(), m_longitudinalDiffusionFunction->GetRandom());
+			Electron->setOffsetPosition(getTransversDiffusion(initialPosition.Y()) , getLongitudinalDiffusion(initialPosition.Y()) );
 
 		}
 
@@ -254,7 +258,8 @@ void MM_StripsResponseSimulation::whichStrips( const float & hitx,
 
 		for (auto& Electron : IonizationCluster.getElectrons()){
 
-			float effectiveCharge = m_polyaFunction->GetRandom();
+			//float effectiveCharge = m_polyaFunction->GetRandom();
+			float effectiveCharge = getEffectiveCharge();
 
 			Electron->setCharge( effectiveCharge );
 
@@ -275,7 +280,7 @@ void MM_StripsResponseSimulation::whichStrips( const float & hitx,
 		//---
 		m_IonizationClusters.push_back(IonizationCluster);
 
-		pathLengthTraveled +=  (1. / m_interactionDensityFunction->GetRandom() ) * -1. * std::log( m_random->Uniform() );
+		pathLengthTraveled +=  getPathLengthTraveled();
 
 		ATH_MSG_DEBUG("Path length traveled: " << pathLengthTraveled);
 
@@ -332,6 +337,33 @@ void MM_StripsResponseSimulation::whichStrips( const float & hitx,
 
 } // end of whichStrips()
 
+float MM_StripsResponseSimulation::getTransversDiffusion(float posY){
+  if ( m_longitudinalDiffusionSigma == 0 || m_transverseDiffusionSigma == 0) {
+
+	  m_transverseDiffusionFunction->SetParameter(2, posY*m_transverseDiffusionSigma);
+	  m_transverseDiffusionFunction->SetParameter(5, 0.0);
+
+	} else {
+	  m_transverseDiffusionFunction->SetParameter(2, posY*m_transverseDiffusionSigma);
+    m_transverseDiffusionFunction->SetParameter(5, 1.0);
+	}
+  return m_transverseDiffusionFunction->GetRandom(); 
+  }
+
+float MM_StripsResponseSimulation::getLongitudinalDiffusion(float posY){
+  m_longitudinalDiffusionFunction->SetParameters(1.0, 0., posY*m_longitudinalDiffusionSigma);
+  return m_longitudinalDiffusionFunction->GetRandom();
+}
+
+float  MM_StripsResponseSimulation::getEffectiveCharge(){return m_polyaFunction->GetRandom();}
+
+float MM_StripsResponseSimulation::getPathLengthTraveled(){
+	return  ( 1. / m_interactionDensityFunction->GetRandom() ) * -1. * log( m_random->Uniform() );
+}
+
+
+
+
 /*******************************************************************************/
 MM_StripsResponseSimulation::~MM_StripsResponseSimulation()
 {
diff --git a/MuonSpectrometer/MuonDigitization/MM_Digitization/src/VMM_Shaper.cxx b/MuonSpectrometer/MuonDigitization/MM_Digitization/src/VMM_Shaper.cxx
index 39d0763c2ab71b15c51ad1432226b15fc35274cc..788f87ecec6b6e75b8c89ea2cac3c4f98dcf37a4 100644
--- a/MuonSpectrometer/MuonDigitization/MM_Digitization/src/VMM_Shaper.cxx
+++ b/MuonSpectrometer/MuonDigitization/MM_Digitization/src/VMM_Shaper.cxx
@@ -42,16 +42,20 @@ void VMM_Shaper::initialize() {
     
     // preCalculate factor to avoid recalculating for each electron
     m_preCalculationVMMShaper = chargeScaleFactor*m_peakTimeChargeScaling*std::pow(m_a, 3)*m_pole0*m_pole1_square;
+
+    m_pole0_ns = m_pole0*(10^-9);
+    m_re_pole1_ns = m_re_pole1*(10^-9);
+    m_im_pole1_ns = m_im_pole1*(10^-9);
 }
 
 double VMM_Shaper::vmmResponse(const std::vector<float> &effectiveCharge, const std::vector<float> &electronsTime, double time) const{
     double response = 0;
     for (unsigned int i_electron = 0; i_electron < effectiveCharge.size(); i_electron++) {
             if (time < electronsTime.at(i_electron)) continue;
-            double t = (time-electronsTime.at(i_electron))*(10^-9);
+            double t = (time-electronsTime.at(i_electron));
             // now follows the vmm shaper response function provided by G. Iakovidis
             // It is described in section 7.1.3 of https://cds.cern.ch/record/1955475
-            double st = effectiveCharge.at(i_electron)*m_preCalculationVMMShaper*((K0*std::exp(-t*m_pole0))+(2.*m_k1_abs*std::exp(-t*m_re_pole1)*std::cos(-t*m_im_pole1+m_argK1)));
+            double st = effectiveCharge.at(i_electron)*m_preCalculationVMMShaper*((K0*std::exp(-t*m_pole0_ns))+(2.*m_k1_abs*std::exp(-t*m_re_pole1_ns)*std::cos(-t*m_im_pole1_ns+m_argK1)));
             response += st;
     }
     return response;
@@ -74,13 +78,29 @@ void VMM_Shaper::vmmThresholdResponse(const std::vector<float> &effectiveCharge,
     double startTime = m_lowerTimeWindow;
     double minElectronTime = *std::min_element(electronsTime.begin(), electronsTime.end());
     if (startTime < minElectronTime) startTime = minElectronTime;  // if smallest strip times are higher then the lower time window, just start the loop from the smallest electron time
-
+    
     double tmpTimeAtThreshold = -9999;
-    for (double time = startTime; time < m_upperTimeWindow; time += m_timeStep) {
-        if (vmmResponse(effectiveCharge, electronsTime, time) >= electronicsThreshold) {
-            tmpTimeAtThreshold = time;
-            break;
-        }
+    
+    for (double time = startTime; time < minElectronTime + 0.9*m_peakTime; time += 10*m_timeStep) { // quick search till the first possible peak
+      if(vmmResponse(effectiveCharge, electronsTime, time) <= electronicsThreshold ) continue;
+      for(double fineTime = time; fineTime >= time - 10*m_timeStep; fineTime -= m_timeStep) { // since value above threshold was found, loop back in time to find the crossing with the timeStep precission
+          if(vmmResponse(effectiveCharge, electronsTime, fineTime) >= electronicsThreshold) continue;
+              tmpTimeAtThreshold = fineTime + 0.5*m_timeStep; //  get time between time above and time below threshold 
+              break;
+          }
+      break;
+    } 
+    
+    if(tmpTimeAtThreshold == -9999) {  // threshold crossing not yet found 
+        // check if first possible peak was before start time
+        double tmpStartTime = std::max(minElectronTime + 0.9*m_peakTime, startTime); 
+        for (double time = tmpStartTime; time < m_upperTimeWindow; time += m_timeStep) {
+          if (vmmResponse(effectiveCharge, electronsTime, time) >= electronicsThreshold) {
+              tmpTimeAtThreshold = time;
+              break;
+          }
+       } 
+    
     }
 
     if (tmpTimeAtThreshold == -9999) return;
@@ -97,44 +117,58 @@ double VMM_Shaper::findPeak(const std::vector<float> &effectiveCharge, const std
     if(effectiveCharge.size()==0) return -9999; // protect min_element
     double startTime = m_lowerTimeWindow;
     double minElectronTime = *std::min_element(electronsTime.begin(), electronsTime.end());
+
+    minElectronTime += 0.8*m_peakTime;  // only start looking for the peak close to the first possible peak
     if(startTime < minElectronTime) startTime = minElectronTime; // if smallest strip times are higher then the lower time window, just start the loop from the smallest electron time
 
     double oldResponse = 0;
-    double oldDerivative = 0 , currentDerivative = 0;
+    //double currentDerivative = 0;
 
-    for (double time = startTime; time < m_upperTimeWindow; time += m_timeStep) {
+    double timeStepScaleFactor = 5.0;
 
-        double response = vmmResponse(effectiveCharge, electronsTime, time);
+    for (double time = startTime; time < m_upperTimeWindow; time += m_timeStep*timeStepScaleFactor) {
 
-        oldDerivative = currentDerivative;
-        currentDerivative = (response-oldResponse) * m_inverseTimeStep;
-        //  check if sign of derivative has not changed ==> no peak;  or if response is below threshold
-        if (oldDerivative*currentDerivative >= 0 || oldResponse < electronicsThreshold) {oldResponse = response; continue;}
+        double response = vmmResponse(effectiveCharge, electronsTime, time);
+        if(oldResponse < response){oldResponse=response; continue;}
+        oldResponse = response;
 
-        // from here one its assumed that a peak above threshold was found
+        int searchWindow = 5;
 
-        //  check if the derivative is monoton falling within the given window of 5 bins
-        bool checkDerivative = true;
-        double tmp_checkOldDerivative = 0, tmp_checkCurrentDerivative = 0;
-        double tmp_checkOldResponse = 0;
+        std::vector<double> tmpTime, tmpResponse;
 
-        int searchWindow = 5;
+        tmpTime.reserve(2*timeStepScaleFactor);
+        tmpResponse.reserve(2*timeStepScaleFactor);
 
-        for (int i_timeOfPeak = -searchWindow; i_timeOfPeak <= searchWindow; i_timeOfPeak ++) {
-           double response = vmmResponse(effectiveCharge, electronsTime, time + i_timeOfPeak * m_timeStep);
 
-           tmp_checkOldDerivative = tmp_checkCurrentDerivative;
-           tmp_checkCurrentDerivative = (response - tmp_checkOldResponse) * m_inverseTimeStep;
-           tmp_checkOldResponse = response;
+        for(double fineTime = (time-1.5*m_timeStep*timeStepScaleFactor); fineTime < time+0.5*m_timeStep*timeStepScaleFactor; fineTime += m_timeStep) {
+          tmpTime.push_back(fineTime);
+          tmpResponse.push_back(vmmResponse(effectiveCharge,electronsTime,fineTime));     
+        }
 
-           if (i_timeOfPeak >= -searchWindow + 2  // needs two iterations to fill the variables
-                && tmp_checkOldDerivative < tmp_checkCurrentDerivative) {  // derivative is not falling monothonic
-               checkDerivative = false;
-               break;
+        int nBins = tmpTime.size();
+
+        for(int i_time = 1; i_time < nBins-1;i_time++){
+            if(tmpResponse.at(i_time)<tmpResponse.at(i_time+1)) continue;
+
+            if(tmpResponse.at(i_time) < electronicsThreshold) break; 
+            
+            bool checkTimeWindow = false;
+            for(int i_timeOfPeak = i_time - searchWindow + 1; i_timeOfPeak <= i_time + searchWindow; i_timeOfPeak++) {
+              if(i_timeOfPeak < 1 || i_timeOfPeak == nBins - 1) continue;
+              
+              double oldDerivative = (tmpResponse.at(i_time) - tmpResponse.at(i_time-1));
+              double newDerivative = (tmpResponse.at(i_time+1) - tmpResponse.at(i_time));
+              if (newDerivative > oldDerivative){
+                checkTimeWindow = false;
+                break; 
+              } else {
+                checkTimeWindow = true;
+              }
+            
            }
+           if(checkTimeWindow) return tmpTime.at(i_time);
+
         }
-        if (!checkDerivative) continue;
-        return time - m_timeStep;
     }
     return -9999;  // no peak found
 }