void QmitkTbssRoiAnalysisWidget::DoPlotFiberBundles(mitk::FiberBundle *fib, mitk::Image* img,
                                                    mitk::DataNode* startRoi, mitk::DataNode* endRoi, bool avg, int number)
{

  TractContainerType tracts = CreateTracts(fib, startRoi, endRoi);

  TractContainerType resampledTracts = ParameterizeTracts(tracts, number);

  // Now we have the resampled tracts. Next we should use these points to read out the values



  mitkPixelTypeMultiplex3(PlotFiberBundles,img->GetImageDescriptor()->GetChannelTypeById(0),resampledTracts, img, avg);
  m_CurrentTracts = resampledTracts;
}
std::vector< std::vector<mitk::ScalarType> > QmitkTbssRoiAnalysisWidget::CalculateGroupProfilesFibers(mitk::TbssImage::Pointer tbssImage,
                                                                                            mitk::FiberBundle *fib,
                                                                                            mitk::DataNode* startRoi,
                                                                                            mitk::DataNode* endRoi,
                                                                                            int number)
{
    TractContainerType tracts = CreateTracts(fib, startRoi, endRoi);

    TractContainerType resampledTracts = ParameterizeTracts(tracts, number);

    int nTracts = resampledTracts.size();

    this->Clear();


    // For every group we have m fibers * n subjects of profiles to fill

    std::vector< std::vector<mitk::ScalarType> > profiles;

    // calculate individual profiles by going through all n subjects
    int size = m_Projections->GetVectorLength();
    for(int s=0; s<size; s++)
    {

      // Iterate through all tracts

      for(int t=0; t<nTracts; t++)
      {
        // Iterate trough the tract
        std::vector<mitk::ScalarType> profile;
        TractType::iterator it = resampledTracts[t].begin();
        while(it != resampledTracts[t].end())
        {
          PointType p = *it;
          PointType index;
          tbssImage->GetGeometry()->WorldToIndex(p, index);

          itk::Index<3> ix;
          ix[0] = index[0];
          ix[1] = index[1];
          ix[2] = index[2];
          // Get value from image

          profile.push_back(m_Projections->GetPixel(ix).GetElement(s));

          it++;
        }
        profiles.push_back(profile);
      }


    }

    m_IndividualProfiles = profiles;

    // Now create the group averages (every group contains m fibers * n_i group members

    std::vector< std::pair<std::string, int> >::iterator it;
    it = m_Groups.begin();
    int c = 0; //the current profile number

    // Calculate the group averages
    std::vector< std::vector<mitk::ScalarType> > groupProfiles;

    while(it != m_Groups.end() && profiles.size() > 0)
    {
      std::pair<std::string, int> p = *it;
      int size = p.second;

      //initialize a vector of the right length with zeroes
      std::vector<mitk::ScalarType> averageProfile;
      for(unsigned int i=0; i<profiles.at(0).size(); i++)
      {
        averageProfile.push_back(0.0);
      }

      // Average the right number of profiles

      for(int i=0; i<size*nTracts; i++)
      {
        for(unsigned int j=0; j<averageProfile.size(); ++j)
        {
          averageProfile.at(j) = averageProfile.at(j) + profiles.at(c).at(j);
        }
        c++;
      }

      // Divide by the number of profiles to get group average
      for(unsigned int i=0; i<averageProfile.size(); i++)
      {
        averageProfile.at(i) = averageProfile.at(i) / (size*nTracts);
      }

      groupProfiles.push_back(averageProfile);

      ++it;
    }

    return groupProfiles;
}
void QmitkTbssRoiAnalysisWidget::DoPlotFiberBundles(mitk::FiberBundleX *fib, mitk::Image* img,
                                                    mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, bool avg, int number)
{

  mitk::Geometry3D* currentGeometry = fib->GetGeometry();

  mitk::PlaneGeometry* startGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(startRoi->GetGeometry2D()) );
  mitk::PlaneGeometry* endGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(endRoi->GetGeometry2D()) );


  mitk::Point3D startCenter = startRoi->GetWorldControlPoint(0); //center Point of start roi
  mitk::Point3D endCenter = endRoi->GetWorldControlPoint(0); //center Point of end roi

  mitk::FiberBundleX::Pointer inStart = fib->ExtractFiberSubset(startRoi);
  mitk::FiberBundleX::Pointer inBoth = inStart->ExtractFiberSubset(endRoi);



  int num = inBoth->GetNumFibers();


  TractContainerType tracts;


  vtkSmartPointer<vtkPolyData> fiberPolyData = inBoth->GetFiberPolyData();
  vtkCellArray* lines = fiberPolyData->GetLines();
  lines->InitTraversal();



  // Now find out for each fiber which ROI is encountered first. If this is the startRoi, the direction is ok
  // Otherwise the plot should be in the reverse direction
  for( int fiberID( 0 ); fiberID < num; fiberID++ )
  {
    vtkIdType   numPointsInCell(0);
    vtkIdType*  pointsInCell(NULL);
    lines->GetNextCell ( numPointsInCell, pointsInCell );

    int startId = 0;
    int endId = 0;

    float minDistStart = std::numeric_limits<float>::max();
    float minDistEnd = std::numeric_limits<float>::max();



    for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++)
    {


      double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );

      mitk::Point3D point;
      point[0] = p[0];
      point[1] = p[1];
      point[2] = p[2];

      float distanceToStart = point.EuclideanDistanceTo(startCenter);
      float distanceToEnd = point.EuclideanDistanceTo(endCenter);

      if(distanceToStart < minDistStart)
      {
        minDistStart = distanceToStart;
        startId = pointInCellID;
      }

      if(distanceToEnd < minDistEnd)
      {
        minDistEnd = distanceToEnd;
        endId = pointInCellID;
      }



    }

    /* We found the start and end points of of the part that should be plottet for
       the current fiber. now we need to plot them. If the endId is smaller than the startId the plot order
       must be reversed*/

    TractType singleTract;
    PointType point;

    if(startId < endId)
    {

      // Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of
      double *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
      mitk::Vector3D p0;
      p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

      p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] );
      mitk::Vector3D p1;
      p1[0] = p[0];       p1[1] = p[1];       p1[2] = p[2];

      // Check if p and p2 are both on the same side of the plane
      mitk::Vector3D normal = startGeometry2D->GetNormal();

      mitk::Point3D pStart;
      pStart[0] = p0[0];      pStart[1] = p0[1];      pStart[2] = p0[2];

      mitk::Point3D pSecond;
      pSecond[0] = p1[0];      pSecond[1] = p1[1];      pSecond[2] = p1[2];

      bool startOnPositive = startGeometry2D->IsAbove(pStart);
      bool secondOnPositive = startGeometry2D->IsAbove(pSecond);


      mitk::Vector3D onPlane;
      onPlane[0] = startCenter[0];      onPlane[1] = startCenter[1];      onPlane[2] = startCenter[2];



      if(! (secondOnPositive ^ startOnPositive) )
      {
        /* startId and startId+1 lie on the same side of the plane, so we need
           need startId-1 to calculate the intersection with the planar figure*/
        p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
        p1[0] = p[0];        p1[1] = p[1];        p1[2] = p[2];
      }


      double d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
      mitk::Vector3D newPoint = (p0-p1);

      point[0] = d*newPoint[0] + p0[0];
      point[1] = d*newPoint[1] + p0[1];
      point[2] = d*newPoint[2] + p0[2];

      singleTract.push_back(point);

      if(! (secondOnPositive ^ startOnPositive) )
      {
        /* StartId and startId+1 lie on the same side of the plane
           so startId is also part of the ROI*/

        double *start = fiberPolyData->GetPoint( pointsInCell[startId] );
        point[0] = start[0]; point[1] = start[1]; point[2] = start[2];
        singleTract.push_back(point);
      }



      for( int pointInCellID( startId+1 ); pointInCellID < endId ; pointInCellID++)
      {
        // push back point
        double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
        point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
        singleTract.push_back( point );

      }

      /* endId must be included if endId and endId-1 lie on the same side of the
               plane defined by endRoi*/


      p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
      p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

      p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
      p1[0] = p[0];      p1[1] = p[1];      p1[2] = p[2];

      mitk::Point3D pLast;
      pLast[0] = p0[0];      pLast[1] = p0[1];      pLast[2] = p0[2];

      mitk::Point3D pBeforeLast;
      pBeforeLast[0] = p1[0];      pBeforeLast[1] = p1[1];      pBeforeLast[2] = p1[2];

      normal = endGeometry2D->GetNormal();
      bool lastOnPositive = endGeometry2D->IsAbove(pLast);
      bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);


      onPlane[0] = endCenter[0];
      onPlane[1] = endCenter[1];
      onPlane[2] = endCenter[2];

      if(! (lastOnPositive ^ secondLastOnPositive) )
      {
        /* endId and endId-1 lie on the same side of the plane, so we need
           need endId+1 to calculate the intersection with the planar figure.
           this should exist since we know that the fiber crosses the planar figure
           endId is also part of the tract and can be inserted here */

        p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
        point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
        singleTract.push_back( point );

        p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
      }

      d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );

      newPoint = (p0-p1);

      point[0] = d*newPoint[0] + p0[0];
      point[1] = d*newPoint[1] + p0[1];
      point[2] = d*newPoint[2] + p0[2];

      singleTract.push_back(point);



    }
    else{

      // Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of
      double *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
      mitk::Vector3D p0;
      p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

      p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
      mitk::Vector3D p1;
      p1[0] = p[0];       p1[1] = p[1];       p1[2] = p[2];

      // Check if p and p2 are both on the same side of the plane
      mitk::Vector3D normal = startGeometry2D->GetNormal();

      mitk::Point3D pStart;
      pStart[0] = p0[0];      pStart[1] = p0[1];      pStart[2] = p0[2];

      mitk::Point3D pSecond;
      pSecond[0] = p1[0];      pSecond[1] = p1[1];      pSecond[2] = p1[2];

      bool startOnPositive = startGeometry2D->IsAbove(pStart);
      bool secondOnPositive = startGeometry2D->IsAbove(pSecond);

      mitk::Vector3D onPlane;
      onPlane[0] = startCenter[0];      onPlane[1] = startCenter[1];      onPlane[2] = startCenter[2];


      if(! (secondOnPositive ^ startOnPositive) )
      {
        /* startId and startId+1 lie on the same side of the plane, so we need
           need startId-1 to calculate the intersection with the planar figure*/
        p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
        p1[0] = p[0];        p1[1] = p[1];        p1[2] = p[2];
      }


      double d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
      mitk::Vector3D newPoint = (p0-p1);


      point[0] = d*newPoint[0] + p0[0];
      point[1] = d*newPoint[1] + p0[1];
      point[2] = d*newPoint[2] + p0[2];


      singleTract.push_back(point);

      if(! (secondOnPositive ^ startOnPositive) )
      {
        /* StartId and startId+1 lie on the same side of the plane
           so startId is also part of the ROI*/

        double *start = fiberPolyData->GetPoint( pointsInCell[startId] );
        point[0] = start[0]; point[1] = start[1]; point[2] = start[2];
        singleTract.push_back(point);
      }



      for( int pointInCellID( startId-1 ); pointInCellID > endId ; pointInCellID--)
      {
        // push back point
        double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
        point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
        singleTract.push_back( point );

      }

      /* endId must be included if endId and endI+1 lie on the same side of the
               plane defined by endRoi*/


      p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
      p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

      p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
      p1[0] = p[0];      p1[1] = p[1];      p1[2] = p[2];

      mitk::Point3D pLast;
      pLast[0] = p0[0];      pLast[1] = p0[1];      pLast[2] = p0[2];

      mitk::Point3D pBeforeLast;
      pBeforeLast[0] = p1[0];      pBeforeLast[1] = p1[1];      pBeforeLast[2] = p1[2];

      bool lastOnPositive = endGeometry2D->IsAbove(pLast);
      bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);
      normal = endGeometry2D->GetNormal();



      onPlane[0] = endCenter[0];
      onPlane[1] = endCenter[1];
      onPlane[2] = endCenter[2];

      if(! (lastOnPositive ^ secondLastOnPositive) )
      {
        /* endId and endId+1 lie on the same side of the plane, so we need
           need endId-1 to calculate the intersection with the planar figure.
           this should exist since we know that the fiber crosses the planar figure
           endId is also part of the tract and can be inserted here */

        p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
        point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
        singleTract.push_back( point );

        p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
      }

      d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );

      newPoint = (p0-p1);

      point[0] = d*newPoint[0] + p0[0];
      point[1] = d*newPoint[1] + p0[1];
      point[2] = d*newPoint[2] + p0[2];

      singleTract.push_back(point);

    }


    tracts.push_back(singleTract);


  }


  //todo: Make number of samples selectable by user
  TractContainerType resampledTracts = ParameterizeTracts(tracts, number);

  // Now we have the resampled tracts. Next we should use these points to read out the values



  PlotFiberBundles(resampledTracts, img, avg);
  m_CurrentTracts = resampledTracts;
}