/// Sets the Jacobian, which is wi at any point.
void PoldiSpectrumLinearBackground::functionDeriv1DSpectrum(
    const FunctionDomain1DSpectrum &domain, Jacobian &jacobian) {
  double wsIndexDouble = static_cast<double>(domain.getWorkspaceIndex());

  for (size_t i = 0; i < domain.size(); ++i) {
    jacobian.set(i, 0, wsIndexDouble);
  }
}
/**
 * Calculates derivatives
 *
 * The method calculates derivatives of the wrapped profile function and
 * transforms them into the correct domain.
 *
 * @param domain :: FunctionDomain1DSpectrum, containing a workspace index
 * @param jacobian :: Jacobian matrix.
 */
void PoldiSpectrumDomainFunction::functionDeriv1DSpectrum(
    const FunctionDomain1DSpectrum &domain, Jacobian &jacobian) {
  size_t index = domain.getWorkspaceIndex();
  Poldi2DHelper_sptr helper = m_2dHelpers[index];

  if (helper) {
    size_t domainSize = domain.size();

    double fwhm = m_profileFunction->fwhm();
    double centre = m_profileFunction->centre();

    double dWidth = 2.0 * fwhm;
    double dCalcMin = centre - dWidth;
    size_t dWidthN = static_cast<size_t>(
        std::max(2, 2 * static_cast<int>(dWidth / helper->deltaD) + 1));

    int pos = 0;

    for (size_t i = 0; i < helper->domain->size(); ++i) {
      if ((*(helper->domain))[i] >= dCalcMin) {
        pos = static_cast<int>(i + 1);
        break;
      }
    }

    size_t baseOffset = static_cast<size_t>(pos + helper->minTOFN);

    for (size_t i = 0; i < helper->dOffsets.size(); ++i) {
      double newD = centre + helper->dFractionalOffsets[i];
      size_t offset = static_cast<size_t>(helper->dOffsets[i]) + baseOffset;
      WrapAroundJacobian smallJ(jacobian, offset, helper->factors, pos,
                                domainSize);

      m_profileFunction->setCentre(newD);

      m_profileFunction->functionDerivLocal(
          &smallJ, helper->domain->getPointerAt(pos), dWidthN);
    }

    m_profileFunction->setCentre(centre);
  }
}