Example #1
0
RcppExport SEXP treePhaser(SEXP Rsignal, SEXP RkeyFlow, SEXP RflowCycle, SEXP Rcf, SEXP Rie, SEXP Rdr, SEXP Rbasecaller)
{
  SEXP ret = R_NilValue;
  char *exceptionMesg = NULL;

  try {
    RcppMatrix<double>   signal(Rsignal);
    RcppVector<int>      keyFlow(RkeyFlow);
    string flowCycle   = Rcpp::as<string>(RflowCycle);
    double cf          = Rcpp::as<double>(Rcf);
    double ie          = Rcpp::as<double>(Rie);
    double dr          = Rcpp::as<double>(Rdr);
    string basecaller  = Rcpp::as<string>(Rbasecaller);
  
    unsigned int nFlow = signal.cols();
    unsigned int nRead = signal.rows();

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

      // Prepare objects for holding and passing back results
      RcppMatrix<double>        predicted_out(nRead,nFlow);
      RcppMatrix<double>        residual_out(nRead,nFlow);
      RcppMatrix<int>           hpFlow_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);
      string result;
      for(unsigned int iRead=0; iRead < nRead; iRead++) {
        for(unsigned int iFlow=0; iFlow < nFlow; iFlow++)
          sigVec[iFlow] = (float) signal(iRead,iFlow);
        BasecallerRead read;
        read.SetDataAndKeyNormalize(&(sigVec[0]), (int)nFlow, &(keyVec[0]), nKeyFlow-1);
        DPTreephaser dpTreephaser(flowCycle.c_str(), flowCycle.length(), 8);
        if (basecaller == "dp-treephaser")
          dpTreephaser.SetModelParameters(cf, ie, dr);
        else
          dpTreephaser.SetModelParameters(cf, ie, 0); // Adaptive normalization
          
        // Execute the iterative solving-normalization routine
        if (basecaller == "dp-treephaser")
          dpTreephaser.NormalizeAndSolve4(read, nFlow);
        else if (basecaller == "treephaser-adaptive")
          dpTreephaser.NormalizeAndSolve3(read, nFlow); // Adaptive normalization
        else
          dpTreephaser.NormalizeAndSolve5(read, nFlow); // sliding window adaptive normalization

        read.flowToString(flowCycle,seq_out[iRead]);
        for(unsigned int iFlow=0; iFlow < nFlow; iFlow++) {
          predicted_out(iRead,iFlow) = (double) read.prediction[iFlow];
          residual_out(iRead,iFlow)  = (double) read.normalizedMeasurements[iFlow] - read.prediction[iFlow];
          hpFlow_out(iRead,iFlow)    = (int)    read.solution[iFlow];
        }

        // Store results
        RcppResultSet rs;
        rs.add("seq",        seq_out);
        rs.add("predicted",  predicted_out);
        rs.add("residual",   residual_out);
        rs.add("hpFlow",     hpFlow_out);

        ret = rs.getReturnList();
      }
    }
  } catch(std::exception& ex) {
    exceptionMesg = copyMessageToR(ex.what());
  } catch(...) {
    exceptionMesg = copyMessageToR("unknown reason");
  }
    
  if(exceptionMesg != NULL)
    Rf_error(exceptionMesg);

  return ret;
}
Example #2
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 #3
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;
}
Example #4
0
RcppExport SEXP DPPhaseSim(SEXP Rsequence, SEXP RflowCycle, SEXP Rcf, SEXP Rie, SEXP Rdr,
                           SEXP Rmaxflows, SEXP RgetStates, SEXP RnucContamination)
{
  SEXP ret = R_NilValue;
  char *exceptionMesg = NULL;

  try {

    Rcpp::StringVector        sequences(Rsequence);
    string flowCycle        = Rcpp::as<string>(RflowCycle);
    Rcpp::NumericMatrix       cf_mat(Rcf);
    Rcpp::NumericMatrix       ie_mat(Rie);
    Rcpp::NumericMatrix       dr_mat(Rdr);
    Rcpp::NumericMatrix       nuc_contamination(RnucContamination);
    unsigned int max_flows  = Rcpp::as<int>(Rmaxflows);
    unsigned int get_states = Rcpp::as<int>(RgetStates);

    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);

    vector<vector<double> >    nuc_availbality;
    nuc_availbality.resize(nuc_contamination.nrow());
    for (unsigned int iFlowNuc=0; iFlowNuc < nuc_availbality.size(); iFlowNuc++){
      nuc_availbality.at(iFlowNuc).resize(nuc_contamination.ncol());
      for (unsigned int iNuc=0; iNuc < nuc_availbality.at(iFlowNuc).size(); iNuc++){
        nuc_availbality.at(iFlowNuc).at(iNuc) = nuc_contamination(iFlowNuc, iNuc);
      }
    }

    // Prepare objects for holding and passing back results
    Rcpp::NumericMatrix       predicted_out(nRead,nFlow);
    Rcpp::StringVector        seq_out(nRead);


    // Set Phasing Model
    DPPhaseSimulator PhaseSimulator(flow_order);
    PhaseSimulator.UpdateNucAvailability(nuc_availbality);

    bool per_read_phasing = true;
    if (cf_mat.nrow() == 1 and cf_mat.ncol() == 1) {
      per_read_phasing = false;
      cout << "DPPhaseSim: Single Phase Parameter set detected." << endl; // XXX
      PhaseSimulator.SetPhasingParameters_Basic((double)cf_mat(0,0), (double)ie_mat(0,0), (double)dr_mat(0,0));
    } else if (cf_mat.nrow() == (int)nFlow and cf_mat.ncol() == (int)nFlow) {
    	cout << "DPPhaseSim: Full Phase Parameter set detected." << endl; // XXX
      per_read_phasing = false;
      vector<vector<double> > cf(nFlow);
      vector<vector<double> > ie(nFlow);
      vector<vector<double> > dr(nFlow);
      for (unsigned int iFlowNuc=0; iFlowNuc < nFlow; iFlowNuc++){
        cf.at(iFlowNuc).resize(nFlow);
        ie.at(iFlowNuc).resize(nFlow);
        dr.at(iFlowNuc).resize(nFlow);
        for (unsigned int iFlow=0; iFlow < nFlow; iFlow++){
          cf.at(iFlowNuc).at(iFlow) = cf_mat(iFlowNuc, iFlow);
          ie.at(iFlowNuc).at(iFlow) = ie_mat(iFlowNuc, iFlow);
          dr.at(iFlowNuc).at(iFlow) = dr_mat(iFlowNuc, iFlow);
        }
      }
      PhaseSimulator.SetPhasingParameters_Full(cf, ie, dr);
    }
    else
      cout << "DPPhaseSim: Per Read Phase Parameter set detected." << endl; //XXX


    // --- Iterate over all sequences

    string         my_sequence, sim_sequence;
    vector<float>  my_prediction;

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

      if (per_read_phasing)
        PhaseSimulator.SetPhasingParameters_Basic((double)cf_mat(0,iRead), (double)ie_mat(0,iRead), (double)dr_mat(0,iRead));

      my_sequence = Rcpp::as<std::string>(sequences(iRead));
      PhaseSimulator.Simulate(my_sequence, my_prediction, max_flows);

      PhaseSimulator.GetSimSequence(sim_sequence); // Simulated sequence might be shorter than input sequence.
      seq_out(iRead) = sim_sequence;
      for(unsigned int iFlow=0; iFlow<nFlow and iFlow<max_flows; ++iFlow) {
		predicted_out(iRead,iFlow) = (double) my_prediction.at(iFlow);
      }
      //cout << "--- DPPhaseSim: Done simulating read "<< iRead << " of " << nRead << endl; // XXX
    }

    // --- Store results
    if (nRead == 1 and get_states > 0) {

      vector<vector<float> >    query_states;
      vector<int>               hp_lengths;
      PhaseSimulator.GetStates(query_states, hp_lengths);

      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("seq")       = seq_out,
                               Rcpp::Named("states")    = states,
                               Rcpp::Named("HPlengths") = HPlengths);
    } else {
      ret = Rcpp::List::create(Rcpp::Named("sig")  = predicted_out,
                               Rcpp::Named("seq")  = seq_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 #5
0
RcppExport SEXP phaseSolve(SEXP Rsignal, SEXP RflowCycle, SEXP RnucConc, SEXP Rcf, SEXP Rie, SEXP Rdr, SEXP RhpScale, SEXP RdroopType, SEXP RmaxAdv, SEXP RnIterations, SEXP RresidualScale, SEXP RresidualScaleMinFlow, SEXP RresidualScaleMaxFlow, SEXP RextraTaps, SEXP RdebugBaseCall)
{
    SEXP ret = R_NilValue;
    char *exceptionMesg = NULL;

    try {
        Rcpp::NumericMatrix signal(Rsignal);
        string flowCycle         = Rcpp::as<string>(RflowCycle);
        Rcpp::NumericMatrix cc(RnucConc);
        Rcpp::NumericVector cf(Rcf);
        Rcpp::NumericVector ie(Rie);
        Rcpp::NumericVector dr(Rdr);
        Rcpp::NumericVector hpScale(RhpScale);
        string drType                     = Rcpp::as<string>(RdroopType);
        unsigned int maxAdv               = (unsigned int) Rcpp::as<int>(RmaxAdv);
        unsigned int nIterations          = (unsigned int) Rcpp::as<int>(RnIterations);
        unsigned int extraTaps            = (unsigned int) Rcpp::as<int>(RextraTaps);
        bool residualScale                = Rcpp::as<bool>(RresidualScale);
        int residualScaleMinFlow          = Rcpp::as<int>(RresidualScaleMinFlow);
        int residualScaleMaxFlow          = Rcpp::as<int>(RresidualScaleMaxFlow);
        bool debugBaseCall                = Rcpp::as<bool>(RdebugBaseCall);

        unsigned int nFlow = signal.cols();
        unsigned int nRead = signal.rows();

        DroopType droopType;
        bool badDroopType = false;
        if(drType == "ONLY_WHEN_INCORPORATING") {
            droopType = ONLY_WHEN_INCORPORATING;
        } else if(drType == "EVERY_FLOW") {
            droopType = EVERY_FLOW;
        } else {
            badDroopType = true;
        }

        if(badDroopType) {
            std::string exception = "bad droop type supplied\n";
            exceptionMesg = strdup(exception.c_str());
        } else if(cc.rows() != (int) N_NUCLEOTIDES) {
            std::string exception = "concentration matrix should have 4 rows\n";
            exceptionMesg = strdup(exception.c_str());
        } else if(cc.cols() != (int) N_NUCLEOTIDES) {
            std::string exception = "concentration matrix should have 4 columns\n";
            exceptionMesg = strdup(exception.c_str());
        } else {
            // recast cf, ie, dr, hpScale
            weight_vec_t cfMod(cf.size());
            for(int i=0; i<cf.size(); i++)
                cfMod[i] = cf(i);
            weight_vec_t ieMod(ie.size());
            for(int i=0; i<ie.size(); i++)
                ieMod[i] = ie(i);
            weight_vec_t drMod(dr.size());
            for(int i=0; i<dr.size(); i++)
                drMod[i] = dr(i);
            weight_vec_t hpScaleMod(hpScale.size());
            for(int i=0; i<hpScale.size(); i++)
                hpScaleMod[i] = hpScale(i);

            // recast nuc concentration
            vector<weight_vec_t> ccMod(cc.rows());
            for(int iRow=0; iRow < cc.rows(); iRow++) {
                ccMod[iRow].resize(cc.cols());
                for(unsigned int iCol=0; iCol < N_NUCLEOTIDES; iCol++)
                    ccMod[iRow][iCol] = cc(iRow,iCol);
            }

            // Other recasts
            hpLen_t maxAdvMod = (hpLen_t) maxAdv;

            // Prepare objects for holding and passing back results
            Rcpp::NumericMatrix        predicted_out(nRead,nFlow);
            Rcpp::NumericMatrix        residual_out(nRead,nFlow);
            Rcpp::IntegerMatrix        hpFlow_out(nRead,nFlow);
            std::vector< std::string>  seq_out(nRead);
            Rcpp::NumericMatrix        multiplier_out(nRead,1+nIterations);

            // Iterate over all reads
            weight_vec_t sigMod(nFlow);
            string result;
            for(unsigned int iRead=0; iRead < nRead; iRead++) {
                for(unsigned int iFlow=0; iFlow < nFlow; iFlow++)
                    sigMod[iFlow] = (weight_t) signal(iRead,iFlow);

                PhaseSolve p;
                p.SetResidualScale(residualScale);
                if(residualScaleMinFlow >= 0)
                    p.SetResidualScaleMinFlow((unsigned int) residualScaleMinFlow);
                if(residualScaleMaxFlow >= 0)
                    p.SetResidualScaleMaxFlow((unsigned int) residualScaleMaxFlow);
                p.setExtraTaps(extraTaps);
                p.setHpScale(hpScaleMod);
                p.setPhaseParam(flowCycle,maxAdvMod,ccMod,cfMod,ieMod,drMod,droopType);
                p.GreedyBaseCall(sigMod, nIterations, debugBaseCall);
                p.getSeq(result);
                seq_out[iRead] = result;
                weight_vec_t & predicted = p.GetPredictedSignal();
                weight_vec_t & residual  = p.GetResidualSignal();
                hpLen_vec_t &  hpFlow    = p.GetPredictedHpFlow();
                for(unsigned int iFlow=0; iFlow < nFlow; iFlow++) {
                    predicted_out(iRead,iFlow) = (double) predicted[iFlow];
                    residual_out(iRead,iFlow)  = (double) residual[iFlow];
                    hpFlow_out(iRead,iFlow)    = (int)    hpFlow[iFlow];
                }
                if(residualScale) {
                    weight_vec_t & multiplier  = p.GetMultiplier();
                    // We re-order these so the last multiplier comes first.  This is for convenience
                    // as it allows us grab the first col of the matrix as the last multiplier applied
                    // even if each read ended up taking different numbers of iterations.
                    unsigned int i1,i2;
                    for(i1=0,i2=multiplier.size()-1; i1 < multiplier.size(); i1++,i2--) {
                        multiplier_out(iRead,i1) = (double) multiplier[i2];
                    }
                    // If the read took fewer than all available iterations, pad with zero
                    for(; i1 <= nIterations; i1++) {
                        multiplier_out(iRead,i1) = 0;
                    }
                }

            }

            // Store results
            std::map<std::string,SEXP> map;
            map["seq"]          = Rcpp::wrap( seq_out );
            map["predicted"]    = Rcpp::wrap( predicted_out );
            map["residual"]     = Rcpp::wrap( residual_out );
            map["hpFlow"]       = Rcpp::wrap( hpFlow_out );
            if(residualScale)
                map["multiplier"] = Rcpp::wrap( multiplier_out );

            ret = Rcpp::wrap( map );
        }
    } catch(std::exception& ex) {
        forward_exception_to_r(ex);
    } catch(...) {
        ::Rf_error("c++ exception (unknown reason)");
    }

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

    return ret;
}