mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -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 "RimCalculationCollection.h"
|
||||||
#include "RimProject.h"
|
#include "RimProject.h"
|
||||||
|
|
||||||
#include "cafPdmUiTreeSelectionEditor.h"
|
|
||||||
#include "cafPdmUiListEditor.h"
|
#include "cafPdmUiListEditor.h"
|
||||||
#include "cafPdmUiPushButtonEditor.h"
|
#include "cafPdmUiPushButtonEditor.h"
|
||||||
|
#include "cafPdmUiTreeSelectionEditor.h"
|
||||||
|
|
||||||
|
|
||||||
CAF_PDM_SOURCE_INIT(RicSummaryCurveCalculator, "RicSummaryCurveCalculator");
|
CAF_PDM_SOURCE_INIT(RicSummaryCurveCalculator, "RicSummaryCurveCalculator");
|
||||||
@ -49,6 +49,12 @@ RicSummaryCurveCalculator::RicSummaryCurveCalculator()
|
|||||||
CAF_PDM_InitFieldNoDefault(&m_deleteCalculation, "DeleteCalculation", "Delete Calculation", "", "", "");
|
CAF_PDM_InitFieldNoDefault(&m_deleteCalculation, "DeleteCalculation", "Delete Calculation", "", "", "");
|
||||||
RicSummaryCurveCalculator::assignPushButtonEditor(&m_deleteCalculation);
|
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", "", "", "");
|
CAF_PDM_InitFieldNoDefault(&m_newVariable, "NewVariable", "New Variable", "", "", "");
|
||||||
RicSummaryCurveCalculator::assignPushButtonEditor(&m_newVariable);
|
RicSummaryCurveCalculator::assignPushButtonEditor(&m_newVariable);
|
||||||
|
|
||||||
@ -106,6 +112,26 @@ void RicSummaryCurveCalculator::fieldChangedByUi(const caf::PdmFieldHandle* chan
|
|||||||
this->updateConnectedEditors();
|
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)
|
else if (changedField == &m_newVariable)
|
||||||
{
|
{
|
||||||
m_newVariable = false;
|
m_newVariable = false;
|
||||||
@ -142,6 +168,9 @@ void RicSummaryCurveCalculator::defineUiOrdering(QString uiConfigName, caf::PdmU
|
|||||||
m_currentCalculation->uiOrdering(uiConfigName, *group);
|
m_currentCalculation->uiOrdering(uiConfigName, *group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group->add(&m_parseExpression);
|
||||||
|
group->add(&m_calculateExpression);
|
||||||
|
|
||||||
group->add(&m_newVariable);
|
group->add(&m_newVariable);
|
||||||
group->add(&m_deleteVariable);
|
group->add(&m_deleteVariable);
|
||||||
}
|
}
|
||||||
@ -157,7 +186,7 @@ QList<caf::PdmOptionItemInfo> RicSummaryCurveCalculator::calculateValueOptions(c
|
|||||||
{
|
{
|
||||||
for (auto c : calculationCollection()->calculations())
|
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");
|
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_newVariable;
|
||||||
caf::PdmField<bool> m_deleteVariable;
|
caf::PdmField<bool> m_deleteVariable;
|
||||||
|
|
||||||
|
caf::PdmField<bool> m_parseExpression;
|
||||||
|
caf::PdmField<bool> m_calculateExpression;
|
||||||
};
|
};
|
||||||
|
@ -18,8 +18,16 @@
|
|||||||
|
|
||||||
#include "RimCalculation.h"
|
#include "RimCalculation.h"
|
||||||
|
|
||||||
|
#include "expressionparser/ExpressionParser.h"
|
||||||
|
|
||||||
|
#include "RiaLogging.h"
|
||||||
#include "RimCalculationVariable.h"
|
#include "RimCalculationVariable.h"
|
||||||
|
|
||||||
|
#include "cafPdmUiTextEditor.h"
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
|
||||||
CAF_PDM_SOURCE_INIT(RimCalculation, "RimCalculation");
|
CAF_PDM_SOURCE_INIT(RimCalculation, "RimCalculation");
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -29,11 +37,32 @@ RimCalculation::RimCalculation()
|
|||||||
{
|
{
|
||||||
CAF_PDM_InitObject("RimCalculation", ":/octave.png", "Calculation", "");
|
CAF_PDM_InitObject("RimCalculation", ":/octave.png", "Calculation", "");
|
||||||
|
|
||||||
|
CAF_PDM_InitFieldNoDefault(&m_description, "Description", "Description", "", "", "");
|
||||||
|
m_description.uiCapability()->setUiReadOnly(true);
|
||||||
|
|
||||||
CAF_PDM_InitFieldNoDefault(&m_expression, "Expression", "Expression", "", "", "");
|
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_variables, "Variables", "Variables", "", "", "");
|
||||||
CAF_PDM_InitFieldNoDefault(&m_calculatedValues, "CalculatedValues", "Calculated Values", "", "", "");
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "RimNamedObject.h"
|
|
||||||
|
|
||||||
#include "cafPdmChildArrayField.h"
|
#include "cafPdmChildArrayField.h"
|
||||||
|
#include "cafPdmObject.h"
|
||||||
|
#include "cafPdmField.h"
|
||||||
|
|
||||||
class RimCalculationVariable;
|
class RimCalculationVariable;
|
||||||
|
|
||||||
@ -28,21 +28,33 @@ class RimCalculationVariable;
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
class RimCalculation : public RimNamedObject
|
class RimCalculation : public caf::PdmObject
|
||||||
{
|
{
|
||||||
CAF_PDM_HEADER_INIT;
|
CAF_PDM_HEADER_INIT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RimCalculation();
|
RimCalculation();
|
||||||
|
|
||||||
|
void setDescription(const QString& description);
|
||||||
|
QString description() const;
|
||||||
|
|
||||||
caf::PdmChildArrayFieldHandle* variables();
|
caf::PdmChildArrayFieldHandle* variables();
|
||||||
RimCalculationVariable* addVariable();
|
RimCalculationVariable* addVariable();
|
||||||
void deleteVariable(RimCalculationVariable* calcVariable);
|
void deleteVariable(RimCalculationVariable* calcVariable);
|
||||||
|
|
||||||
const std::vector<double>& values() const;
|
const std::vector<double>& values() const;
|
||||||
void setCalculatedValues(const std::vector<double>& values);
|
|
||||||
|
bool parseExpression();
|
||||||
|
bool calculate();
|
||||||
|
|
||||||
|
virtual caf::PdmFieldHandle* userDescriptionField() override;
|
||||||
|
|
||||||
private:
|
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::PdmField<QString> m_expression;
|
||||||
caf::PdmChildArrayField<RimCalculationVariable*> m_variables;
|
caf::PdmChildArrayField<RimCalculationVariable*> m_variables;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ RimCalculationCollection::RimCalculationCollection()
|
|||||||
RimCalculation* RimCalculationCollection::addCalculation()
|
RimCalculation* RimCalculationCollection::addCalculation()
|
||||||
{
|
{
|
||||||
RimCalculation* calculation = new RimCalculation;
|
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);
|
m_calcuations.push_back(calculation);
|
||||||
|
|
||||||
|
@ -54,6 +54,22 @@ RimCalculationVariable::RimCalculationVariable()
|
|||||||
m_summaryAddress = new RimSummaryAddress;
|
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:
|
public:
|
||||||
RimCalculationVariable();
|
RimCalculationVariable();
|
||||||
|
|
||||||
|
QString name() const;
|
||||||
|
void setName(const QString& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString summaryAddressDisplayString() const;
|
QString summaryAddressDisplayString() const;
|
||||||
|
Loading…
Reference in New Issue
Block a user