/** Calculate Chi^2 of the a function with all parameters are fixed
    */
  double RefinePowderInstrumentParameters2::calculateFunctionError(IFunction_sptr function,
                                                                   Workspace2D_sptr dataws, int wsindex)
  {
    // 1. Record the fitting information
    vector<string> parnames = function->getParameterNames();
    vector<bool> vecFix(parnames.size(), false);

    for (size_t i = 0; i < parnames.size(); ++i)
    {
      bool fixed = function->isFixed(i);
      vecFix[i] = fixed;
      if (!fixed)
        function->fix(i);
    }

    // 2. Fit with zero iteration
    double chi2;
    string fitstatus;
    doFitFunction(function, dataws, wsindex, "Levenberg-MarquardtMD", 0, chi2, fitstatus);

    // 3. Restore the fit/fix setup
    for (size_t i = 0; i < parnames.size(); ++i)
    {
      if (!vecFix[i])
        function->unfix(i);
    }

    return chi2;
  }
  /** Set parameter fitting setup (boundary, fix or unfix) to function from Parameter map
   */
  void RefinePowderInstrumentParameters2::setFunctionParameterFitSetups(IFunction_sptr function,
                                                                        map<string, Parameter> params)
  {
    // 1. Prepare
    vector<string> funparamnames = m_positionFunc->getParameterNames();

    // 2. Set up
    std::map<std::string, Parameter>::iterator paramiter;
    for (size_t i = 0; i < funparamnames.size(); ++i)
    {
      string parname = funparamnames[i];
      paramiter = params.find(parname);

      if (paramiter != params.end())
      {
        // Found, set up the parameter
        Parameter& param = paramiter->second;
        if (param.fit)
        {
          // If fit.  Unfix it and set up constraint
          function->unfix(i);

          double lowerbound = param.minvalue;
          double upperbound = param.maxvalue;
          if (lowerbound >= -DBL_MAX*0.1 || upperbound <= DBL_MAX*0.1)
          {
            // If there is a boundary
            BoundaryConstraint *bc = new BoundaryConstraint(function.get(), parname, lowerbound,
                                                            upperbound, false);
            function->addConstraint(bc);
          }
        }
        else
        {
          // If fix.
          function->fix(i);
        }
      }
      else
      {
        // Not found and thus quit
        stringstream errss;
        errss << "Peak profile parameter " << parname << " is not found in input parameters. ";
        g_log.error(errss.str());
        throw runtime_error(errss.str());
      }
    } // ENDFOR parameter name

    g_log.notice() << "Fit function:\n" << function->asString() << "\n";

    return;
  }