diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc
index 34b55476d9a4f869bd9a29c51688d0f49e680c37..0df3f0d6499228b06865019a13904d26da59ade8 100644
--- a/Documentation/Examples/cascade_example.cc
+++ b/Documentation/Examples/cascade_example.cc
@@ -24,6 +24,7 @@
 #include <corsika/process/sibyll/ParticleConversion.h>
 
 #include <corsika/units/PhysicalUnits.h>
+
 using namespace corsika;
 using namespace corsika::process;
 using namespace corsika::units;
@@ -43,46 +44,59 @@ public:
   template <typename Particle>
   double MinStepLength(Particle& p, setup::Trajectory&) const {
 
+    const Code corsikaBeamId = p.GetPID();
+    
     // beam particles for sibyll : 1, 2, 3 for p, pi, k
     // read from cross section code table
-    int kBeam = 1;
+    int kBeam   =  process::sibyll::GetSibyllXSCode( corsikaBeamId );   
 
-    /*
+    bool kInteraction = process::sibyll::CanInteract( corsikaBeamId );
+    
+    /* 
        the target should be defined by the Environment,
        ideally as full particle object so that the four momenta
        and the boosts can be defined..
      */
     // target nuclei: A < 18
     // FOR NOW: assume target is oxygen
-    int kTarget = 1;
-    double beamEnergy = p.GetEnergy() / 1_GeV;
-    std::cout << "ProcessSplit: "
-              << "MinStep: en: " << beamEnergy << " pid:" << kBeam << std::endl;
-    double prodCrossSection, dummy, dum1, dum2, dum3, dum4;
-    double dumdif[3];
-
-    if (kTarget == 1)
-      sib_sigma_hp_(kBeam, beamEnergy, dum1, dum2, prodCrossSection, dumdif, dum3, dum4);
-    else
-      sib_sigma_hnuc_(kBeam, kTarget, beamEnergy, prodCrossSection, dummy);
-
-    std::cout << "ProcessSplit: "
-              << "MinStep: sibyll return: " << prodCrossSection << std::endl;
-    CrossSectionType sig = prodCrossSection * 1_mbarn;
-    std::cout << "ProcessSplit: "
-              << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl;
-
-    const MassType nucleon_mass = 0.93827_GeV / corsika::units::si::constants::cSquared;
-    std::cout << "ProcessSplit: "
-              << "nucleon mass " << nucleon_mass << std::endl;
-    // calculate interaction length in medium
-    double int_length = kTarget * (nucleon_mass / 1_g) / (sig / 1_cmeter / 1_cmeter);
-    // pick random step lenth
-    std::cout << "ProcessSplit: "
-              << "interaction length (g/cm2): " << int_length << std::endl;
-    // add exponential sampling
-    int a = 0;
-    const double next_step = -int_length * log(s_rndm_(a));
+    int kTarget = 16;
+    double beamEnergy =  p.GetEnergy() / 1_GeV;
+#warning boost to cm. still missing, sibyll cross section input is cm. energy!
+    
+    std::cout << "ProcessSplit: " << "MinStep: input en: " << beamEnergy
+      	      << " beam can interact:" << kBeam
+	      << " beam XS code:" << kBeam
+      	      << " beam pid:" << p.GetPID()
+	      << " target mass number:" << kTarget << std::endl;
+
+    double next_step;
+    if(kInteraction){
+      
+      double prodCrossSection,dummy,dum1,dum2,dum3,dum4;
+      double dumdif[3];
+      
+      if(kTarget==1)
+	sib_sigma_hp_(kBeam, beamEnergy, dum1, dum2, prodCrossSection, dumdif,dum3, dum4 );
+      else
+	sib_sigma_hnuc_(kBeam, kTarget, beamEnergy, prodCrossSection, dummy );
+    
+      std::cout << "ProcessSplit: " << "MinStep: sibyll return: " << prodCrossSection << std::endl;
+      CrossSectionType sig = prodCrossSection * 1_mbarn;
+      std::cout << "ProcessSplit: " << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl;
+
+      const MassType nucleon_mass = 0.93827_GeV / corsika::units::si::constants::cSquared;
+      std::cout << "ProcessSplit: " << "nucleon mass " << nucleon_mass << std::endl;
+      // calculate interaction length in medium
+      double int_length = kTarget * ( nucleon_mass / 1_g ) / ( sig / 1_cmeter / 1_cmeter );
+      // pick random step lenth
+      std::cout << "ProcessSplit: " << "interaction length (g/cm2): " << int_length << std::endl;
+      // add exponential sampling
+      int a = 0;
+      next_step = -int_length * log(s_rndm_(a));
+    }else
+#warning define infinite interaction length? then we can skip the test in DoDiscrete()
+      next_step = 1.e8;
+    
     /*
       what are the units of the output? slant depth or 3space length?
 
@@ -93,86 +107,154 @@ public:
   }
 
   template <typename Particle, typename Stack>
-  EProcessReturn DoContinuous(Particle&, Trajectory&, Stack&) const {
+  EProcessReturn DoContinuous(Particle&, setup::Trajectory&, Stack&) const {
     // corsika::utls::ignore(p);
     return EProcessReturn::eOk;
   }
 
   template <typename Particle, typename Stack>
   void DoDiscrete(Particle& p, Stack& s) const {
-    cout << "DoDiscrete: " << p.GetPID() << " interaction? "
-         << process::sibyll::CanInteract(p.GetPID()) << endl;
-    if (process::sibyll::CanInteract(p.GetPID())) {
-
+    cout << "DoDiscrete: " << p.GetPID() << " interaction? " << process::sibyll::CanInteract( p.GetPID() )  << endl; 
+    if( process::sibyll::CanInteract( p.GetPID() ) ){
+      cout << "defining coordinates" << endl;
+      // coordinate system, get global frame of reference
+      CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS();
+
+      QuantityVector<length_d> const coordinates{0_m, 0_m, 0_m};
+      Point pOrig(rootCS, coordinates);
+      
+      /* 
+	 the target should be defined by the Environment,
+	 ideally as full particle object so that the four momenta 
+	 and the boosts can be defined..
+
+	 here we need: GetTargetMassNumber() or GetTargetPID()??
+	               GetTargetMomentum() (zero in EAS)
+      */
+      // FOR NOW: set target to proton
+      int kTarget = 1; //p.GetPID();
+
+      // proton mass in units of energy
+      const EnergyType proton_mass_en = 0.93827_GeV ; //0.93827_GeV / si::constants::cSquared ;
+
+      cout << "defining target momentum.." << endl;
+      // FOR NOW: target is always at rest
+      const EnergyType Etarget = 0. * 1_GeV + proton_mass_en;      
+      const auto pTarget = super_stupid::MomentumVector(rootCS, 0. * 1_GeV / si::constants::c,  0. * 1_GeV / si::constants::c, 0. * 1_GeV / si::constants::c);
+      cout << "target momentum (GeV/c): " << pTarget.GetComponents() / 1_GeV * si::constants::c << endl;
+      //      const auto pBeam = super_stupid::MomentumVector(rootCS, 0. * 1_GeV / si::constants::c,  0. * 1_GeV / si::constants::c, 0. * 1_GeV / si::constants::c);
+      //      cout << "beam momentum: " << pBeam.GetComponents() << endl;
+      cout << "beam momentum (GeV/c): " << p.GetMomentum().GetComponents() / 1_GeV * si::constants::c << endl;
+      
       // get energy of particle from stack
       /*
-        stack is in GeV in lab. frame
-        convert to GeV in cm. frame
-        (assuming proton at rest as target AND
-        assuming no pT, i.e. shower frame-z is aligned with hadron-int-frame-z)
+	stack is in GeV in lab. frame
+	convert to GeV in cm. frame 
+	(assuming proton at rest as target AND 
+	assuming no pT, i.e. shower frame-z is aligned with hadron-int-frame-z)
       */
-      EnergyType E = p.GetEnergy();
-      EnergyType Ecm = sqrt(2. * E * 0.93827_GeV);
-
-      int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID());
+      // cout << "defining total energy" << endl;
+      // total energy: E_beam + E_target
+      // in lab. frame: E_beam + m_target*c**2
+      EnergyType E   = p.GetEnergy();
+      EnergyType Etot   = E + Etarget;
+      // cout << "tot. energy: " << Etot / 1_GeV << endl;
+      // cout << "defining total momentum" << endl;
+      // total momentum
+      super_stupid::MomentumVector Ptot = p.GetMomentum(); // + pTarget;
+      // cout << "tot. momentum: " << Ptot.GetComponents() / 1_GeV * si::constants::c << endl;
+      // cout << "inv. mass.." << endl;
+      // invariant mass, i.e. cm. energy
+      EnergyType Ecm = sqrt( Etot * Etot - Ptot.squaredNorm() * si::constants::cSquared ); //sqrt( 2. * E * 0.93827_GeV );
+      // cout << "inv. mass: " << Ecm / 1_GeV << endl; 
+      // cout << "boost parameters.." << endl;
+       /*
+	get transformation between Stack-frame and SibStack-frame
+	for EAS Stack-frame is lab. frame, could be different for CRMC-mode
+	the transformation should be derived from the input momenta
+      */      
+      //      const double gamma  = ( E + proton_mass * si::constants::cSquared ) / Ecm ;
+      // const double gambet =  sqrt( E * E - proton_mass * proton_mass ) / Ecm;
+      const double gamma  = Etot / Ecm ;
+      const auto gambet = Ptot / (Ecm / si::constants::c );      
+
+      std::cout << "ProcessSplit: " << " DoDiscrete: gamma:" << gamma << endl;
+      std::cout << "ProcessSplit: " << " DoDiscrete: gambet:" << gambet.GetComponents() << endl;
+      
+      int kBeam   = process::sibyll::ConvertToSibyllRaw( p.GetPID() );
+    
+  
+      std::cout << "ProcessSplit: " << " DoDiscrete: E(GeV):" << E / 1_GeV << " Ecm(GeV): " << Ecm / 1_GeV << std::endl;
+    if (E < 8.5_GeV || Ecm < 10_GeV ) {
+      std::cout << "ProcessSplit: " << " DoDiscrete: dropping particle.." << std::endl;
+      p.Delete();
+      fCount++;
+    } else {
+      // Sibyll does not know about units..
+      double sqs = Ecm / 1_GeV;
+      // running sibyll, filling stack
+      sibyll_( kBeam, kTarget, sqs);
+      // running decays
+      //decsib_();
+      // print final state
+      int print_unit = 6;
+      sib_list_( print_unit );
+
+      // delete current particle
+      p.Delete();
 
-      /*
-         the target should be defined by the Environment,
-         ideally as full particle object so that the four momenta
-         and the boosts can be defined..
-       */
-      // FOR NOW: set target to proton
-      int kTarget = 1; // p.GetPID();
-
-      std::cout << "ProcessSplit: "
-                << " DoDiscrete: E(GeV):" << E / 1_GeV << " Ecm(GeV): " << Ecm / 1_GeV
-                << std::endl;
-      if (E < 8.5_GeV || Ecm < 10_GeV) {
-        std::cout << "ProcessSplit: "
-                  << " DoDiscrete: dropping particle.." << std::endl;
-        p.Delete();
-        fCount++;
-      } else {
-        // Sibyll does not know about units..
-        double sqs = Ecm / 1_GeV;
-        // running sibyll, filling stack
-        sibyll_(kBeam, kTarget, sqs);
-        // running decays
-        // decsib_();
-        // print final state
-        int print_unit = 6;
-        sib_list_(print_unit);
-
-        // delete current particle
-        p.Delete();
-
-        // add particles from sibyll to stack
-        // link to sibyll stack
-        SibStack ss;
-        /*
-          get transformation between Stack-frame and SibStack-frame
-          for EAS Stack-frame is lab. frame, could be different for CRMC-mode
-          the transformation should be derived from the input momenta
-          in general transformation is rotation + boost
-        */
-        const EnergyType proton_mass = 0.93827_GeV;
-        const double gamma = (E + proton_mass) / (Ecm);
-        const double gambet = sqrt(E * E - proton_mass * proton_mass) / Ecm;
-
-        // SibStack does not know about momentum yet so we need counter to access momentum
-        // array in Sibyll
-        int i = -1;
-        for (auto& p : ss) {
-          ++i;
-          // transform to lab. frame, primitve
-          const double en_lab = gambet * s_plist_.p[2][i] + gamma * p.GetEnergy();
-          // add to corsika stack
-          auto pnew = s.NewParticle();
-          pnew.SetEnergy(en_lab * 1_GeV);
-          pnew.SetPID(process::sibyll::ConvertFromSibyll(p.GetPID()));
-        }
+      // add particles from sibyll to stack
+      // link to sibyll stack
+      SibStack ss;
+
+      // SibStack does not know about momentum yet so we need counter to access momentum array in Sibyll
+      int i = -1;
+      super_stupid::MomentumVector Ptot_final(rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second});
+      for (auto &psib: ss){
+	++i;
+	//transform energy to lab. frame, primitve
+	// compute beta_vec * p_vec
+	// arbitrary Lorentz transformation based on sibyll routines
+	const auto gammaBetaComponents = gambet.GetComponents();
+	const auto pSibyllComponents = psib.GetMomentum().GetComponents();	
+	EnergyType en_lab = 0. * 1_GeV;	
+	MomentumType p_lab_components[3];
+	en_lab =  psib.GetEnergy() * gamma;
+	EnergyType pnorm = 0. * 1_GeV;
+	for(int j=0; j<3; ++j)
+	  pnorm += ( pSibyllComponents[j] * gammaBetaComponents[j] * si::constants::c ) / ( gamma + 1.);
+	pnorm += psib.GetEnergy();
+	
+	for(int j=0; j<3; ++j){
+	  p_lab_components[j] = pSibyllComponents[j] - (-1) * pnorm * gammaBetaComponents[j] /  si::constants::c;
+	  // cout << "p:" << j << " pSib (GeV/c): " << pSibyllComponents[j] / 1_GeV * si::constants::c
+	  //      << " gb: " << gammaBetaComponents[j] << endl;
+	  en_lab -= (-1) * pSibyllComponents[j] * gammaBetaComponents[j] * si::constants::c;
+	}
+	//	const EnergyType en_lab = psib.GetEnergy()*gamma + gambet * psib.GetMomentum() * si::constants::c );
+	// cout << " en cm  (GeV): " << psib.GetEnergy() / 1_GeV << endl
+	//      << " en lab (GeV): " << en_lab / 1_GeV << endl;
+	// cout << " pz cm  (GeV/c): " << psib.GetMomentum().GetComponents()[2] / 1_GeV * si::constants::c << endl
+	//      << " pz lab (GeV/c): " << p_lab_components[2] / 1_GeV * si::constants::c << endl;
+	
+	// add to corsika stack
+	auto pnew = s.NewParticle();
+	pnew.SetEnergy( en_lab );
+	pnew.SetPID( process::sibyll::ConvertFromSibyll( psib.GetPID() ) );
+	//cout << "momentum sib (cm): " << psib.GetMomentum().GetComponents() / 1_GeV * si::constants::c << endl;
+	
+	corsika::geometry::QuantityVector<momentum_d> p_lab_c{ p_lab_components[0],
+							       p_lab_components[1],
+							       p_lab_components[2]};
+	pnew.SetMomentum( super_stupid::MomentumVector( rootCS, p_lab_c) );
+	//cout << "momentum sib (lab): " << pnew.GetMomentum().GetComponents() / 1_GeV * si::constants::c << endl;
+	//cout << "s_cm  (GeV2): " << (psib.GetEnergy() * psib.GetEnergy() - psib.GetMomentum().squaredNorm() * si::constants::cSquared ) / 1_GeV / 1_GeV << endl;
+	//cout << "s_lab (GeV2): " << (pnew.GetEnergy() * pnew.GetEnergy() - pnew.GetMomentum().squaredNorm() * si::constants::cSquared ) / 1_GeV / 1_GeV << endl;
+	Ptot_final += pnew.GetMomentum();
       }
-    } else
+      //cout << "tot. momentum final (GeV/c): " << Ptot_final.GetComponents() / 1_GeV * si::constants::c << endl;
+    }
+    }else
       p.Delete();
   }
 
@@ -238,6 +320,8 @@ double s_rndm_(int&) {
 
 int main() {
 
+  CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS();
+  
   tracking_line::TrackingLine<setup::Stack> tracking;
   stack_inspector::StackInspector<setup::Stack> p0(true);
   ProcessSplit p1;
@@ -248,9 +332,15 @@ int main() {
 
   stack.Clear();
   auto particle = stack.NewParticle();
-  EnergyType E0 = 100_GeV;
+  EnergyType E0 = 500_GeV;
+  MomentumType P0 = sqrt( E0*E0 - 0.93827_GeV * 0.93827_GeV ) / si::constants::c;
+  auto plab = super_stupid::MomentumVector(rootCS,
+					   0. * 1_GeV / si::constants::c,
+					   0. * 1_GeV / si::constants::c,
+					   P0);
   particle.SetEnergy(E0);
-  particle.SetPID(Code::Proton);
+  particle.SetMomentum(plab);
+  particle.SetPID( Code::Proton );
   EAS.Init();
   EAS.Run();
   cout << "Result: E0=" << E0 / 1_GeV << "GeV, count=" << p1.GetCount() << endl;
diff --git a/Framework/Cascade/SibStack.h b/Framework/Cascade/SibStack.h
index 7e9bd3bac3bc743bea8fcb0c2b0d1d401e16efae..57a3f9c16b099c6d00e71b405223f6c3f7eb41c5 100644
--- a/Framework/Cascade/SibStack.h
+++ b/Framework/Cascade/SibStack.h
@@ -10,6 +10,8 @@
 
 using namespace std;
 using namespace corsika::stack;
+using namespace corsika::units;
+using namespace corsika::geometry;
 
 class SibStackData {
 
@@ -17,16 +19,33 @@ public:
   void Init();
 
   void Clear() { s_plist_.np = 0; }
-
-  int GetSize() const { return s_plist_.np; }
+  
+  int GetSize() const { return s_plist_.np;  }
+#warning check actual capacity of sibyll stack  
   int GetCapacity() const { return 8000; }
 
-  void SetId(const int i, const int v) { s_plist_.llist[i] = v; }
-  void SetEnergy(const int i, const double v) { s_plist_.p[3][i] = v; }
-
+  
+  void SetId(const int i, const int v) { s_plist_.llist[i]=v; }
+  void SetEnergy(const int i, const EnergyType v) { s_plist_.p[3][i] = v / 1_GeV;  }
+  void SetMomentum(const int i, const super_stupid::MomentumVector& v)
+  {
+    auto tmp = v.GetComponents();
+    for(int idx=0; idx<3; ++idx)      
+      s_plist_.p[idx][i] = tmp[idx] / 1_GeV * si::constants::c;    
+  }
+  
   int GetId(const int i) const { return s_plist_.llist[i]; }
-  double GetEnergy(const int i) const { return s_plist_.p[3][i]; }
-
+  
+  EnergyType GetEnergy(const int i) const { return s_plist_.p[3][i] * 1_GeV; }
+  
+  super_stupid::MomentumVector GetMomentum(const int i) const
+  {
+    CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS();
+    corsika::geometry::QuantityVector<momentum_d> components{ s_plist_.p[0][i] * 1_GeV / si::constants::c , s_plist_.p[1][i] * 1_GeV / si::constants::c, s_plist_.p[2][i] * 1_GeV / si::constants::c};
+    super_stupid::MomentumVector v1(rootCS,components);
+    return v1;
+  }
+  
   void Copy(const int i1, const int i2) {
     s_plist_.llist[i1] = s_plist_.llist[i2];
     s_plist_.p[3][i1] = s_plist_.p[3][i2];
@@ -46,12 +65,11 @@ class ParticleInterface : public ParticleBase<StackIteratorInterface> {
 
 public:
   void SetEnergy(const double v) { GetStackData().SetEnergy(GetIndex(), v); }
-  double GetEnergy() const { return GetStackData().GetEnergy(GetIndex()); }
+  EnergyType GetEnergy() const { return GetStackData().GetEnergy(GetIndex()); }
   void SetPID(const int v) { GetStackData().SetId(GetIndex(), v); }
-  corsika::process::sibyll::SibyllCode GetPID() const {
-    return static_cast<corsika::process::sibyll::SibyllCode>(
-        GetStackData().GetId(GetIndex()));
-  }
+  corsika::process::sibyll::SibyllCode GetPID() const { return static_cast<corsika::process::sibyll::SibyllCode> (GetStackData().GetId(GetIndex())); }
+  super_stupid::MomentumVector GetMomentum() const { return GetStackData().GetMomentum(GetIndex()); }
+  
 };
 
 typedef Stack<SibStackData, ParticleInterface> SibStack;