mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-08 07:03:25 -06:00
#1977 Curve Calculator : Trigger parsing and evaluation of expression
This commit is contained in:
parent
a3cd62d315
commit
9d0e59c60f
@ -24,9 +24,9 @@
|
||||
#include "RimCalculationCollection.h"
|
||||
#include "RimProject.h"
|
||||
|
||||
#include "cafPdmUiTreeSelectionEditor.h"
|
||||
#include "cafPdmUiListEditor.h"
|
||||
#include "cafPdmUiPushButtonEditor.h"
|
||||
#include "cafPdmUiTreeSelectionEditor.h"
|
||||
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RicSummaryCurveCalculator, "RicSummaryCurveCalculator");
|
||||
@ -49,6 +49,12 @@ RicSummaryCurveCalculator::RicSummaryCurveCalculator()
|
||||
CAF_PDM_InitFieldNoDefault(&m_deleteCalculation, "DeleteCalculation", "Delete Calculation", "", "", "");
|
||||
RicSummaryCurveCalculator::assignPushButtonEditor(&m_deleteCalculation);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_parseExpression, "ParseExpression", "Parse", "", "", "");
|
||||
RicSummaryCurveCalculator::assignPushButtonEditor(&m_parseExpression);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_calculateExpression, "CalculateExpression", "Calculate", "", "", "");
|
||||
RicSummaryCurveCalculator::assignPushButtonEditor(&m_calculateExpression);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_newVariable, "NewVariable", "New Variable", "", "", "");
|
||||
RicSummaryCurveCalculator::assignPushButtonEditor(&m_newVariable);
|
||||
|
||||
@ -106,6 +112,26 @@ void RicSummaryCurveCalculator::fieldChangedByUi(const caf::PdmFieldHandle* chan
|
||||
this->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
else if (changedField == &m_parseExpression)
|
||||
{
|
||||
m_parseExpression = false;
|
||||
|
||||
if (m_currentCalculation())
|
||||
{
|
||||
m_currentCalculation()->parseExpression();
|
||||
|
||||
this->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
else if (changedField == &m_calculateExpression)
|
||||
{
|
||||
m_calculateExpression = false;
|
||||
|
||||
if (m_currentCalculation())
|
||||
{
|
||||
m_currentCalculation()->calculate();
|
||||
}
|
||||
}
|
||||
else if (changedField == &m_newVariable)
|
||||
{
|
||||
m_newVariable = false;
|
||||
@ -142,6 +168,9 @@ void RicSummaryCurveCalculator::defineUiOrdering(QString uiConfigName, caf::PdmU
|
||||
m_currentCalculation->uiOrdering(uiConfigName, *group);
|
||||
}
|
||||
|
||||
group->add(&m_parseExpression);
|
||||
group->add(&m_calculateExpression);
|
||||
|
||||
group->add(&m_newVariable);
|
||||
group->add(&m_deleteVariable);
|
||||
}
|
||||
@ -157,7 +186,7 @@ QList<caf::PdmOptionItemInfo> RicSummaryCurveCalculator::calculateValueOptions(c
|
||||
{
|
||||
for (auto c : calculationCollection()->calculations())
|
||||
{
|
||||
options.push_back(caf::PdmOptionItemInfo(c->name(), c));
|
||||
options.push_back(caf::PdmOptionItemInfo(c->description(), c));
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,4 +252,12 @@ void RicSummaryCurveCalculator::defineEditorAttribute(const caf::PdmFieldHandle*
|
||||
{
|
||||
RicSummaryCurveCalculator::assignPushButtonEditorText(attribute, "Delete Variable");
|
||||
}
|
||||
else if (&m_parseExpression == field)
|
||||
{
|
||||
RicSummaryCurveCalculator::assignPushButtonEditorText(attribute, "Parse Expression");
|
||||
}
|
||||
else if (&m_calculateExpression == field)
|
||||
{
|
||||
RicSummaryCurveCalculator::assignPushButtonEditorText(attribute, "Calculate");
|
||||
}
|
||||
}
|
||||
|
@ -64,4 +64,7 @@ private:
|
||||
|
||||
caf::PdmField<bool> m_newVariable;
|
||||
caf::PdmField<bool> m_deleteVariable;
|
||||
|
||||
caf::PdmField<bool> m_parseExpression;
|
||||
caf::PdmField<bool> m_calculateExpression;
|
||||
};
|
||||
|
@ -18,8 +18,16 @@
|
||||
|
||||
#include "RimCalculation.h"
|
||||
|
||||
#include "expressionparser/ExpressionParser.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RimCalculationVariable.h"
|
||||
|
||||
#include "cafPdmUiTextEditor.h"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RimCalculation, "RimCalculation");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -29,11 +37,32 @@ RimCalculation::RimCalculation()
|
||||
{
|
||||
CAF_PDM_InitObject("RimCalculation", ":/octave.png", "Calculation", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_expression, "Expression", "Expression", "", "", "");
|
||||
CAF_PDM_InitFieldNoDefault(&m_variables, "Variables", "Variables", "", "", "");
|
||||
CAF_PDM_InitFieldNoDefault(&m_description, "Description", "Description", "", "", "");
|
||||
m_description.uiCapability()->setUiReadOnly(true);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_expression, "Expression", "Expression", "", "", "");
|
||||
m_expression.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName());
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_variables, "Variables", "Variables", "", "", "");
|
||||
CAF_PDM_InitFieldNoDefault(&m_calculatedValues, "CalculatedValues", "Calculated Values", "", "", "");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCalculation::setDescription(const QString& description)
|
||||
{
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimCalculation::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -74,7 +103,143 @@ const std::vector<double>& RimCalculation::values() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCalculation::setCalculatedValues(const std::vector<double>& values)
|
||||
caf::PdmFieldHandle* RimCalculation::userDescriptionField()
|
||||
{
|
||||
m_calculatedValues = values;
|
||||
return &m_description;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimCalculation::parseExpression()
|
||||
{
|
||||
QString leftHandSideVariableName = RimCalculation::findLeftHandSide(m_expression);
|
||||
if (leftHandSideVariableName.isEmpty()) return false;
|
||||
|
||||
std::vector<QString> variableNames = ExpressionParser::detectReferencedVariables(m_expression);
|
||||
|
||||
// Remove variables not present in expression
|
||||
{
|
||||
std::vector<RimCalculationVariable*> toBeDeleted;
|
||||
for (RimCalculationVariable* v : m_variables)
|
||||
{
|
||||
if (std::find(variableNames.begin(), variableNames.end(), v->name()) == variableNames.end())
|
||||
{
|
||||
toBeDeleted.push_back(v);
|
||||
}
|
||||
|
||||
if (leftHandSideVariableName == v->name())
|
||||
{
|
||||
toBeDeleted.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
for (RimCalculationVariable* v : toBeDeleted)
|
||||
{
|
||||
deleteVariable(v);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto variableName : variableNames)
|
||||
{
|
||||
if (leftHandSideVariableName != variableName)
|
||||
{
|
||||
if (!findByName(variableName))
|
||||
{
|
||||
auto v = this->addVariable();
|
||||
v->setName(variableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimCalculation::calculate()
|
||||
{
|
||||
if (!parseExpression()) return false;
|
||||
|
||||
QString leftHandSideVariableName = RimCalculation::findLeftHandSide(m_expression);
|
||||
|
||||
ExpressionParser parser;
|
||||
|
||||
std::vector<double> a(10);
|
||||
std::iota(a.begin(), a.end(), 0);
|
||||
|
||||
size_t itemCount = 0;
|
||||
|
||||
for (RimCalculationVariable* v : m_variables)
|
||||
{
|
||||
itemCount = a.size();
|
||||
parser.assignVector(v->name(), a);
|
||||
}
|
||||
|
||||
if (itemCount == 0)
|
||||
{
|
||||
RiaLogging::error("Not able to evaluate expression with no data.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_calculatedValues.v().resize(itemCount);
|
||||
parser.assignVector(leftHandSideVariableName, m_calculatedValues.v());
|
||||
|
||||
QString errorText;
|
||||
bool evaluatedOk = parser.evaluate(m_expression, &errorText);
|
||||
|
||||
if (evaluatedOk)
|
||||
{
|
||||
QString txt;
|
||||
for (auto v : m_calculatedValues())
|
||||
{
|
||||
txt += QString::number(v);
|
||||
txt += " ";
|
||||
}
|
||||
|
||||
RiaLogging::info(txt);
|
||||
}
|
||||
else
|
||||
{
|
||||
RiaLogging::error(errorText);
|
||||
}
|
||||
|
||||
return evaluatedOk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Find the last assignment using := and interpret the text before the := as LHS
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimCalculation::findLeftHandSide(const QString& expresion)
|
||||
{
|
||||
QString exprWithSpace = expresion;
|
||||
exprWithSpace.replace("\n", " ");
|
||||
|
||||
QStringList words = exprWithSpace.split(" ", QString::SkipEmptyParts);
|
||||
|
||||
int index = words.lastIndexOf(":=");
|
||||
if (index > 0)
|
||||
{
|
||||
return words[index - 1];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimCalculationVariable* RimCalculation::findByName(const QString& name) const
|
||||
{
|
||||
for (RimCalculationVariable* v : m_variables)
|
||||
{
|
||||
if (v->name() == name)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimNamedObject.h"
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmField.h"
|
||||
|
||||
class RimCalculationVariable;
|
||||
|
||||
@ -28,21 +28,33 @@ class RimCalculationVariable;
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimCalculation : public RimNamedObject
|
||||
class RimCalculation : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimCalculation();
|
||||
|
||||
void setDescription(const QString& description);
|
||||
QString description() const;
|
||||
|
||||
caf::PdmChildArrayFieldHandle* variables();
|
||||
RimCalculationVariable* addVariable();
|
||||
void deleteVariable(RimCalculationVariable* calcVariable);
|
||||
|
||||
const std::vector<double>& values() const;
|
||||
void setCalculatedValues(const std::vector<double>& values);
|
||||
|
||||
bool parseExpression();
|
||||
bool calculate();
|
||||
|
||||
virtual caf::PdmFieldHandle* userDescriptionField() override;
|
||||
|
||||
private:
|
||||
static QString findLeftHandSide(const QString& expresion);
|
||||
RimCalculationVariable* findByName(const QString& name) const;
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_description;
|
||||
caf::PdmField<QString> m_expression;
|
||||
caf::PdmChildArrayField<RimCalculationVariable*> m_variables;
|
||||
|
||||
|
@ -42,7 +42,7 @@ RimCalculationCollection::RimCalculationCollection()
|
||||
RimCalculation* RimCalculationCollection::addCalculation()
|
||||
{
|
||||
RimCalculation* calculation = new RimCalculation;
|
||||
calculation->setName(QString("Calculation %1").arg(m_calcuations.size()));
|
||||
calculation->setDescription(QString("Calculation %1").arg(m_calcuations.size()));
|
||||
|
||||
m_calcuations.push_back(calculation);
|
||||
|
||||
|
@ -54,6 +54,22 @@ RimCalculationVariable::RimCalculationVariable()
|
||||
m_summaryAddress = new RimSummaryAddress;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimCalculationVariable::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCalculationVariable::setName(const QString& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -40,7 +40,8 @@ class RimCalculationVariable : public caf::PdmObject
|
||||
public:
|
||||
RimCalculationVariable();
|
||||
|
||||
|
||||
QString name() const;
|
||||
void setName(const QString& name);
|
||||
|
||||
private:
|
||||
QString summaryAddressDisplayString() const;
|
||||
|
Loading…
Reference in New Issue
Block a user