diff --git a/algo/kf/core/KfTrackKalmanFilter.cxx b/algo/kf/core/KfTrackKalmanFilter.cxx
index f9bdb65f257a85338e1a043eb0c2b88ec3e73a62..7230a22f136d33fea3e1a0945b7d2024cb3a54a2 100644
--- a/algo/kf/core/KfTrackKalmanFilter.cxx
+++ b/algo/kf/core/KfTrackKalmanFilter.cxx
@@ -4,6 +4,7 @@
 
 #include "KfTrackKalmanFilter.h"
 
+#include "AlgoFairloggerCompat.h"
 #include "KfMeasurementU.h"
 #include "KfMeasurementXy.h"
 
@@ -46,7 +47,7 @@ namespace cbm::algo::kf
 
     wi = kf::utils::iif(m.Du2() > DataT(0.), wi, DataT(0.));
 
-    fTr.ChiSq() += m.Ndf() * zeta * zeta * wi;
+    fTr.ChiSq() += zeta * zeta * wi;
     fTr.Ndf() += kf::utils::iif(fMask, m.Ndf(), DataT(0.));
 
     K1 = F1 * wi;
@@ -977,29 +978,37 @@ namespace cbm::algo::kf
 
 
   template<typename DataT>
-  void TrackKalmanFilter<DataT>::MultipleScattering(DataT radThick, DataT qp0)
+  void TrackKalmanFilter<DataT>::MultipleScattering(DataT radThick, DataT tx, DataT ty, DataT qp)
   {
-    cnst kONE = 1.;
+    // 1974 - Highland (PDG) correction for multiple scattering
+    // In the formula there is a replacement:
+    // log(X/X0) == log( RadThick * sqrt(1+h) ) -> log(RadThick) + 0.5 * log(1+h);
+    // then we use an approximation:
+    // log(1+h) -> h - h^2/2 + h^3/3 - h^4/4
 
-    DataT tx    = fTr.Tx();
-    DataT ty    = fTr.Ty();
     DataT txtx  = tx * tx;
     DataT tyty  = ty * ty;
-    DataT txtx1 = txtx + kONE;
+    DataT txtx1 = DataT(1.) + txtx;
+    DataT tyty1 = DataT(1.) + tyty;
     DataT h     = txtx + tyty;
     DataT t     = sqrt(txtx1 + tyty);
     DataT h2    = h * h;
-    DataT qp0t  = qp0 * t;
+    DataT qpt   = qp * t;
 
-    cnst c1 = 0.0136f, c2 = c1 * 0.038f, c3 = c2 * 0.5f, c4 = -c3 / 2.0f, c5 = c3 / 3.0f, c6 = -c3 / 4.0f;
+    DataT lg = DataT(.0136) * (DataT(1.) + DataT(0.038) * log(radThick * t));
+    lg       = kf::utils::iif(lg > DataT(0.), lg, DataT(0.));
 
-    DataT s0 = (c1 + c2 * log(radThick) + c3 * h + h2 * (c4 + c5 * h + c6 * h2)) * qp0t;
+    DataT s0 = lg * qp * t;
+    DataT a  = (DataT(1.) + fMass2 * qp * qp) * s0 * s0 * t * radThick;
+
+    //cnst c1 = 0.0136f, c2 = c1 * 0.038f, c3 = c2 * 0.5f, c4 = -c3 / 2.0f, c5 = c3 / 3.0f, c6 = -c3 / 4.0f;
+    //DataT s0 = (c1 + c2 * log(radThick) + c3 * h + h2 * (c4 + c5 * h + c6 * h2)) * qp0t;
     //DataT a = ( (kONE+mass2*qp0*qp0t)*radThick*s0*s0 );
-    DataT a = ((t + fMass2 * qp0 * qp0t) * radThick * s0 * s0);
+    //DataT a = ((t + fMass2 * qp0 * qp0t) * radThick * s0 * s0);
 
     fTr.C22() += kf::utils::iif(fMask, txtx1 * a, DataT(0.));
     fTr.C32() += kf::utils::iif(fMask, tx * ty * a, DataT(0.));
-    fTr.C33() += kf::utils::iif(fMask, (kONE + tyty) * a, DataT(0.));
+    fTr.C33() += kf::utils::iif(fMask, tyty1 * a, DataT(0.));
   }
 
   template<typename DataT>
@@ -1087,10 +1096,12 @@ namespace cbm::algo::kf
     cnst E2   = fMass2 + p2;
 
     DataT i;
-    if (atomicZ < 13)
+    if (atomicZ < 13) {
       i = (12. * atomicZ + 7.) * 1.e-9;
-    else
+    }
+    else {
       i = (9.76 * atomicZ + 58.8 * std::pow(atomicZ, -0.19)) * 1.e-9;
+    }
 
     cnst bethe = ApproximateBetheBloch(p2 / fMass2, rho, 0.20, 3.00, i, atomicZ / atomicA);
 
diff --git a/algo/kf/core/KfTrackKalmanFilter.h b/algo/kf/core/KfTrackKalmanFilter.h
index 525ef228e98caa00ea649b40c8fd2f810f001c95..ad18cab1061dbbd0d492481c97d5e7286c4e697f 100644
--- a/algo/kf/core/KfTrackKalmanFilter.h
+++ b/algo/kf/core/KfTrackKalmanFilter.h
@@ -151,10 +151,10 @@ namespace cbm::algo::kf
 
 
     /// apply multiple scattering correction to the track with the given Qp0
-    void MultipleScattering(DataT radThick, DataT qp0);
+    void MultipleScattering(DataT radThick, DataT tx0, DataT ty0, DataT qp0);
 
     /// apply multiple scattering correction to the track
-    void MultipleScattering(DataT radThick) { MultipleScattering(radThick, fQp0); }
+    void MultipleScattering(DataT radThick) { MultipleScattering(radThick, fTr.GetTx(), fTr.GetTy(), fQp0); }
 
     /// apply multiple scattering correction in thick material to the track
     void MultipleScatteringInThickMaterial(DataT radThick, DataT thickness, bool fDownstream);
diff --git a/reco/KF/CbmKfTrackFitter.cxx b/reco/KF/CbmKfTrackFitter.cxx
index 28c2940f4f84443292f70424cf24781d93d0b7fe..fe974c9d069d80d20d803ab5b60fa4f747eb6814 100644
--- a/reco/KF/CbmKfTrackFitter.cxx
+++ b/reco/KF/CbmKfTrackFitter.cxx
@@ -428,7 +428,7 @@ void CbmKfTrackFitter::FilterFirstMeasurement(const FitNode& n)
 
   auto& tr = fFit.Tr();
 
-  tr.ResetErrors(mxy.Dx2(), mxy.Dy2(), 100., 100., 1., 1.e4, 1.e2);
+  tr.ResetErrors(mxy.Dx2(), mxy.Dy2(), 100., 100., 10., 1.e4, 1.e2);
   tr.SetC10(mxy.Dxy());
 
   if (!(fSkipUnmeasuredCoordinates && mxy.NdfX() == 0)) {
@@ -437,6 +437,8 @@ void CbmKfTrackFitter::FilterFirstMeasurement(const FitNode& n)
   if (!(fSkipUnmeasuredCoordinates && mxy.NdfY() == 0)) {
     tr.SetY(mxy.Y());
   }
+  tr.SetZ(n.fZ);
+
   tr.SetChiSq(0.);
   tr.SetChiSqTime(0.);
   tr.SetNdf(-5 + mxy.NdfX() + mxy.NdfY());
@@ -462,15 +464,18 @@ void CbmKfTrackFitter::AddMaterialEffects(CbmKfTrackFitter::FitNode& n, kf::FitD
 
   auto& tr = n.fIsFitted ? n.fTrack : fFit.Tr();
 
+  double msQp0 = n.fIsFitted ? n.fTrack.GetQp() : fFit.Qp0();
+  if (fIsQpForMsFixed) {
+    msQp0 = fDefaultQpForMs;
+  }
+
   // calculate the radiation thickness from the current track
   if (!n.fIsRadThickFixed) {
     n.fRadThick =
       CbmL1::Instance()->fpAlgo->GetParameters().GetMaterialThicknessScal(n.fMaterialLayer, tr.GetX(), tr.GetY());
   }
 
-  double msQp0 = fIsQpForMsFixed ? fDefaultQpForMs : fFit.Qp0();
-
-  fFit.MultipleScattering(n.fRadThick, msQp0);
+  fFit.MultipleScattering(n.fRadThick, tr.GetTx(), tr.GetTy(), msQp0);
   if (!fIsQpForMsFixed) {
     fFit.EnergyLossCorrection(n.fRadThick, direction);
   }
@@ -479,7 +484,7 @@ void CbmKfTrackFitter::AddMaterialEffects(CbmKfTrackFitter::FitNode& n, kf::FitD
 
 bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
 {
-  // fit the track
+  // (re)fit the track
   if (fVerbosityLevel > 0) {
     std::cout << "FitTrack ... " << std::endl;
   }
@@ -521,11 +526,13 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
   }
 
   if (!isOrdered) {
-    LOG(warning) << "CbmKfTrackFitter: the nodes are not ordered in Z!";
+    LOG(warning) << "CbmKfTrackFitter: track nodes are not ordered in Z!";
   }
 
   fFit.SetParticleMass(fMass);
 
+  // kf::GlobalField::fgOriginalFieldType = kf::EFieldType::Null;
+
   kf::FieldRegion<double> field(kf::GlobalField::fgOriginalFieldType, kf::GlobalField::fgOriginalField);
 
   {  // fit downstream
@@ -536,10 +543,16 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
 
       if (n.fIsFitted) {  // The initial parameters are taken from the previous fit
                           // Linearisation at the previously fitted momentum
-        assert(n.fZ == n.fTrack.GetZ());
+        //if (n.fZ != n.fTrack.GetZ()) {
+        //LOG(ERROR) << "Z " << n.fZ << " track Z " << n.fTrack.GetZ() << " dz " << n.fZ - n.fTrack.GetZ();
+        //}
+        //assert(n.fZ == n.fTrack.GetZ());
         fFit.SetTrack(n.fTrack);
       }
-      else {  // The initial parameters are calculated from the first and the last measurements
+      else {               // The initial parameters are calculated from the first and the last measurements
+        if (!fDoSmooth) {  //SG!!!
+          LOG(fatal) << "CbmKfTrackFitter: Debug: downstream: the first measurement is not fitted";
+        }
         auto& tr  = fFit.Tr();
         auto& n1  = t.fNodes[lastHitNode];
         tr.X()    = n.fMxy.X();
@@ -558,8 +571,8 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
 
       if (fVerbosityLevel > 0) {
         std::cout << " fit downstream: node " << firstHitNode << " chi2 " << fFit.Tr().GetChiSq() << " x "
-                  << fFit.Tr().GetX() << " y " << fFit.Tr().GetY() << " tx " << fFit.Tr().GetTx() << " ty "
-                  << fFit.Tr().GetTy() << std::endl;
+                  << fFit.Tr().GetX() << " y " << fFit.Tr().GetY() << " z " << fFit.Tr().GetZ() << " tx "
+                  << fFit.Tr().GetTx() << " ty " << fFit.Tr().GetTy() << std::endl;
       }
     }
 
@@ -567,20 +580,25 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
 
       FitNode& n = t.fNodes[iNode];
 
+      if (!fDoSmooth && !n.fIsFitted) {  //SG!!!
+        LOG(fatal) << "CbmKfTrackFitter: Debug: downstream: node " << iNode << " is not fitted";
+      }
+
       fFit.Extrapolate(n.fZ, field);
 
+      if (n.fIsFitted && (iNode <= lastHitNode)) {  // linearisation is taken from the previous fit
+        fFit.SetQp0(n.fTrack.GetQp());
+      }
+
       if (fDoSmooth) {  // store the partially fitted track
         n.fTrack    = fFit.Tr();
         n.fIsFitted = false;  // the stored track is not fully fitted
       }
 
-      if (n.fIsFitted && (iNode <= lastHitNode)) {  // linearisation is taken from the previous fit
-        fFit.SetQp0(n.fTrack.GetQp());
-      }
-
       AddMaterialEffects(n, kf::FitDirection::kDownstream);
 
       if (n.fIsXySet) {
+        assert(iNode <= lastHitNode);
         fFit.FilterXY(n.fMxy, fSkipUnmeasuredCoordinates);
       }
       if (n.fIsTimeSet) {
@@ -589,10 +607,10 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
 
       if (fVerbosityLevel > 0) {
         std::cout << " fit downstream: node " << iNode << " chi2 " << fFit.Tr().GetChiSq() << " x " << fFit.Tr().GetX()
-                  << " y " << fFit.Tr().GetY() << " tx " << fFit.Tr().GetTx() << " ty " << fFit.Tr().GetTy()
-                  << std::endl;
+                  << " y " << fFit.Tr().GetY() << " z " << fFit.Tr().GetZ() << " tx " << fFit.Tr().GetTx() << " ty "
+                  << fFit.Tr().GetTy() << std::endl;
       }
-      if (iNode >= lastHitNode) {  // the track is fully fitted, store it
+      if (fDoSmooth && iNode >= lastHitNode) {  // the track is fully fitted, store it
         n.fTrack    = fFit.Tr();
         n.fIsFitted = true;
         fFit.SetQp0(fFit.Tr().GetQp());  // set the linearisation of q/p to the fitted value
@@ -607,22 +625,28 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
 
     {
       FitNode& n = t.fNodes[lastHitNode];
+      if (!fDoSmooth && !n.fIsFitted) {
+        LOG(fatal) << "CbmKfTrackFitter: Debug: upstream: the last measurement is not fitted";
+      }
+
       assert(n.fIsFitted);
       fFit.SetTrack(n.fTrack);
       FilterFirstMeasurement(n);
       if (fVerbosityLevel > 0) {
-        std::cout << "\n\n up node " << lastHitNode << " chi2 " << fFit.Tr().GetChiSq() << " x " << fFit.Tr().GetX()
-                  << " y " << fFit.Tr().GetY() << " tx " << fFit.Tr().GetTx() << " ty " << fFit.Tr().GetTy()
-                  << std::endl;
+        std::cout << "\n\n fit upstream: node " << lastHitNode << " chi2 " << fFit.Tr().GetChiSq() << " x "
+                  << fFit.Tr().GetX() << " y " << fFit.Tr().GetY() << " z " << fFit.Tr().GetZ() << " tx "
+                  << fFit.Tr().GetTx() << " ty " << fFit.Tr().GetTy() << std::endl;
       }
     }
 
     for (int iNode = lastHitNode - 1; iNode >= 0; iNode--) {
       FitNode& n = t.fNodes[iNode];
 
-      fFit.Extrapolate(n.fZ, field);
+      if (!fDoSmooth && !n.fIsFitted) {
+        LOG(fatal) << "CbmKfTrackFitter: Debug: upstream: the node " << iNode << "is not fitted";
+      }
 
-      AddMaterialEffects(n, kf::FitDirection::kUpstream);
+      fFit.Extrapolate(n.fZ, field);
 
       if (n.fIsXySet) {
         fFit.FilterXY(n.fMxy, fSkipUnmeasuredCoordinates);
@@ -630,31 +654,35 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
       if (n.fIsTimeSet) {
         fFit.FilterTime(n.fMt);
       }
+
+      AddMaterialEffects(n, kf::FitDirection::kUpstream);
+
       if (fVerbosityLevel > 0) {
-        std::cout << " up node " << iNode << " chi2 " << fFit.Tr().GetChiSq() << " x " << fFit.Tr().GetX() << " y "
-                  << fFit.Tr().GetY() << " tx " << fFit.Tr().GetTx() << " ty " << fFit.Tr().GetTy() << std::endl;
+        std::cout << " fit upstream: node " << iNode << " chi2 " << fFit.Tr().GetChiSq() << " x " << fFit.Tr().GetX()
+                  << " y " << fFit.Tr().GetY() << " z " << fFit.Tr().GetZ() << " tx " << fFit.Tr().GetTx() << " ty "
+                  << fFit.Tr().GetTy() << std::endl;
       }
 
       // combine partially fitted downstream and upstream tracks
-      n.fIsFitted = true;
 
       if (iNode > firstHitNode) {
-        n.fIsFitted = false;
         if (fDoSmooth) {
           n.fIsFitted = Smooth(n.fTrack, fFit.Tr());
         }
       }
       else {
-        n.fIsFitted = true;
-        n.fTrack    = fFit.Tr();
+        if (fDoSmooth) {
+          n.fIsFitted = true;
+          n.fTrack    = fFit.Tr();
+        }
       }
+
       if (fDoSmooth && !n.fIsFitted) {
         ok = false;
       }
       if (n.fIsFitted) {
         fFit.SetQp0(n.fTrack.GetQp());
       }
-      AddMaterialEffects(n, kf::FitDirection::kUpstream);
     }
   }
 
@@ -665,9 +693,13 @@ bool CbmKfTrackFitter::FitTrack(CbmKfTrackFitter::Track& t)
     if (upNdf != dnNdf) {
       LOG(fatal) << "CbmKfTrackFitter: ndf mismatch: dn " << dnNdf << " != up " << upNdf;
     }
-    if (fabs(upChi2 - dnChi2) > 1.e-2) {
-      LOG(fatal) << "CbmKfTrackFitter: chi2 mismatch: dn " << dnChi2 << " != up " << upChi2 << " first node "
-                 << firstHitNode << " last node " << lastHitNode << " of " << nNodes;
+    if (fabs(upChi2 - dnChi2) > 1.e-1) {
+      //if (upChi2 > dnChi2 + 1.e-2) {
+      LOG(error) << "CbmKfTrackFitter: " << fDebugInfo << ": chi2 mismatch: dn " << dnChi2 << " != up " << upChi2
+                 << " first node " << firstHitNode << " last node " << lastHitNode << " of " << nNodes;
+      //if (fVerbosityLevel > 0) {
+      exit(1);
+      //}
     }
   }
   // distribute the final chi2, ndf to all nodes
diff --git a/reco/KF/CbmKfTrackFitter.h b/reco/KF/CbmKfTrackFitter.h
index 00a5f11e97c317c97afecd2748b0b86c1fd4e04a..50f6182c3cefd5123da40fb10b04af60f9c00169 100644
--- a/reco/KF/CbmKfTrackFitter.h
+++ b/reco/KF/CbmKfTrackFitter.h
@@ -51,7 +51,10 @@ class CbmKfTrackFitter {
   /// When fIsFitted flag is set (e.g. by the fitter), the node track parameters are used
   /// for the trajectory linearisation during the fit.
   ///
-  // TODO: proper interface
+  /// When fitting w/o smoother we assume that smoothed parameters are always better than partially fitted parameters
+  ///
+  /// TODO: proper interface and description
+  ///
   struct FitNode {
 
     double fZ{0.};  ///< Z coordinate
@@ -115,7 +118,13 @@ class CbmKfTrackFitter {
   void SetSkipUnmeasuredCoordinates(bool skip = true) { fSkipUnmeasuredCoordinates = skip; }
 
   /// set the default inverse momentum for the Multiple Scattering calculation
-  void SetDefaultMomentumForMs(double p) { fDefaultQpForMs = 1. / p; }
+  void SetDefaultMomentumForMs(double p) { fDefaultQpForMs = fabs(1. / p); }
+
+  /// set the default inverse momentum for the Multiple Scattering calculation
+  void SetDefaultInverseMomentumForMs(double invP) { fDefaultQpForMs = fabs(invP); }
+
+  /// set the default inverse momentum for the Multiple Scattering calculation
+  void SetNoMultipleScattering() { fDefaultQpForMs = 0.; }
 
   /// fix the inverse momentum for the Multiple Scattering calculation
   void FixMomentumForMs(bool fix = true) { fIsQpForMsFixed = fix; }
@@ -134,6 +143,9 @@ class CbmKfTrackFitter {
   /// set verbosity level
   void SetVerbosityLevel(int level) { fVerbosityLevel = level; }
 
+  /// set information about the track for debug output
+  void SetDebugInfo(const std::string &info) { fDebugInfo = info; }
+
  private:
   void FilterFirstMeasurement(const FitNode& n);
 
@@ -173,4 +185,5 @@ class CbmKfTrackFitter {
   bool fIsElectron{false};                   // fit track as an electron (with the bermsstrallung effect)
   bool fDoSmooth{true};                      // do the KF-smoothing to define track pars at all the nodes
   int fVerbosityLevel{0};                    // verbosity level
+  std::string fDebugInfo{};                  // debug info
 };