Skip to content
Snippets Groups Projects
ConvFit.cpp 48.7 KiB
Newer Older
    FunctionDomain1DVector domain(inputXData);
    FunctionValues outputData(domain);
    function->function(domain, outputData);

    QVector<double> dataX, dataY;

    for ( size_t i = 0; i < nData; i++ )
    {
      dataX.append(inputXData[i]);
      dataY.append(outputData.getCalculated(i));
    }

    IAlgorithm_sptr createWsAlg = AlgorithmManager::Instance().create("CreateWorkspace");
    createWsAlg->initialize();
    createWsAlg->setChild(true);
    createWsAlg->setLogging(false);
    createWsAlg->setProperty("OutputWorkspace", "__GuessAnon");
    createWsAlg->setProperty("NSpec", 1);
    createWsAlg->setProperty("DataX", dataX.toStdVector());
    createWsAlg->setProperty("DataY", dataY.toStdVector());
    createWsAlg->execute();
    MatrixWorkspace_sptr guessWs = createWsAlg->getProperty("OutputWorkspace");

    m_uiForm.ppPlot->addSpectrum("Guess", guessWs, 0, Qt::green);
  void ConvFit::singleFit()
    if(!validate())
      return;

    updatePlot();
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.ckPlotGuess->setChecked(false);
    CompositeFunction_sptr function = createFunction(m_uiForm.ckTieCentres->isChecked());

    // get output name
    QString fitType = fitTypeString();
    QString bgType = backgroundString();
    if(fitType == "")
    {
      g_log.error("No fit type defined!");
    }

Dan Nixon's avatar
Dan Nixon committed
    m_singleFitOutputName = runPythonCode(QString("from IndirectCommon import getWSprefix\nprint getWSprefix('") + m_cfInputWSName + QString("')\n")).trimmed();
    m_singleFitOutputName += QString("conv_") + fitType + bgType + m_uiForm.spPlotSpectrum->text();
    int maxIterations = static_cast<int>(m_dblManager->value(m_properties["MaxIterations"]));

    m_singleFitAlg = AlgorithmManager::Instance().create("Fit");
    m_singleFitAlg->initialize();
    m_singleFitAlg->setPropertyValue("Function", function->asString());
    m_singleFitAlg->setPropertyValue("InputWorkspace", m_cfInputWSName.toStdString());
    m_singleFitAlg->setProperty<int>("WorkspaceIndex", m_uiForm.spPlotSpectrum->text().toInt());
    m_singleFitAlg->setProperty<double>("StartX", m_dblManager->value(m_properties["StartX"]));
    m_singleFitAlg->setProperty<double>("EndX", m_dblManager->value(m_properties["EndX"]));
    m_singleFitAlg->setProperty("Output", m_singleFitOutputName.toStdString());
    m_singleFitAlg->setProperty("CreateOutput", true);
    m_singleFitAlg->setProperty("OutputCompositeMembers", true);
    m_singleFitAlg->setProperty("ConvolveMembers", true);
    m_singleFitAlg->setProperty("MaxIterations", maxIterations);
    m_singleFitAlg->setProperty("Minimizer", minimizerString(m_singleFitOutputName).toStdString());

    m_batchAlgoRunner->addAlgorithm(m_singleFitAlg);
    connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)),
            this, SLOT(singleFitComplete(bool)));
    m_batchAlgoRunner->executeBatchAsync();
  }

Dan Nixon's avatar
Dan Nixon committed
  /**
   * Handle completion of the fit algorithm for single fit.
   *
   * @param error If the fit algorithm failed
   */
  void ConvFit::singleFitComplete(bool error)
  {
    disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)),
               this, SLOT(singleFitComplete(bool)));

    if(error)
      showMessageBox("Fit algorithm failed.");
    // Plot the line on the mini plot
    m_uiForm.ppPlot->removeSpectrum("Guess");
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.ppPlot->addSpectrum("Fit", m_singleFitOutputName+"_Workspace", 1, Qt::red);
Dan Nixon's avatar
Dan Nixon committed
    IFunction_sptr outputFunc = m_singleFitAlg->getProperty("Function");
    // Get params.
    QMap<QString,double> parameters;
    std::vector<std::string> parNames = outputFunc->getParameterNames();
    std::vector<double> parVals;
    for( size_t i = 0; i < parNames.size(); ++i )
      parVals.push_back(outputFunc->getParameter(parNames[i]));
    for ( size_t i = 0; i < parNames.size(); ++i )
      parameters[QString(parNames[i].c_str())] = parVals[i];

    // Populate Tree widget with values
    // Background should always be f0
    m_dblManager->setValue(m_properties["BGA0"], parameters["f0.A0"]);
    m_dblManager->setValue(m_properties["BGA1"], parameters["f0.A1"]);
    int fitTypeIndex = m_uiForm.cbFitType->currentIndex();

    int funcIndex = 0;
Dan Nixon's avatar
Dan Nixon committed
    int subIndex = 0;
Dan Nixon's avatar
Dan Nixon committed
    //check if we're using a temperature correction
    if (m_uiForm.ckTempCorrection->isChecked() &&
        !m_uiForm.leTempCorrection->text().isEmpty())
    {
      subIndex++;
    }
Dan Nixon's avatar
Dan Nixon committed
    bool usingDeltaFunc = m_blnManager->value(m_properties["UseDeltaFunc"]);

    // If using a delta function with any fit type or using two Lorentzians
    bool usingCompositeFunc = ((usingDeltaFunc && fitTypeIndex > 0) || fitTypeIndex == 2);

    QString prefBase = "f1.f1.";

Dan Nixon's avatar
Dan Nixon committed
    if ( usingDeltaFunc )
      QString key = prefBase;
Dan Nixon's avatar
Dan Nixon committed
      if (usingCompositeFunc)
      {
        key += "f0.";
      }
Dan Nixon's avatar
Dan Nixon committed
      key += "Height";
      m_dblManager->setValue(m_properties["DeltaHeight"], parameters[key]);
      funcIndex++;
    if ( fitTypeIndex == 1 || fitTypeIndex == 2 )
      // One Lorentz
Dan Nixon's avatar
Dan Nixon committed
      QString pref = prefBase;
Dan Nixon's avatar
Dan Nixon committed
      if ( usingCompositeFunc )
      {
        pref += "f" + QString::number(funcIndex) + ".f" + QString::number(subIndex) + ".";
      }
      else
      {
        pref += "f" + QString::number(subIndex) + ".";
      }
      m_dblManager->setValue(m_properties["Lorentzian 1.Amplitude"], parameters[pref+"Amplitude"]);
      m_dblManager->setValue(m_properties["Lorentzian 1.PeakCentre"], parameters[pref+"PeakCentre"]);
      m_dblManager->setValue(m_properties["Lorentzian 1.FWHM"], parameters[pref+"FWHM"]);
      funcIndex++;
    if ( fitTypeIndex == 2 )
    {
      // Two Lorentz
Dan Nixon's avatar
Dan Nixon committed
      QString pref = prefBase;
      pref += "f" + QString::number(funcIndex) + ".f" + QString::number(subIndex) + ".";
      m_dblManager->setValue(m_properties["Lorentzian 2.Amplitude"], parameters[pref+"Amplitude"]);
      m_dblManager->setValue(m_properties["Lorentzian 2.PeakCentre"], parameters[pref+"PeakCentre"]);
      m_dblManager->setValue(m_properties["Lorentzian 2.FWHM"], parameters[pref+"FWHM"]);
    if ( fitTypeIndex == 3 )
    {
      // DiffSphere
      QString pref = prefBase;

      if ( usingCompositeFunc )
      {
        pref += "f" + QString::number(funcIndex) + ".f" + QString::number(subIndex) + ".";
      }
      else
      {
        pref += "f" + QString::number(subIndex) + ".";
      }

      m_dblManager->setValue(m_properties["Diffusion Sphere.Intensity"], parameters[pref+"Intensity"]);
      m_dblManager->setValue(m_properties["Diffusion Sphere.Radius"], parameters[pref+"Radius"]);
      m_dblManager->setValue(m_properties["Diffusion Sphere.Diffusion"], parameters[pref+"Diffusion"]);
      m_dblManager->setValue(m_properties["Diffusion Sphere.Shift"], parameters[pref+"Shift"]);
    if ( fitTypeIndex == 4 )
    {
      // DiffSphere
      QString pref = prefBase;

      if ( usingCompositeFunc )
      {
        pref += "f" + QString::number(funcIndex) + ".f" + QString::number(subIndex) + ".";
      }
      else
      {
        pref += "f" + QString::number(subIndex) + ".";
      }

      m_dblManager->setValue(m_properties["Diffusion Circle.Intensity"], parameters[pref+"Intensity"]);
      m_dblManager->setValue(m_properties["Diffusion Circle.Radius"], parameters[pref+"Radius"]);
      m_dblManager->setValue(m_properties["Diffusion Circle.Decay"], parameters[pref+"Decay"]);
      m_dblManager->setValue(m_properties["Diffusion Circle.Shift"], parameters[pref+"Shift"]);
    }

    m_pythonExportWsName = "";
  /**
   * Handles the user entering a new minimum spectrum index.
   *
   * Prevents the user entering an overlapping spectra range.
   *
   * @param value Minimum spectrum index
   */
  void ConvFit::specMinChanged(int value)
  {
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.spSpectraMax->setMinimum(value);
  /**
   * Handles the user entering a new maximum spectrum index.
   *
   * Prevents the user entering an overlapping spectra range.
   *
   * @param value Maximum spectrum index
   */
  void ConvFit::specMaxChanged(int value)
  {
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.spSpectraMin->setMaximum(value);
  void ConvFit::minChanged(double val)
  {
    m_dblManager->setValue(m_properties["StartX"], val);
  void ConvFit::maxChanged(double val)
  {
    m_dblManager->setValue(m_properties["EndX"], val);
  void ConvFit::hwhmChanged(double val)
  {
    const double peakCentre = m_dblManager->value(m_properties["Lorentzian 1.PeakCentre"]);
    // Always want FWHM to display as positive.
    const double hwhm = std::fabs(val-peakCentre);
    // Update the property
    auto hwhmRangeSelector = m_uiForm.ppPlot->getRangeSelector("ConvFitHWHM");
    hwhmRangeSelector->blockSignals(true);
    m_dblManager->setValue(m_properties["Lorentzian 1.FWHM"], hwhm*2);
    hwhmRangeSelector->blockSignals(false);
  void ConvFit::backgLevel(double val)
  {
    m_dblManager->setValue(m_properties["BGA0"], val);
  void ConvFit::updateRS(QtProperty* prop, double val)
  {
    auto fitRangeSelector = m_uiForm.ppPlot->getRangeSelector("ConvFitRange");
    auto backRangeSelector = m_uiForm.ppPlot->getRangeSelector("ConvFitBackRange");

    if ( prop == m_properties["StartX"] ) { fitRangeSelector->setMinimum(val); }
    else if ( prop == m_properties["EndX"] ) { fitRangeSelector->setMaximum(val); }
    else if ( prop == m_properties["BGA0"] ) { backRangeSelector->setMinimum(val); }
    else if ( prop == m_properties["Lorentzian 1.FWHM"] ) { hwhmUpdateRS(val); }
    else if ( prop == m_properties["Lorentzian 1.PeakCentre"] )
Dan Nixon's avatar
Dan Nixon committed
      hwhmUpdateRS(m_dblManager->value(m_properties["Lorentzian 1.FWHM"]));
  void ConvFit::hwhmUpdateRS(double val)
  {
    const double peakCentre = m_dblManager->value(m_properties["Lorentzian 1.PeakCentre"]);
    auto hwhmRangeSelector = m_uiForm.ppPlot->getRangeSelector("ConvFitHWHM");
    hwhmRangeSelector->setMinimum(peakCentre-val/2);
    hwhmRangeSelector->setMaximum(peakCentre+val/2);
  void ConvFit::checkBoxUpdate(QtProperty* prop, bool checked)
  {
    UNUSED_ARG(checked);

    if(prop == m_properties["UseDeltaFunc"])
      updatePlotOptions();
    else if(prop == m_properties["UseFABADA"])
    {
      if(checked)
      {
        // FABADA needs a much higher iteration limit
        m_dblManager->setValue(m_properties["MaxIterations"], 20000);

        m_properties["FABADA"]->addSubProperty(m_properties["OutputFABADAChain"]);
        m_properties["FABADA"]->addSubProperty(m_properties["FABADAChainLength"]);
      }
      else
      {
        m_dblManager->setValue(m_properties["MaxIterations"], 500);

        m_properties["FABADA"]->removeSubProperty(m_properties["OutputFABADAChain"]);
        m_properties["FABADA"]->removeSubProperty(m_properties["FABADAChainLength"]);
      }
    }
  void ConvFit::fitContextMenu(const QPoint &)
  {
    QtBrowserItem* item(NULL);

    item = m_cfTree->currentItem();

    if ( ! item )
      return;

    // is it a fit property ?
    QtProperty* prop = item->property();

    if ( prop == m_properties["StartX"] || prop == m_properties["EndX"] )
    bool fixed = prop->propertyManager() != m_dblManager;
    if ( fixed && prop->propertyManager() != m_stringManager )
    QMenu* menu = new QMenu("ConvFit", m_cfTree);
      action = new QAction("Fix", m_parentWidget);
      connect(action, SIGNAL(triggered()), this, SLOT(fixItem()));
    }
    else
    {
      action = new QAction("Remove Fix", m_parentWidget);
      connect(action, SIGNAL(triggered()), this, SLOT(unFixItem()));
    }

    menu->addAction(action);

    // Show the menu
    menu->popup(QCursor::pos());
  }

  void ConvFit::fixItem()
  {
    QtBrowserItem* item = m_cfTree->currentItem();

    // Determine what the property is.
    QtProperty* prop = item->property();
Dan Nixon's avatar
Dan Nixon committed
    QtProperty* fixedProp = m_stringManager->addProperty( prop->propertyName() );
    QtProperty* fprlbl = m_stringManager->addProperty("Fixed");
    fixedProp->addSubProperty(fprlbl);
    m_stringManager->setValue(fixedProp, prop->valueText());

    item->parent()->property()->addSubProperty(fixedProp);

    m_fixedProps[fixedProp] = prop;

    item->parent()->property()->removeSubProperty(prop);
  }

  void ConvFit::unFixItem()
  {
    QtBrowserItem* item = m_cfTree->currentItem();

    QtProperty* prop = item->property();
    if ( prop->subProperties().empty() )
      item = item->parent();
      prop = item->property();
    }

    item->parent()->property()->addSubProperty(m_fixedProps[prop]);
    item->parent()->property()->removeSubProperty(prop);
    m_fixedProps.remove(prop);
    QtProperty* proplbl = prop->subProperties()[0];
    delete proplbl;
    delete prop;
  }
  void ConvFit::showTieCheckbox(QString fitType)
  {
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.ckTieCentres->setVisible( fitType == "Two Lorentzians" );
  void ConvFit::updatePlotOptions()
  {
    m_uiForm.cbPlotType->clear();

    bool deltaFunction = m_blnManager->value(m_properties["UseDeltaFunc"]);

    QStringList plotOptions;
    plotOptions << "None";

    if(deltaFunction)
      plotOptions << "Height";

    switch(m_uiForm.cbFitType->currentIndex())
    {
      // Lorentzians
      case 1:
      case 2:
        plotOptions << "Amplitude" << "FWHM";
        if(deltaFunction)
          plotOptions << "EISF";
        break;

      // DiffSphere
      case 3:
        plotOptions << "Intensity" << "Radius" << "Diffusion" << "Shift";
        break;

      // DiffRotDiscreteCircle
      case 4:
        plotOptions << "Intensity" << "Radius" << "Decay" << "Shift";
        break;

      default:
        break;
    }

    plotOptions << "All";
    m_uiForm.cbPlotType->addItems(plotOptions);
  }

} // namespace IDA
} // namespace CustomInterfaces
} // namespace MantidQt