inputIndex = 0; inputIndex < _slices.size(); inputIndex++)
    if (slice_potential_gpu[inputIndex] >= 0) {
    sum += (slice_potential_gpu[inputIndex] - _mean_s_gpu) * (slice_potential_gpu[inputIndex] - _mean_s_gpu)
      * _slice_weight_gpu[inputIndex];
    den += _slice_weight_gpu[inputIndex];

    sum2 += (slice_potential_gpu[inputIndex] - _mean_s2_gpu) * (slice_potential_gpu[inputIndex] - _mean_s2_gpu)
      * (1 - _slice_weight_gpu[inputIndex]);
    den2 += (1 - _slice_weight_gpu[inputIndex]);

    }

  //_sigma_s
  if ((sum > 0) && (den > 0)) {
    _sigma_s_gpu = (float)(sum / den);
    //do not allow too small sigma
    if (_sigma_s_gpu < _step * _step / 6.28)
      _sigma_s_gpu = (float)(_step * _step / 6.28);
  }
  else {
    _sigma_s_gpu = 0.025f;
    if (_debug) {
      if (sum <= 0)
        cout << "All slices are equal. ";
      if (den < 0) //this should not happen
        cout << "All slices are outliers. ";
      cout << "Setting sigma to " << sqrt(_sigma_s_gpu) << endl;
    }
  }

  //sigma_s2
  if ((sum2 > 0) && (den2 > 0)) {
    _sigma_s2_gpu = (float)(sum2 / den2);
    //do not allow too small sigma
    if (_sigma_s2_gpu < _step * _step / 6.28)
      _sigma_s2_gpu = (float)(_step * _step / 6.28);
  }
  else {
    _sigma_s2_gpu = (_mean_s2_gpu - _mean_s_gpu) * (_mean_s2_gpu - _mean_s_gpu) / 4;
    //do not allow too small sigma
    if (_sigma_s2_gpu < _step * _step / 6.28)
      _sigma_s2_gpu = (float)(_step * _step / 6.28);

    if (_debug) {
      if (sum2 <= 0)
        cout << "All slices are equal. ";
      if (den2 <= 0)
        cout << "All slices inliers. ";
      cout << "Setting sigma_s2 to " << sqrt(_sigma_s2_gpu) << endl;
    }
  }

  //Calculate slice weights
  double gs1, gs2;
  for (inputIndex = 0; inputIndex < _slices.size(); inputIndex++) {
    //Slice does not have any voxels in volumetric ROI
    if (slice_potential_gpu[inputIndex] == -1) {
      _slice_weight_gpu[inputIndex] = 0;
      continue;
    }

    //All slices are outliers or the means are not valid
    if ((den <= 0) || (_mean_s2_gpu <= _mean_s_gpu)) {
      _slice_weight_gpu[inputIndex] = 1;
      continue;
    }

    //likelihood for inliers
    if (slice_potential_gpu[inputIndex] < _mean_s2_gpu)
      gs1 = G(slice_potential_gpu[inputIndex] - _mean_s_gpu, _sigma_s_gpu);
    else
      gs1 = 0;

    //likelihood for outliers
    if (slice_potential_gpu[inputIndex] > _mean_s_gpu)
      gs2 = G(slice_potential_gpu[inputIndex] - _mean_s2_gpu, _sigma_s2_gpu);
    else
      gs2 = 0;

    //calculate slice weight
    double likelihood = gs1 * _mix_s_gpu + gs2 * (1 - _mix_s_gpu);
    if (likelihood > 0)
      _slice_weight_gpu[inputIndex] = (float)(gs1 * _mix_s_gpu / likelihood);
    else {
      if (slice_potential_gpu[inputIndex] <= _mean_s_gpu)
        _slice_weight_gpu[inputIndex] = 1;
      if (slice_potential_gpu[inputIndex] >= _mean_s2_gpu)
        _slice_weight_gpu[inputIndex] = 0;
      if ((slice_potential_gpu[inputIndex] < _mean_s2_gpu) && (slice_potential_gpu[inputIndex] > _mean_s_gpu)) //should not happen
        _slice_weight_gpu[inputIndex] = 1;
    }
  }

  //Update _mix_s this should also be part of MStep
  sum = 0;
  int num = 0;
  for (inputIndex = 0; inputIndex < _slices.size(); inputIndex++)
    if (slice_potential_gpu[inputIndex] >= 0) {
    sum += _slice_weight_gpu[inputIndex];
    num++;
    }

  if (num > 0)
    _mix_s_gpu = (float)(sum / num);
  else {
    cout << "All slices are outliers. Setting _mix_s to 0.9." << endl;
    _mix_s_gpu = 0.9f;
  }

  if (_debug || _debugGPU) {
    cout << setprecision(3);
    cout << "Slice robust statistics parameters GPU: ";
    cout << "means: " << _mean_s_gpu << " " << _mean_s2_gpu << "  ";
    cout << "sigmas: " << sqrt(_sigma_s_gpu) << " " << sqrt(_sigma_s2_gpu) << "  ";
    cout << "proportions: " << _mix_s_gpu << " " << 1 - _mix_s_gpu << endl;
    cout << "Slice weights GPU: ";
    for (inputIndex = 0; inputIndex < _slices.size(); inputIndex++)
      cout << _slice_weight_gpu[inputIndex] << " ";
    /*cout << "Slice potential: ";
    for (inputIndex = 0; inputIndex < _slices.size(); inputIndex++)
    cout << slice_potential[inputIndex] << " ";*/
    cout << endl;
  }

  //TODO only slice weight
  reconstructionGPU->UpdateSliceWeights(_slice_weight_gpu);

}

void irtkReconstruction::EStep()
{
  //EStep performs calculation of voxel-wise and slice-wise posteriors (weights)
  if (_debug)
    cout << "EStep: " << endl;

  unsigned int inputIndex;
  irtkRealImage slice, w, b, sim;
  int num = 0;
  vector<double> slice_potential_cpu(_slices.size(), 0);
  //std::cout << "num Estp CPU: ";
  ParallelEStep parallelEStep(this, slice_potential_cpu);
  parallelEStep();

  if(_debugGPU)
  {
    _weights[40].Write("testweightCPU.nii");
}

  //To force-exclude slices predefined by a user, set their potentials to -1
  for (unsigned int i = 0; i < _force_excluded.size(); i++)
    slice_potential_cpu[_force_excluded[i]] = -1;

  //exclude slices identified as having small overlap with ROI, set their potentials to -1
  for (unsigned int i = 0; i < _small_slices.size(); i++)
    slice_potential_cpu[_small_slices[i]] = -1;

  //these are unrealistic scales pointing at misregistration - exclude the corresponding slices
  for (inputIndex = 0; inputIndex < slice_potential_cpu.size(); inputIndex++)
    if ((_scale_cpu[inputIndex] < 0.2) || (_scale_cpu[inputIndex]>5)) {
    slice_potential_cpu[inputIndex] = -1;
    }

  // exclude unrealistic transformations
  /*
  int current_stack = 0;
  int nb_stacks = _stack_index[_stack_index.size()-1];
  double tx,ty,tz,rx,ry,rz, nb;
  for ( int i = 0; i < nb_stacks; i++ ) {
  tx = 0;
  ty