Example #1
0
    Interpolator1D::Interpolator1D(const Vector<double>& x,
            const Vector<double>& y,
            InterpolationType interp_type)
    : x_values(x),
    y_values(y),
    interpolation_type(interp_type) {

        // number of nodes
        unsigned int n = x_values.size();

        // calculate the spline coefficients according to the type
		  // of interpolation
        switch (interpolation_type) {

            case LINEAR:
                spline_coeffs = setupSplineLinear(x_values, y_values);
                break;
            case SPLINE_MONOTONE:
                spline_coeffs = setupSplineMonotoneSpline(x_values, y_values);
                break;
            default:
                throw "CurveInterpolator type not allowed";

        }

        // set up flat extrapolation for tail values by default.
        extrap_values.resize(2);
        extrap_values(0) = y_values(0);
        extrap_values(1) = y_values(n - 1);

    }
Example #2
0
void
LeastSquaresFitHistory::execute()
{
  if (_x_values.size() != _y_values.size())
    mooseError("In LeastSquresFitTimeHistory size of data in x_values and y_values must be equal");
  if (_x_values.size() == 0)
    mooseError("In LeastSquresFitTimeHistory size of data in x_values and y_values must be > 0");

  // Create a copy of _x_values that we can modify.
  std::vector<Real> x_values(_x_values.begin(), _x_values.end());
  std::vector<Real> y_values(_y_values.begin(), _y_values.end());

  for (MooseIndex(_x_values) i = 0; i < _x_values.size(); ++i)
  {
    x_values[i] = (x_values[i] + _x_shift) * _x_scale;
    y_values[i] = (y_values[i] + _y_shift) * _y_scale;
  }

  PolynomialFit pf(x_values, y_values, _order, true);
  pf.generate();

  std::vector<Real> coeffs = pf.getCoefficients();
  mooseAssert(coeffs.size() == _coeffs.size(),
              "Sizes of current coefficients and vector of coefficient vectors must match");
  for (MooseIndex(coeffs) i = 0; i < coeffs.size(); ++i)
    _coeffs[i]->push_back(coeffs[i]);

  _times->push_back(_t);
}
void FindCenterOfMassPosition2::exec()
{
  MatrixWorkspace_sptr inputWSWvl = getProperty("InputWorkspace");
  MatrixWorkspace_sptr inputWS;

  // Option to exclude beam area
  bool direct_beam = getProperty("DirectBeam");

  //TODO: Need an input for the X bin to use, assume 0 for now
  int specID = 0;
  // Initial center location
  double center_x = getProperty("CenterX");
  double center_y = getProperty("CenterY");
  const double tolerance = getProperty("Tolerance");
  // Iteration cutoff
  int max_iteration = 200;
  // Radius of the beam area, in pixels
  double beam_radius = getProperty("BeamRadius");

  // Get the number of monitors. We assume that all monitors are stored in the first spectra
  const int numSpec = static_cast<int>(inputWSWvl->getNumberHistograms());

  // Set up the progress reporting object
  Progress progress(this,0.0,1.0,max_iteration);

  EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWSWvl);
  if(inputEventWS)
  {
    std::vector<double> y_values(numSpec);
    std::vector<double> e_values(numSpec);

    PARALLEL_FOR_NO_WSP_CHECK()
    for (int i = 0; i < numSpec; i++)
    {
      double sum_i(0), err_i(0);
      progress.report("Integrating events");
      const EventList& el = inputEventWS->getEventList(i);
      el.integrate(0,0,true,sum_i,err_i);
      y_values[i] = sum_i;
      e_values[i] = err_i;
    }

    IAlgorithm_sptr algo = createChildAlgorithm("CreateWorkspace", 0.7, 1.0);
    algo->setProperty< std::vector<double> >("DataX", std::vector<double>(2,0.0) );
    algo->setProperty< std::vector<double> >("DataY", y_values );
    algo->setProperty< std::vector<double> >("DataE", e_values );
    algo->setProperty<int>("NSpec", numSpec );
    algo->execute();

    inputWS = algo->getProperty("OutputWorkspace");
    WorkspaceFactory::Instance().initializeFromParent(inputWSWvl, inputWS, false);
  }
  else
  {
Example #4
0
	/**
	* Interpolates the spline value for the a given abscissas "x"
	*/
	double Interpolator1D::operator()(double x) const {

		// This will be the returned value.
		// Initialize it to zero.
		double y = 0.0;

		if (x < x_values(0))
			y = extrap_values(0);
		else if (x == x_values(0))
			y = y_values(0);
		else if (x > x_values(x_values.size() - 1))
			y = extrap_values(1);
		else { // if it is within the bounds, interpolate with the polynomial.

			const double* itx = lower_bound(x_values.begin(), x_values.end(), x);
			itx--;

			const unsigned int index = itx - x_values.begin();

			//Important note!: spline values could be different from
			//node values because of discontinuity of the spline at the nodes.
			//When the spline is discontinuous, the function value is one half
			//the value from the left and the value from the right.

			if (x == x_values(index))
				y = y_values(index);
			else if (x == x_values(index + 1))
				y = y_values(index + 1);
			else
				y = calcSplineValue(index, 0, x);

		}

		return y;

    }
  // Processes the point cloud with OpenCV using the PCL cluster indices
  void processClusters( const std::vector<pcl::PointIndices> cluster_indices,
                        //                        const sensor_msgs::PointCloud2ConstPtr& pointcloud_msg,
                        const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr  cloud_transformed,
                        const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr& cloud_filtered,
                        const pcl::PointCloud<pcl::PointXYZRGB>&  cloud )
  {

    // -------------------------------------------------------------------------------------------------------
    // Convert image
    ROS_INFO_STREAM_NAMED("perception","Converting image to OpenCV format");

    try
    {
      sensor_msgs::ImagePtr image_msg(new sensor_msgs::Image);
      //      pcl::toROSMsg (*pointcloud_msg, *image_msg);
      pcl::toROSMsg (*cloud_transformed, *image_msg);
      cv_bridge::CvImagePtr input_bridge = cv_bridge::toCvCopy(image_msg, "rgb8");
      full_input_image = input_bridge->image;
    }
    catch (cv_bridge::Exception& ex)
    {
      ROS_ERROR_STREAM_NAMED("perception","[calibrate] Failed to convert image");
      return;
    }

    // -------------------------------------------------------------------------------------------------------
    // Process Image

    // Convert image to gray
    cv::cvtColor( full_input_image, full_input_image_gray, CV_BGR2GRAY );
    //cv::adaptiveThreshold( full_input_image, full_input_image_gray, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,5,10);

    // Blur image - reduce noise with a 3x3 kernel
    cv::blur( full_input_image_gray, full_input_image_gray, cv::Size(3,3) );

    ROS_INFO_STREAM_NAMED("perception","Finished coverting");

    // -------------------------------------------------------------------------------------------------------
    // Check OpenCV and PCL image height for errors
    int image_width = cloud.width;
    int image_height = cloud.height;
    ROS_DEBUG_STREAM( "PCL Image height " << image_height << " -- width " << image_width << "\n");
    int image_width_cv = full_input_image.size.p[1];
    int image_height_cv = full_input_image.size.p[0];
    ROS_DEBUG_STREAM( "OpenCV Image height " << image_height_cv << " -- width " << image_width_cv << "\n");

    if( image_width != image_width_cv || image_height != image_height_cv )
    {
      ROS_ERROR_STREAM_NAMED("perception","PCL and OpenCV image heights/widths do not match!");
      return;
    }

    // -------------------------------------------------------------------------------------------------------
    // GUI Stuff

    // First window
    const char* opencv_window = "Source";
    /*
      cv::namedWindow( opencv_window, CV_WINDOW_AUTOSIZE );
      cv::imshow( opencv_window, full_input_image_gray );
    */


    //    while(true)  // use this when we want to tweak the image
    {

      output_image = full_input_image.clone();

      // -------------------------------------------------------------------------------------------------------
      // Start processing clusters
      ROS_INFO_STREAM_NAMED("perception","Finding min/max in x/y axis");

      int top_image_overlay_x = 0; // tracks were to copyTo the mini images

      // for each cluster, see if it is a block
      for(size_t c = 0; c < cluster_indices.size(); ++c)
      {
        ROS_INFO_STREAM_NAMED("perception","\n\n");
        ROS_INFO_STREAM_NAMED("perception","On cluster " << c);

        // find the outer dimensions of the cluster
        double xmin = 0; double xmax = 0;
        double ymin = 0; double ymax = 0;

        // also remember each min & max's correponding other coordinate (not needed for z)
        double xminy = 0; double xmaxy = 0;
        double yminx = 0; double ymaxx = 0;

        // also remember their corresponding indice
        int xmini = 0; int xmaxi = 0;
        int ymini = 0; int ymaxi = 0;

        // loop through and find all min/max of x/y
        for(size_t i = 0; i < cluster_indices[c].indices.size(); i++)
        {
          int j = cluster_indices[c].indices[i];

          // Get RGB from point cloud
          pcl::PointXYZRGB p = cloud_transformed->points[j];

          double x = p.x;
          double y = p.y;

          if(i == 0) // initial values
          {
            xmin = xmax = x;
            ymin = ymax = y;
            xminy = xmaxy = y;
            yminx = ymaxx = x;
            xmini = xmaxi = ymini = ymaxi = j; // record the indice corresponding to the min/max
          }
          else
          {
            if( x < xmin )
            {
              xmin = x;
              xminy = y;
              xmini = j;
            }
            if( x > xmax )
            {
              xmax = x;
              xmaxy = y;
              xmaxi = j;
            }
            if( y < ymin )
            {
              ymin = y;
              yminx = x;
              ymini = j;
            }
            if( y > ymax )
            {
              ymax = y;
              ymaxx = x;
              ymaxi = j;
            }
          }
        }

        ROS_DEBUG_STREAM_NAMED("perception","Cluster size - xmin: " << xmin << " xmax: " << xmax << " ymin: " << ymin << " ymax: " << ymax);
        ROS_DEBUG_STREAM_NAMED("perception","Cluster size - xmini: " << xmini << " xmaxi: " << xmaxi << " ymini: " << ymini << " ymaxi: " << ymaxi);

        // ---------------------------------------------------------------------------------------------
        // Check if these dimensions make sense for the block size specified
        double xside = xmax-xmin;
        double yside = ymax-ymin;

        const double tol = 0.01; // 1 cm error tolerance

        // In order to be part of the block, xside and yside must be between
        // blocksize and blocksize*sqrt(2)
        if(xside > block_size-tol &&
           xside < block_size*sqrt(2)+tol &&
                   yside > block_size-tol &&
          yside < block_size*sqrt(2)+tol )
        {

          // -------------------------------------------------------------------------------------------------------
          // Get the four farthest corners of the block - use OpenCV only on the region identified by PCL

          // Get the pixel coordinates of the xmax and ymax indicies
          int px_xmax = 0; int py_xmax = 0;
          int px_ymax = 0; int py_ymax = 0;
          getXYCoordinates( xmaxi, image_height, image_width, px_xmax, py_xmax);
          getXYCoordinates( ymaxi, image_height, image_width, px_ymax, py_ymax);

          // Get the pixel coordinates of the xmin and ymin indicies
          int px_xmin = 0; int py_xmin = 0;
          int px_ymin = 0; int py_ymin = 0;
          getXYCoordinates( xmini, image_height, image_width, px_xmin, py_xmin);
          getXYCoordinates( ymini, image_height, image_width, px_ymin, py_ymin);

          ROS_DEBUG_STREAM_NAMED("perception","px_xmin " << px_xmin << " px_xmax: " << px_xmax << " py_ymin: " << py_ymin << " py_ymax: " << py_ymax );

          // -------------------------------------------------------------------------------------------------------
          // Change the frame of reference from the robot to the camera

          // Create an array of all the x value options
          const int x_values_a[] = {px_xmax, px_ymax, px_xmin, px_ymin};
          const int y_values_a[] = {py_xmax, py_ymax, py_xmin, py_ymin};
          // Turn it into a vector
          std::vector<int> x_values (x_values_a, x_values_a + sizeof(x_values_a) / sizeof(x_values_a[0]));
          std::vector<int> y_values (y_values_a, y_values_a + sizeof(y_values_a) / sizeof(y_values_a[0]));
          // Find the min
          int x1 = *std::min_element(x_values.begin(), x_values.end());
          int y1 = *std::min_element(y_values.begin(), y_values.end());
          // Find the max
          int x2 = *std::max_element(x_values.begin(), x_values.end());
          int y2 = *std::max_element(y_values.begin(), y_values.end());

          ROS_DEBUG_STREAM_NAMED("perception","x1: " << x1 << " y1: " << y1 << " x2: " << x2 << " y2: " << y2);

          // -------------------------------------------------------------------------------------------------------
          // Expand the ROI by a fudge factor, if possible
          const int FUDGE_FACTOR = 5; // pixels
          if( x1 > FUDGE_FACTOR)
            x1 -= FUDGE_FACTOR;
          if( y1 > FUDGE_FACTOR )
            y1 -= FUDGE_FACTOR;
          if( x2 < image_width - FUDGE_FACTOR )
            x2 += FUDGE_FACTOR;
          if( y2 < image_height - FUDGE_FACTOR )
            y2 += FUDGE_FACTOR;

          ROS_DEBUG_STREAM_NAMED("perception","After Fudge Factor - x1: " << x1 << " y1: " << y1 << " x2: " << x2 << " y2: " << y2);

          // -------------------------------------------------------------------------------------------------------
          // Create ROI parameters
          //        (x1,y1)----------------------
          //       |                            |
          //       |            ROI             |
          //       |                            |
          //       |_____________________(x2,y2)|

          // Create Region of Interest
          int roi_width = x2 - x1;
          int roi_height = y2 - y1;
          cv::Rect region_of_interest = cv::Rect( x1, y1, roi_width, roi_height );
          ROS_DEBUG_STREAM_NAMED("perception","ROI: x " << x1 << " -- y " << y1 << " -- height " << roi_height << " -- width " << roi_width );

          // -------------------------------------------------------------------------------------------------------
          // Find paramters of the block in pixel coordiantes
          int block_center_x = x1 + 0.5*roi_width;
          int block_center_y = y1 + 0.5*roi_height;
          int block_center_z = block_size / 2; // TODO: make this better
          const cv::Point block_center = cv::Point( block_center_x, block_center_y );

          // -------------------------------------------------------------------------------------------------------
          // Create a sub image of just the block
          cv::Point a1 = cv::Point(x1, y1);
          cv::Point a2 = cv::Point(x2, y2);
          cv::rectangle( output_image, a1, a2, cv::Scalar(0, 255, 255), 1, 8);

          // Crop image (doesn't actually copy the data)
          cropped_image = full_input_image_gray(region_of_interest);

          // -------------------------------------------------------------------------------------------------------
          // Detect edges using canny
          ROS_INFO_STREAM_NAMED("perception","Detecting edges using canny");

          // Find edges
          cv::Mat canny_output;
          cv::Canny( cropped_image, canny_output, canny_threshold, canny_threshold*2, 3 );

          // Get mini window stats
          const int mini_width = canny_output.size.p[1];
          const int mini_height = canny_output.size.p[0];
          const cv::Size mini_size = canny_output.size();
          const cv::Point mini_center = cv::Point( mini_width/2, mini_height/2 );

          // Find contours
          vector<vector<cv::Point> > contours;
          vector<cv::Vec4i> hierarchy;
          cv::findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
          ROS_INFO_STREAM_NAMED("perception","Contours");

          // Draw contours
          cv::Mat drawing = cv::Mat::zeros( mini_size, CV_8UC3 );
          ROS_INFO_STREAM_NAMED("perception","Drawing contours");

          // Find the largest contour for getting the angle
          double max_contour_length = 0;
          int max_contour_length_i;
          for( size_t i = 0; i< contours.size(); i++ )
          {
            double contour_length = cv::arcLength( contours[i], false );
            if( contour_length > max_contour_length )
            {
              max_contour_length = contour_length;
              max_contour_length_i = i;
            }
            //ROS_DEBUG_STREAM_NAMED("perception","Contour length = " << contour_length << " of index " << max_contour_length_i);


            cv::Scalar color = cv::Scalar( (30 + i*10) % 255, (30 + i*10) % 255, (30 + i*10) % 255);
            cv::drawContours( drawing, contours, (int)i, color, 1, 8, hierarchy, 0, cv::Point() );
            //drawContours( image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel, offset )

          }

          // -------------------------------------------------------------------------------------------------------
          // Copy largest contour to main image
          cv::Scalar color = cv::Scalar( 0, 255, 0 );
          cv::drawContours( output_image, contours, (int)max_contour_length_i, color, 1, 8, hierarchy, 0, a1 );
          //drawContours( image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel, offset )

          // -------------------------------------------------------------------------------------------------------
          // Copy largest contour to seperate image
          cv::Mat hough_input = cv::Mat::zeros( mini_size, CV_8UC1 );
          cv::Mat hough_input_color;
          cv::Scalar hough_color = cv::Scalar( 200 );
          cv::drawContours( hough_input, contours, (int)max_contour_length_i, hough_color, 1, 8, hierarchy, 0 );
          cv::cvtColor(hough_input, hough_input_color, CV_GRAY2BGR);

          // -------------------------------------------------------------------------------------------------------
          // Hough Transform
          cv::Mat hough_drawing = cv::Mat::zeros( mini_size, CV_8UC3 );
          std::vector<cv::Vec4i> lines;


          ROS_DEBUG_STREAM_NAMED("perception","hough_rho " << hough_rho << " hough_theta " << hough_theta <<
                                 " theta_converted " << (1/hough_theta)*CV_PI/180 << " hough_threshold " <<
                                 hough_threshold << " hough_minLineLength " << hough_minLineLength <<
                                 " hough_maxLineGap " << hough_maxLineGap );

          cv::HoughLinesP(hough_input, lines, hough_rho, (1/hough_theta)*CV_PI/180, hough_threshold, hough_minLineLength, hough_maxLineGap);

          ROS_WARN_STREAM_NAMED("perception","Found " << lines.size() << " lines");

          std::vector<double> line_angles;

          // Copy detected lines to the drawing image
          for( size_t i = 0; i < lines.size(); i++ )
          {
            cv::Vec4i line = lines[i];
            cv::line( hough_drawing, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]),
                      cv::Scalar(255,255,255), 1, CV_AA);

            // Error check
            if(line[3] - line[1] == 0 && line[2] - line[0] == 0)
            {
              ROS_ERROR_STREAM_NAMED("perception","Line is actually two points at the origin, unable to calculate. TODO: handle better?");
              continue;
            }

            // Find angle
            double line_angle = atan2(line[3] - line[1], line[2] - line[0]); //in radian, degrees: * 180.0 / CV_PI;
            // Reverse angle direction if negative
            if( line_angle < 0 )
            {
              line_angle += CV_PI;
            }
            line_angles.push_back(line_angle);
            ROS_DEBUG_STREAM_NAMED("perception","Hough Line angle: " << line_angle * 180.0 / CV_PI;);
          }

          double block_angle = 0; // the overall result of the block's angle

          // Everything is based on the first angle
          if( line_angles.size() == 0 ) // make sure we have at least 1 angle
          {
            ROS_ERROR_STREAM_NAMED("perception","No lines were found for this cluster, unable to calculate block angle");
          }
          else
          {
            calculateBlockAngle( line_angles, block_angle );
          }

          // -------------------------------------------------------------------------------------------------------
          // Draw chosen angle
          ROS_INFO_STREAM_NAMED("perception","Using block angle " << block_angle*180.0/CV_PI);

          // Draw chosen angle on mini image
          cv::Mat angle_drawing = cv::Mat::zeros( mini_size, CV_8UC3 );
          int line_length = 0.5*double(mini_width); // have the line go 1/4 across the screen
          int new_x = mini_center.x + line_length*cos( block_angle );
          int new_y = mini_center.y + line_length*sin( block_angle );
          ROS_INFO_STREAM("Origin (" << mini_center.x << "," << mini_center.y << ") New (" << new_x << "," << new_y <<
                          ") length " << line_length << " angle " << block_angle <<
                          " mini width " << mini_width << " mini height " << mini_height);
          cv::Point angle_point = cv::Point(new_x, new_y);
          cv::line( angle_drawing, mini_center, angle_point, cv::Scalar(255,255,255), 1, CV_AA);

          // Draw chosen angle on contours image
          cv::line( hough_drawing, mini_center, angle_point, cv::Scalar(255,0, 255), 1, CV_AA);

          // Draw chosen angle on main image
          line_length = 0.75 * double(mini_width); // have the line go 1/2 across the box
          new_x = block_center_x + line_length*cos( block_angle );
          new_y = block_center_y + line_length*sin( block_angle );
          ROS_INFO_STREAM_NAMED("perception",block_center_x << ", " << block_center_y << ", " << new_x << ", " << new_y);
          angle_point = cv::Point(new_x, new_y);
          cv::line( output_image, block_center, angle_point, cv::Scalar(255,0,255), 2, CV_AA);


          // -------------------------------------------------------------------------------------------------------
          // Get world coordinates

          // Find the block's center point
          double world_x1 = xmin+(xside)/2.0;
          double world_y1 = ymin+(yside)/2.0;
          double world_z1 = table_height + block_size / 2;

          // Convert pixel coordiantes back to world coordinates
          double world_x2 = cloud_transformed->at(new_x, new_y).x;
          double world_y2 = cloud_transformed->at(new_x, new_y).y;
          double world_z2 = world_z1; // is this even necessary?

          // Get angle from two world coordinates...
          double world_theta = abs( atan2(world_y2 - world_y1, world_x2 - world_x1) );

          // Attempt to make all angles point in same direction
          makeAnglesUniform( world_theta );

          // -------------------------------------------------------------------------------------------------------
          // GUI Stuff

          // Copy the cluster image to the main image in the top left corner
          if( top_image_overlay_x + mini_width < image_width )
          {
            const int common_height = 42;
            cv::Rect small_roi_row0 = cv::Rect(top_image_overlay_x, common_height*0, mini_width, mini_height);
            cv::Rect small_roi_row1 = cv::Rect(top_image_overlay_x, common_height*1, mini_width, mini_height);
            cv::Rect small_roi_row2 = cv::Rect(top_image_overlay_x, common_height*2, mini_width, mini_height);
            cv::Rect small_roi_row3 = cv::Rect(top_image_overlay_x, common_height*3, mini_width, mini_height);

            drawing.copyTo(              output_image(small_roi_row0) );
            hough_input_color.copyTo(    output_image(small_roi_row1) );
            hough_drawing.copyTo(        output_image(small_roi_row2) );
            angle_drawing.copyTo(        output_image(small_roi_row3) );

            top_image_overlay_x += mini_width;
          }

          // figure out the position and the orientation of the block
          //double angle = atan(block_size/((xside+yside)/2));
          //double angle = atan( (xmaxy - xminy) / (xmax - xmin ) );
          // Then add it to our set
          //addBlock( xmin+(xside)/2.0, ymin+(yside)/2.0, zmax - block_size/2.0, angle);
          //ROS_INFO_STREAM_NAMED("perception","FOUND -> xside: " << xside << " yside: " << yside << " angle: " << block_angle);


          addBlock( world_x1, world_y1, world_z1, world_theta );
          //addBlock( block_center_x, block_center_y, block_center_z, block_angle);
        }
        else
        {
Example #6
0
RcppExport SEXP treePhaser(SEXP Rsignal, SEXP RkeyFlow, SEXP RflowCycle,
                           SEXP Rcf, SEXP Rie, SEXP Rdr, SEXP Rbasecaller, SEXP RdiagonalStates,
                           SEXP RmodelFile, SEXP RmodelThreshold, SEXP Rxval, SEXP Ryval)
{
  SEXP ret = R_NilValue;
  char *exceptionMesg = NULL;

  try {
    Rcpp::NumericMatrix      signal(Rsignal);
    Rcpp::IntegerVector      keyFlow(RkeyFlow);
    string flowCycle       = Rcpp::as<string>(RflowCycle);
    Rcpp::NumericVector      cf_vec(Rcf);
    Rcpp::NumericVector      ie_vec(Rie);
    Rcpp::NumericVector      dr_vec(Rdr);
    string basecaller      = Rcpp::as<string>(Rbasecaller);
    unsigned int diagonalStates = Rcpp::as<int>(RdiagonalStates);

    // Recalibration Variables
    string model_file      = Rcpp::as<string>(RmodelFile);
    int model_threshold    = Rcpp::as<int>(RmodelThreshold);
    Rcpp::IntegerVector      x_values(Rxval);
    Rcpp::IntegerVector      y_values(Ryval);
    RecalibrationModel       recalModel;
    if (model_file.length() > 0) {
      recalModel.InitializeModel(model_file, model_threshold);
    }


    ion::FlowOrder flow_order(flowCycle, flowCycle.length());
    unsigned int nFlow = signal.cols();
    unsigned int nRead = signal.rows();

    if(basecaller != "treephaser-swan" && basecaller != "treephaser-solve" && basecaller != "dp-treephaser" && basecaller != "treephaser-adaptive") {
      std::string exception = "base value for basecaller supplied: " + basecaller;
      exceptionMesg = strdup(exception.c_str());
    } else if (flowCycle.length() < nFlow) {
      std::string exception = "Flow cycle is shorter than number of flows to solve";
      exceptionMesg = strdup(exception.c_str());
    } else {

      // Prepare objects for holding and passing back results
      Rcpp::NumericMatrix        predicted_out(nRead,nFlow);
      Rcpp::NumericMatrix        residual_out(nRead,nFlow);
      Rcpp::NumericMatrix        norm_additive_out(nRead,nFlow);
      Rcpp::NumericMatrix        norm_multipl_out(nRead,nFlow);
      std::vector< std::string> seq_out(nRead);

      // Set up key flow vector
      int nKeyFlow = keyFlow.size(); 
      vector <int> keyVec(nKeyFlow);
      for(int iFlow=0; iFlow < nKeyFlow; iFlow++)
        keyVec[iFlow] = keyFlow(iFlow);

      // Iterate over all reads
      vector <float> sigVec(nFlow);
      BasecallerRead read;
      DPTreephaser dpTreephaser(flow_order);
      dpTreephaser.SetStateProgression((diagonalStates>0));

      // In contrast to pipeline, we always use droop here.
      // To have the same behavior of treephaser-swan as in the pipeline, supply dr=0
      bool per_read_phasing = true;
      if (cf_vec.size() == 1) {
        per_read_phasing = false;
        dpTreephaser.SetModelParameters((double)cf_vec(0), (double)ie_vec(0), (double)dr_vec(0));
      }
 
      // Main loop iterating over reads and solving them
      for(unsigned int iRead=0; iRead < nRead; iRead++) {

        // Set phasing parameters for this read
        if (per_read_phasing)
          dpTreephaser.SetModelParameters((double)cf_vec(iRead), (double)ie_vec(iRead), (double)dr_vec(iRead));
        // And load recalibration model
        if (recalModel.is_enabled()) {
          int my_x = (int)x_values(iRead);
          int my_y = (int)y_values(iRead);
          const vector<vector<vector<float> > > * aPtr = 0;
          const vector<vector<vector<float> > > * bPtr = 0;
          aPtr = recalModel.getAs(my_x, my_y);
          bPtr = recalModel.getBs(my_x, my_y);
          if (aPtr == 0 or bPtr == 0) {
            cout << "Error finding a recalibration model for x: " << x_values(iRead) << " y: " << y_values(iRead);
            cout << endl;
          }
          dpTreephaser.SetAsBs(aPtr, bPtr);
        }

        for(unsigned int iFlow=0; iFlow < nFlow; iFlow++)
          sigVec[iFlow] = (float) signal(iRead,iFlow);
        
        // Interface to just solve without any normalization
        if (basecaller == "treephaser-solve") { // Interface to just solve without any normalization
          read.SetData(sigVec, (int)nFlow);
        } 
        else {
          read.SetDataAndKeyNormalize(&(sigVec[0]), (int)nFlow, &(keyVec[0]), nKeyFlow-1);
        }
          
        // Execute the iterative solving-normalization routine
        if (basecaller == "dp-treephaser") {
          dpTreephaser.NormalizeAndSolve_GainNorm(read, nFlow);
        }
        else if (basecaller == "treephaser-solve") {
          dpTreephaser.Solve(read, nFlow);
        }
        else if (basecaller == "treephaser-adaptive") {
          dpTreephaser.NormalizeAndSolve_Adaptive(read, nFlow); // Adaptive normalization
        }
        else {
          dpTreephaser.NormalizeAndSolve_SWnorm(read, nFlow); // sliding window adaptive normalization
        }

        seq_out[iRead].assign(read.sequence.begin(), read.sequence.end());
        for(unsigned int iFlow=0; iFlow < nFlow; iFlow++) {
          predicted_out(iRead,iFlow)     = (double) read.prediction[iFlow];
          residual_out(iRead,iFlow)      = (double) read.normalized_measurements[iFlow] - read.prediction[iFlow];
          norm_multipl_out(iRead,iFlow)  = (double) read.multiplicative_correction.at(iFlow);
          norm_additive_out(iRead,iFlow) = (double) read.additive_correction.at(iFlow);
        }
      }

      // Store results
      ret = Rcpp::List::create(Rcpp::Named("seq")       = seq_out,
                               Rcpp::Named("predicted") = predicted_out,
                               Rcpp::Named("residual")  = residual_out,
                               Rcpp::Named("norm_additive") = norm_additive_out,
                               Rcpp::Named("norm_multipl")  = norm_multipl_out);
    }
  } catch(std::exception& ex) {
    forward_exception_to_r(ex);
  } catch(...) {
    ::Rf_error("c++ exception (unknown reason)");
  }
    
  if(exceptionMesg != NULL)
    Rf_error(exceptionMesg);

  return ret;
}
Example #7
0
RcppExport SEXP treePhaserSim(SEXP Rsequence, SEXP RflowCycle, SEXP Rcf, SEXP Rie, SEXP Rdr,
                              SEXP Rmaxflows, SEXP RgetStates, SEXP RdiagonalStates,
                              SEXP RmodelFile, SEXP RmodelThreshold, SEXP Rxval, SEXP Ryval)
{
  SEXP ret = R_NilValue;
  char *exceptionMesg = NULL;

  try {

    Rcpp::StringVector            sequences(Rsequence);
    string flowCycle            = Rcpp::as<string>(RflowCycle);
    Rcpp::NumericMatrix           cf_vec(Rcf);
    Rcpp::NumericMatrix           ie_vec(Rie);
    Rcpp::NumericMatrix           dr_vec(Rdr);
    unsigned int max_flows      = Rcpp::as<int>(Rmaxflows);
    unsigned int get_states     = Rcpp::as<int>(RgetStates);
    unsigned int diagonalStates = Rcpp::as<int>(RdiagonalStates);

    // Recalibration Variables
    string model_file      = Rcpp::as<string>(RmodelFile);
    int model_threshold    = Rcpp::as<int>(RmodelThreshold);
    Rcpp::IntegerVector      x_values(Rxval);
    Rcpp::IntegerVector      y_values(Ryval);
    RecalibrationModel       recalModel;
    if (model_file.length() > 0) {
      recalModel.InitializeModel(model_file, model_threshold);
    }

    ion::FlowOrder flow_order(flowCycle, flowCycle.length());
    unsigned int nFlow = flow_order.num_flows();
    unsigned int nRead = sequences.size();
    max_flows = min(max_flows, nFlow);

    // Prepare objects for holding and passing back results
    Rcpp::NumericMatrix       predicted_out(nRead,nFlow);
    vector<vector<float> >    query_states;
    vector<int>               hp_lengths;

    // Iterate over all sequences
    BasecallerRead read;
    DPTreephaser dpTreephaser(flow_order);
    bool per_read_phasing = true;
    if (cf_vec.ncol() == 1) {
      per_read_phasing = false;
      dpTreephaser.SetModelParameters((double)cf_vec(0,0), (double)ie_vec(0,0), (double)dr_vec(0,0));
    }
    dpTreephaser.SetStateProgression((diagonalStates>0));
    unsigned int max_length = (2*flow_order.num_flows());

    for(unsigned int iRead=0; iRead<nRead; iRead++) {

      string mySequence = Rcpp::as<std::string>(sequences(iRead));
      read.sequence.clear();
      read.sequence.reserve(2*flow_order.num_flows());
      for(unsigned int iBase=0; iBase<mySequence.length() and iBase<max_length; ++iBase){
        read.sequence.push_back(mySequence.at(iBase));
      }
      // Set phasing parameters for this read
      if (per_read_phasing)
        dpTreephaser.SetModelParameters((double)cf_vec(0,iRead), (double)ie_vec(0,iRead), (double)dr_vec(0,iRead));

      // If you bothered specifying a recalibration model you probably want its effect on the predictions...
      if (recalModel.is_enabled()) {
        int my_x = (int)x_values(iRead);
        int my_y = (int)y_values(iRead);
        const vector<vector<vector<float> > > * aPtr = 0;
        const vector<vector<vector<float> > > * bPtr = 0;
        aPtr = recalModel.getAs(my_x, my_y);
        bPtr = recalModel.getBs(my_x, my_y);
        if (aPtr == 0 or bPtr == 0) {
          cout << "Error finding a recalibration model for x: " << x_values(iRead) << " y: " << y_values(iRead);
          cout << endl;
        }
        dpTreephaser.SetAsBs(aPtr, bPtr);
      }

      if (nRead == 1 and get_states > 0)
        dpTreephaser.QueryAllStates(read, query_states, hp_lengths, max_flows);
      else
        dpTreephaser.Simulate(read, max_flows);

      for(unsigned int iFlow=0; iFlow<nFlow and iFlow<max_flows; ++iFlow){
		predicted_out(iRead,iFlow) = (double) read.prediction.at(iFlow);
      }
    }

    // Store results
    if (nRead == 1 and get_states > 0) {
      Rcpp::NumericMatrix        states(hp_lengths.size(), nFlow);
      Rcpp::NumericVector        HPlengths(hp_lengths.size());
      for (unsigned int iHP=0; iHP<hp_lengths.size(); iHP++){
        HPlengths(iHP) = (double)hp_lengths[iHP];
        for (unsigned int iFlow=0; iFlow<nFlow; iFlow++)
          states(iHP, iFlow) = (double)query_states.at(iHP).at(iFlow);
      }
      ret = Rcpp::List::create(Rcpp::Named("sig")  = predicted_out,
                               Rcpp::Named("states")  = states,
                               Rcpp::Named("HPlengths")  = HPlengths);
    } else {
      ret = Rcpp::List::create(Rcpp::Named("sig")  = predicted_out);
    }

  } catch(std::exception& ex) {
    forward_exception_to_r(ex);
  } catch(...) {
    ::Rf_error("c++ exception (unknown reason)");
  }

  if(exceptionMesg != NULL)
    Rf_error(exceptionMesg);

  return ret;
}