Beispiel #1
0
void FitDialog::accept()
{
	QString curve = boxCurve->currentText();
	QStringList curvesList = d_graph->curvesList();
	if (curvesList.contains(curve) <= 0)
	{
		QMessageBox::critical(this,tr("Warning"),
				tr("The curve <b> %1 </b> doesn't exist anymore! Operation aborted!").arg(curve));
		boxCurve->clear();
		boxCurve->addItems(curvesList);
		return;
	}

	if (!validInitialValues())
		return;

	QString from=boxFrom->text().toLower();
	QString to=boxTo->text().toLower();
	QString tolerance=boxTolerance->text().toLower();
	double start, end, eps;
	try
	{
		MyParser parser;
		parser.SetExpr(CONFS(from).toAscii().constData());
		start=parser.Eval();
	}
	catch(mu::ParserError &e)
	{
		QMessageBox::critical(this, tr("Start limit error"),QString::fromStdString(e.GetMsg()));
		boxFrom->setFocus();
		return;
	}

	try
	{
		MyParser parser;
		parser.SetExpr(CONFS(to).toAscii().constData());
		end=parser.Eval();
	}
	catch(mu::ParserError &e)
	{
		QMessageBox::critical(this, tr("End limit error"),QString::fromStdString(e.GetMsg()));
		boxTo->setFocus();
		return;
	}

	if (start>=end)
	{
		QMessageBox::critical(0, tr("Input error"),
				tr("Please enter x limits that satisfy: from < end!"));
		boxTo->setFocus();
		return;
	}

	try
	{
		MyParser parser;
		parser.SetExpr(CONFS(tolerance).toAscii().constData());
		eps=parser.Eval();
	}
	catch(mu::ParserError &e)
	{
		QMessageBox::critical(0, tr("Tolerance input error"),QString::fromStdString(e.GetMsg()));
		boxTolerance->setFocus();
		return;
	}

	if (eps<0 || eps>=1)
	{
		QMessageBox::critical(0, tr("Tolerance input error"),
				tr("The tolerance value must be positive and less than 1!"));
		boxTolerance->setFocus();
		return;
	}

	int i, n=0, rows=boxParams->rowCount();
	if (!boxParams->isColumnHidden(2))
	{
		for (i=0;i<rows;i++)
		{//count the non-constant parameters
            QCheckBox *cb = (QCheckBox*)boxParams->cellWidget(i, 2);
			if (!cb->isChecked())
				n++;
		}
	}
	else
		n=rows;

	QStringList parameters;
	double *paramsInit = new double[n];
	QString formula;

	// recursively define variables for user functions used in formula
	bool found_uf;
	do {
		found_uf = false;
		for (i=0; i<d_user_function_names.count(); i++)
			if (boxFunction->text().contains(d_user_function_names[i])) {
				QStringList l = d_user_functions[i].split("=");
				formula += QString("%1=%2\n")
						.arg(d_user_function_names[i])
						.arg(l[1]);
				found_uf = true;
			}
	} while (found_uf);
	formula += boxFunction->text();

	// define variables for builtin functions used in formula
	for (i=0; i<d_built_in_function_names.count(); i++)
		if (formula.contains(d_built_in_function_names[i]))
			formula.prepend(QString("%1=%2\n")
					.arg(d_built_in_function_names[i])
					.arg(d_built_in_functions[i]));


        if (!boxParams->isColumnHidden(2))
        {
            int j = 0;
            for (i=0;i<rows;i++)
            {
                QCheckBox *cb = (QCheckBox*)boxParams->cellWidget(i, 2);
                if (!cb->isChecked())
                {
                    paramsInit[j] = QLocale().toDouble(boxParams->item(i,1)->text());
                    parameters << boxParams->item(i,0)->text();
                    j++;
                }
                else
                    formula.prepend(QString("%1=%2\n")
                                    .arg(boxParams->item(i,0)->text())
                                    .arg(CONFS(boxParams->item(i,1)->text())));
            }
        }
        else
        {
            for (i=0;i<n;i++)
            {
                paramsInit[i] = QLocale().toDouble(boxParams->item(i,1)->text());
                parameters << boxParams->item(i,0)->text();
            }
        }

        ApplicationWindow *app = (ApplicationWindow *)this->parent();

        if (d_fitter)
        {
            delete d_fitter;
            d_fitter  = 0;
        }

        if (boxUseBuiltIn->isChecked() && categoryBox->currentRow() == 1)
            fitBuiltInFunction(funcBox->currentItem()->text(), paramsInit);
        else if (boxUseBuiltIn->isChecked() && categoryBox->currentRow() == 3)
        {
            d_fitter = new PluginFit(app, d_graph);
            if (!((PluginFit*)d_fitter)->load(d_plugin_files_list[funcBox->currentRow()])){
                d_fitter  = 0;
                return;}
            d_fitter->setInitialGuesses(paramsInit);
        }
        else
        {
            d_fitter = new NonLinearFit(app, d_graph);
            ((NonLinearFit*)d_fitter)->setParametersList(parameters);
            ((NonLinearFit*)d_fitter)->setFormula(formula);
            d_fitter->setInitialGuesses(paramsInit);
        }
        delete[] paramsInit;

        if (!d_fitter->setDataFromCurve(curve, start, end) ||
            !d_fitter->setYErrorSource ((Fit::ErrorSource)boxYErrorSource->currentIndex(),
                                        tableNamesBox->currentText()+"_"+colNamesBox->currentText()))
        {
            delete d_fitter;
            d_fitter  = 0;
            return;
        }

        d_fitter->setTolerance (eps);
        d_fitter->setAlgorithm((Fit::Algorithm)boxAlgorithm->currentIndex());
        d_fitter->setColor(boxColor->currentIndex());
        d_fitter->generateFunction(generatePointsBtn->isChecked(), generatePointsBox->value());
        d_fitter->setMaximumIterations(boxPoints->value());
        d_fitter->scaleErrors(scaleErrorsBox->isChecked());

        if (d_fitter->name() == tr("MultiPeak") && ((MultiPeakFit *)d_fitter)->peaks() > 1)
        {
            ((MultiPeakFit *)d_fitter)->enablePeakCurves(app->generatePeakCurves);
            ((MultiPeakFit *)d_fitter)->setPeakCurvesColor(app->peakCurvesColor);
        }

        d_fitter->fit();
        double *res = d_fitter->results();
        if (!boxParams->isColumnHidden(2))
        {
            int j = 0;
            for (i=0;i<rows;i++)
            {
                QCheckBox *cb = (QCheckBox*)boxParams->cellWidget(i, 2);
                if (!cb->isChecked())
                    boxParams->item(i, 1)->setText(QLocale().toString(res[j++], 'g', boxPrecision->value()));
            }
        }
        else
        {
            for (i=0;i<rows;i++)
                boxParams->item(i, 1)->setText(QLocale().toString(res[i], 'g', boxPrecision->value()));
        }
}
void fitDialog::accept()
{
    QString curve = boxCurve->currentText();
    QStringList curvesList = graph->curvesList();
    if (curvesList.contains(curve) <= 0)
    {
        QMessageBox::critical(this,tr("QtiPlot - Warning"),
                              tr("The curve <b> %1 </b> doesn't exist anymore! Operation aborted!").arg(curve));
        boxCurve->clear();
        boxCurve->insertStringList(curvesList);
        return;
    }

    if (!validInitialValues())
        return;

    QString from=boxFrom->text().lower();
    QString to=boxTo->text().lower();
    QString tolerance=boxTolerance->text().lower();
    double start,end,eps;
    try
    {
        myParser parser;
        parser.SetExpr(from.ascii());
        start=parser.Eval();
    }
    catch(mu::ParserError &e)
    {
        QMessageBox::critical(0, tr("QtiPlot - Start limit error"),e.GetMsg());
        boxFrom->setFocus();
        return;
    }

    try
    {
        myParser parser;
        parser.SetExpr(to.ascii());
        end=parser.Eval();
    }
    catch(mu::ParserError &e)
    {
        QMessageBox::critical(0, tr("QtiPlot - End limit error"),e.GetMsg());
        boxTo->setFocus();
        return;
    }

    if (start>=end)
    {
        QMessageBox::critical(0, tr("QtiPlot - Input error"),
                              tr("Please enter x limits that satisfy: from < end!"));
        boxTo->setFocus();
        return;
    }

    try
    {
        myParser parser;
        parser.SetExpr(tolerance.ascii());
        eps=parser.Eval();
    }
    catch(mu::ParserError &e)
    {
        QMessageBox::critical(0, tr("QtiPlot - Tolerance input error"),e.GetMsg());
        boxTolerance->setFocus();
        return;
    }

    if (eps<0 || eps>=1)
    {
        QMessageBox::critical(0, tr("QtiPlot - Tolerance input error"),
                              tr("The tolerance value must be positive and less than 1!"));
        boxTolerance->setFocus();
        return;
    }

    int i, n=0, rows=boxParams->numRows();
    if (boxParams->numCols() == 3)
    {
        for (i=0; i<rows; i++)
        {   //count the non-constant parameters
            QCheckTableItem *it = (QCheckTableItem *)boxParams->item (i, 2);
            if (!it->isChecked())
                n++;
        }
    }
    else
        n=rows;

    QStringList parameters, initialValues;
    myParser parser;
    bool error=FALSE;
    QString formula = boxFunction->text();
    try
    {
        bool withNames = containsUserFunctionName(formula);
        while(withNames)
        {
            for (i=0; i<(int)userFunctionNames.count(); i++)
            {
                if (formula.contains(userFunctionNames[i]))
                {
                    QStringList l = QStringList::split("=", userFunctions[i], true);
                    formula.replace(userFunctionNames[i], "(" + l[1] + ")");
                }
            }
            withNames = containsUserFunctionName(formula);
        }

        for (i=0; i<(int)builtInFunctionNames.count(); i++)
        {
            if (formula.contains(builtInFunctionNames[i]))
                formula.replace(builtInFunctionNames[i], "(" + builtInFunctions[i] + ")");
        }

        double *paramsInit = new double[n];
        if (boxParams->numCols() == 3)
        {
            for (i=0; i<rows; i++)
            {
                QCheckTableItem *it = (QCheckTableItem *)boxParams->item (i, 2);
                int j = 0;
                if (!it->isChecked())
                {
                    paramsInit[j]=boxParams->text(i,1).toDouble();
                    parser.DefineVar(boxParams->text(i,0).ascii(), &paramsInit[j]);
                    parameters<<boxParams->text(i,0);
                    initialValues<<boxParams->text(i,1);
                    j++;
                }
                else
                    formula.replace(boxParams->text(i,0), boxParams->text(i,1));
            }
        }
        else
        {
            for (i=0; i<n; i++)
            {
                paramsInit[i]=boxParams->text(i,1).toDouble();
                parser.DefineVar(boxParams->text(i,0).ascii(), &paramsInit[i]);
                parameters<<boxParams->text(i,0);
                initialValues<<boxParams->text(i,1);
            }
        }

        parser.SetExpr(formula.ascii());
        double x=start;
        parser.DefineVar("x", &x);
        parser.Eval();
        delete[] paramsInit;
    }
    catch(mu::ParserError &e)
    {
        QString errorMsg = boxFunction->text() + " = " + formula + "\n" + e.GetMsg() + "\n" +
                           tr("Please verify that you have initialized all the parameters!");

        QMessageBox::critical(0, tr("QtiPlot - Input function error"), errorMsg);
        boxFunction->setFocus();
        error = true;
    }

    if (!error)
    {
        ApplicationWindow *app = (ApplicationWindow *)this->parent();
        graph->setFitID(++app->fitNumber);
        QString result;
        if (boxUseBuiltIn->isChecked() && categoryBox->currentItem() == 1)
            result = fitBuiltInFunction(curve,funcBox->currentText(),initialValues, start,end,
                                        boxPoints->value(),boxSolver->currentItem(),eps, boxColor->currentItem());
        else if (boxUseBuiltIn->isChecked() && categoryBox->currentItem() == 3)
        {
            result = graph->fitPluginFunction(curve, pluginFilesList[funcBox->currentItem()],
                                              initialValues, start, end, boxPoints->value(),
                                              boxSolver->currentItem(), eps, boxColor->currentItem());
        }
        else
            result = graph->fitNonlinearCurve(curve, lblFunction->text()+"="+formula, parameters, initialValues,
                                              start, end, boxPoints->value(), boxSolver->currentItem(), eps, boxColor->currentItem());

        QStringList res = graph->fitResults();
        if (boxParams->numCols() == 3)
        {
            int j = 0;
            for (i=0; i<rows; i++)
            {
                QCheckTableItem *it = (QCheckTableItem *)boxParams->item (i, 2);
                if (!it->isChecked())
                    boxParams->setText(i, 1, res[j++]);
            }
        }
        else
        {
            for (i=0; i<rows; i++)
                boxParams->setText(i, 1, res[i]);
        }

        app->updateLog(result);
    }
}