Commit 6b5fd214 authored by bonnell's avatar bonnell

added 'safe' ln/log10 expressions by allowing optional numeric argument to be...

added 'safe' ln/log10 expressions by allowing optional numeric argument to be specified as default for non-positive values.Update release notes and expression help.  Updated ultra wrapper to use new 'safe' ln/log10 expressions

git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@7262 18c085ea-50e0-402c-830e-de6fd14e8384
parent 0ffc691a
......@@ -61,6 +61,7 @@
#include <avtExpressionTypeConversions.h>
#include <ParsingExprList.h>
#include <ExprNode.h>
#include <DebugStream.h>
#include <ExpressionException.h>
......@@ -827,4 +828,45 @@ avtExpressionFilter::DetermineVariableType(std::string &varname)
return AVT_UNKNOWN_TYPE;
}
// ****************************************************************************
// Method: avtExpressionFilter::GetNumericVal
//
// Purpose:
// Parses optional arguments.
// Helper to obtain a constant floating point value from an expression
// node. Handles IntegerConst, FloatConst, and Unary Minus
// (with either IntegerConst, FloatConst as a child node)
//
// Programmer: Cyrus Harrison
// Creation: April 4, 2008
//
// ****************************************************************************
bool
avtExpressionFilter::GetNumericVal(ExprNode *node, double &val)
{
bool ok = false;
val = 0;
string n_type = node->GetTypeName();
if ( n_type == "FloatConst")
{
val = dynamic_cast<FloatConstExpr*>(node)->GetValue();
ok = true;
}
else if (n_type == "IntegerConst")
{
val = dynamic_cast<IntegerConstExpr*>(node)->GetValue();
ok = true;
}
else if (n_type == "Unary")
{
ExprNode *child = dynamic_cast<UnaryExpr*>(node)->GetExpr();
if(GetNumericVal(child,val))
{
val *=-1;
ok = true;
}
}
return ok;
}
......@@ -53,6 +53,7 @@
class vtkDataArray;
class ArgsExpr;
class ExprPipelineState;
class ExprNode;
// ****************************************************************************
......@@ -114,6 +115,9 @@ class ExprPipelineState;
// Kathleen Bonnell, Thu Apr 16 09:50:56 PDT 2009
// Added GetOutputVariableName.
//
// Kathleen Bonnell, Fri May 8 13:44:16 PDT 2009
// Added method GetNumericVal (moved from avtCylindricalRadiusExpression.h.
//
// ****************************************************************************
class EXPRESSION_API avtExpressionFilter : virtual public
......@@ -137,6 +141,9 @@ class EXPRESSION_API avtExpressionFilter : virtual public
const char *GetOutputVariableName()
{ return outputVariableName; }
bool GetNumericVal(ExprNode *, double &res);
protected:
char *outputVariableName;
int currentTimeState;
......
......@@ -36,15 +36,19 @@
*
*****************************************************************************/
// ********************************************************************** //
// avtBase10LogExpression.C //
// ********************************************************************** //
// ************************************************************************* //
// avtBase10LogExpression.C //
// ************************************************************************* //
#include <avtBase10LogExpression.h>
#include <vtkDataArray.h>
#include <vtkDataSet.h>
#include <avtExprNode.h>
#include <ExprToken.h>
#include <DebugStream.h>
#include <ExpressionException.h>
......@@ -58,11 +62,16 @@
// Programmer: Hank Childs
// Creation: February 5, 2004
//
// Modifications:
// Kathleen Bonnell, Fri May 8 13:21:52 PDT 2009
// Initialize defaultErrorValue, useDefaultOnError.
//
// ****************************************************************************
avtBase10LogExpression::avtBase10LogExpression()
{
;
defaultErrorValue = 0.;
useDefaultOnError = false;
}
......@@ -105,6 +114,10 @@ avtBase10LogExpression::~avtBase10LogExpression()
// Hank Childs, Fri Nov 15 15:25:26 PST 2002
// Added support for vectors and arbitrary data types.
//
// Kathleen Bonnell, Fri May 8 13:01:58 PDT 2009
// Added support for a default value to be used as a return value for
// non-positive values. Upated exception message.
//
// ****************************************************************************
void
......@@ -118,13 +131,84 @@ avtBase10LogExpression::DoOperation(vtkDataArray *in, vtkDataArray *out,
float f = in->GetComponent(i, j);
if (f <= 0)
{
EXCEPTION2(ExpressionException, outputVariableName,
"you cannot take the logarithm of values <= 0");
if (useDefaultOnError)
out->SetComponent(i, j, defaultErrorValue);
else
{
string msg = "you cannot take the logarithm of values";
msg += "<=0. You might want to try log10(var, ";
msg += "some-default-numeric-value).";
EXCEPTION2(ExpressionException, outputVariableName,
msg.c_str());
}
}
f = log10(f);
out->SetComponent(i, j, f);
else
{
out->SetComponent(i, j, log10(f));
}
}
}
}
// ****************************************************************************
// Method: avtBase10LogExpression::ProcessArguments
//
// Purpose:
// Parses optional arguments.
// Allows the user to pass a default value to be used in error cases.
//
// Programmer: Kathleen Bonnell
// Creation: May 8, 2009
//
// Modifications:
//
// ****************************************************************************
void
avtBase10LogExpression::ProcessArguments(ArgsExpr *args,
ExprPipelineState *state)
{
// Check the number of arguments
std::vector<ArgExpr*> *arguments = args->GetArgs();
int nargs = arguments->size();
if (nargs == 0)
{
EXCEPTION2(ExpressionException, outputVariableName,
"avtBase10LogExpression: No arguments given.");
}
// First arg should be an expression, let it gen is filters.
ArgExpr *first_arg = (*arguments)[0];
avtExprNode *first_tree = dynamic_cast<avtExprNode*>(first_arg->GetExpr());
first_tree->CreateFilters(state);
// If we have two arguments, we expect a numerical const for the second.
if (nargs == 2)
{
ArgExpr *sec = (*arguments)[1];
avtExprNode *second_tree = dynamic_cast<avtExprNode*>(sec->GetExpr());
double v = 0;
if (GetNumericVal(second_tree, v))
{
useDefaultOnError = true;
defaultErrorValue = v;
debug4 << "avtBase10LogExpression:" << "Using " << v
<< " as default value in error conditions" << endl;
}
else
{
string error_msg = "avtBase10LogExpression: "
"Invalid second argument."
"Should be float or int";
debug5 << error_msg << endl;
EXCEPTION2(ExpressionException, outputVariableName,
error_msg.c_str());
}
}
}
......@@ -37,7 +37,7 @@
*****************************************************************************/
// ************************************************************************* //
// avtBase10LogExpression.h //
// avtBase10LogExpression.h //
// ************************************************************************* //
#ifndef AVT_BASE10LOG_FILTER_H
......@@ -47,6 +47,8 @@
#include <avtUnaryMathExpression.h>
class vtkDataArray;
class ArgsExpr;
class ExprPipelineState;
// ****************************************************************************
......@@ -67,21 +69,29 @@ class vtkDataArray;
// Moved inlined constructor and destructor definitions to .C files
// because certain compilers have problems with them.
//
// Kathleen Bonnell, Fri May 8 13:21:18 PDT 2009
// Added defaultErrorValue, useDefaultOnError, and ProcessArguments.
//
// ****************************************************************************
class EXPRESSION_API avtBase10LogExpression : public avtUnaryMathExpression
{
public:
avtBase10LogExpression();
virtual ~avtBase10LogExpression();
avtBase10LogExpression();
virtual ~avtBase10LogExpression();
virtual const char *GetType(void) { return "avtBase10LogExpression"; };
virtual const char *GetDescription(void)
{ return "Calculating base 10 logarithm"; };
virtual const char *GetType(void) { return "avtBase10LogExpression"; };
virtual const char *GetDescription(void)
{ return "Calculating base 10 logarithm"; };
virtual void ProcessArguments(ArgsExpr *, ExprPipelineState *);
protected:
virtual void DoOperation(vtkDataArray *in, vtkDataArray *out,
int ncomponents, int ntuples);
virtual void DoOperation(vtkDataArray *in, vtkDataArray *out,
int ncomponents, int ntuples);
double defaultErrorValue;
bool useDefaultOnError;
};
......
......@@ -301,44 +301,3 @@ avtCylindricalRadiusExpression::ProcessArguments
}
// ****************************************************************************
// Method: avtCylindricalRadiusExpression::avtCylindricalRadiusExpression
//
// Purpose:
// Parses optional arguments.
// Helper to obtain a constant floating point value from an expression
// node. Handles IntegerConst, FloatConst, and Uniary Minus
// (with either IntegerConst, FloatConst as a child node)
//
// Programmer: Cyrus Harrison
// Creation: April 4, 2008
//
// ****************************************************************************
bool
avtCylindricalRadiusExpression::GetNumericVal(ExprNode *node, double &val)
{
bool ok = false;
val = 0;
string n_type = node->GetTypeName();
if ( n_type == "FloatConst")
{
val = dynamic_cast<FloatConstExpr*>(node)->GetValue();
ok = true;
}
else if (n_type == "IntegerConst")
{
val = dynamic_cast<IntegerConstExpr*>(node)->GetValue();
ok = true;
}
else if (n_type == "Unary")
{
ExprNode *child = dynamic_cast<UnaryExpr*>(node)->GetExpr();
if(GetNumericVal(child,val))
{
val *=-1;
ok = true;
}
}
return ok;
}
......@@ -65,6 +65,11 @@ class ExprNode;
// Programmer: Cyrus Harrison
// Creation: April 2, 2008
//
// Modifications:
// Kathleen Bonnell, Fri May 8 12:59:29 PDT 2009
// Moved GetNumericVal to avtExpressionFilter so it could be used by
// other expressions.
//
// ****************************************************************************
class EXPRESSION_API avtCylindricalRadiusExpression
......@@ -87,7 +92,6 @@ class EXPRESSION_API avtCylindricalRadiusExpression
private:
double axisVector[3];
bool GetNumericVal(ExprNode *, double &res);
};
......
......@@ -37,7 +37,7 @@
*****************************************************************************/
// ************************************************************************* //
// avtNaturalLogExpression.C //
// avtNaturalLogExpression.C //
// ************************************************************************* //
#include <avtNaturalLogExpression.h>
......@@ -45,6 +45,11 @@
#include <vtkDataArray.h>
#include <vtkDataSet.h>
#include <avtExprNode.h>
#include <ExprToken.h>
#include <DebugStream.h>
#include <ExpressionException.h>
......@@ -58,11 +63,16 @@
// Programmer: Hank Childs
// Creation: February 5, 2004
//
// Modifications:
// Kathleen Bonnell, Fri May 8 13:21:52 PDT 2009
// Initialize defaultErrorValue, useDefaultOnError.
//
// ****************************************************************************
avtNaturalLogExpression::avtNaturalLogExpression()
{
;
defaultErrorValue = 0.;
useDefaultOnError = false;
}
......@@ -105,6 +115,10 @@ avtNaturalLogExpression::~avtNaturalLogExpression()
// Hank Childs, Fri Nov 15 15:25:26 PST 2002
// Added support for vectors and arbitrary data types.
//
// Kathleen Bonnell, Fri May 8 13:01:58 PDT 2009
// Added support for a default value to be used as a return value for
// non-positive values. Updated exception message.
//
// ****************************************************************************
void
......@@ -115,13 +129,81 @@ avtNaturalLogExpression::DoOperation(vtkDataArray *in, vtkDataArray *out,
{
for (int j = 0 ; j < ncomponents ; j++)
{
float val = in->GetComponent(i, j);
double val = in->GetComponent(i, j);
if (val <= 0)
{
EXCEPTION2(ExpressionException, outputVariableName,
"you cannot take the natural log of values <= 0");
if (useDefaultOnError)
out->SetComponent(i, j, defaultErrorValue);
else
{
string msg = "you cannot take the logarithm of values";
msg += "<=0. You might want to try ln(var, ";
msg += "some-default-numeric-value).";
EXCEPTION2(ExpressionException, outputVariableName,
msg.c_str());
}
}
out->SetComponent(i, j, log(val));
else
out->SetComponent(i, j, log(val));
}
}
}
// ****************************************************************************
// Method: avtNaturalLogExpression::ProcessArguments
//
// Purpose:
// Parses optional arguments.
// Allows the user to pass a default value to be used in error cases.
//
// Programmer: Kathleen Bonnell
// Creation: May 8, 2009
//
// Modifications:
//
// ****************************************************************************
void
avtNaturalLogExpression::ProcessArguments(ArgsExpr *args,
ExprPipelineState *state)
{
// Check the number of arguments
std::vector<ArgExpr*> *arguments = args->GetArgs();
int nargs = arguments->size();
if (nargs == 0)
{
EXCEPTION2(ExpressionException, outputVariableName,
"avtNaturalLogExpression: No arguments given.");
}
// First arg should be an expression, let it gen is filters.
ArgExpr *first_arg = (*arguments)[0];
avtExprNode *first_tree = dynamic_cast<avtExprNode*>(first_arg->GetExpr());
first_tree->CreateFilters(state);
// If we have two arguments, we expect a numerical const for the second.
if (nargs == 2)
{
ArgExpr *sec = (*arguments)[1];
avtExprNode *second_tree = dynamic_cast<avtExprNode*>(sec->GetExpr());
double v = 0;
if (GetNumericVal(second_tree, v))
{
useDefaultOnError = true;
defaultErrorValue = v;
debug4 << "avtNaturalLogExpression:" << "Using " << v
<< " as default value in error conditions" << endl;
}
else
{
string error_msg = "avtNaturalLogExpression: "
"Invalid second argument."
"Should be float or int";
debug5 << error_msg << endl;
EXCEPTION2(ExpressionException, outputVariableName,
error_msg.c_str());
}
}
}
......
......@@ -36,9 +36,9 @@
*
*****************************************************************************/
// ************************************************************************* //
// avtNaturalLogExpression.h //
// ************************************************************************* //
// ************************************************************************** //
// avtNaturalLogExpression.h //
// ************************************************************************** //
#ifndef AVT_NATURALLOG_FILTER_H
#define AVT_NATURALLOG_FILTER_H
......@@ -46,7 +46,8 @@
#include <avtUnaryMathExpression.h>
class vtkDataArray;
class ArgsExpr;
class ExprPipelineState;
// ****************************************************************************
// Class: avtNaturalLogExpression
......@@ -63,6 +64,9 @@ class vtkDataArray;
// Moved inlined constructor and destructor definitions to .C files
// because certain compilers have problems with them.
//
// Kathleen Bonnell, Fri May 8 13:21:18 PDT 2009
// Added defaultErrorValue, useDefaultOnError, and ProcessArguments.
//
// ****************************************************************************
class EXPRESSION_API avtNaturalLogExpression : public avtUnaryMathExpression
......@@ -74,10 +78,13 @@ class EXPRESSION_API avtNaturalLogExpression : public avtUnaryMathExpression
virtual const char *GetType(void) { return "avtNaturalLogExpression"; };
virtual const char *GetDescription(void)
{ return "Calculating natural log"; };
virtual void ProcessArguments(ArgsExpr *, ExprPipelineState *);
protected:
virtual void DoOperation(vtkDataArray *in, vtkDataArray *out,
int ncomponents, int ntuples);
double defaultErrorValue;
bool useDefaultOnError;
};
......
......@@ -160,8 +160,8 @@
</td>
<td width="25%"><p>Array decompose</p>
</td>
<td width="54%"><p>array_decompose(expr1, expr2)</p>
<p>expr1 must evaluate to an array variable. expr2 must evaluate to a number between 0 and the number of scalar components in the array variable minus 1. This expression isolates one scalar variable from an array variable.</p>
<td width="54%"><p>array_decompose(expr<sub>1</sub>, expr<sub>2</sub>)</p>
<p>expr<sub>1</sub> must evaluate to an array variable. expr<sub>2</sub> must evaluate to a number between 0 and the number of scalar components in the array variable minus 1. This expression isolates one scalar variable from an array variable.</p>
<p>Example: array_decompose(array, 0)</p>
</td>
</tr>
......@@ -230,7 +230,7 @@
</td>
<td width="25%"><p>Connectivity-based common mesh field evaluation</p>
</td>
<td width="54%"><p>conn_cmfe(expr1, expr2)</p>
<td width="54%"><p>conn_cmfe(expr<sub>1</sub>, expr<sub>2</sub>)</p>
<p>Examples:</p>
<p><i>Map wave0020.silo's pressure variable the current mesh.</p>
<p></i>conn_cmfe(&lt;wave0020.silo:pressure&gt;, quadmesh)</p>
......@@ -564,9 +564,10 @@
</td>
<td width="25%"><p>Natural logarithm</p>
</td>
<td width="54%"><p>ln(expr)</p>
<p>expr can be a database variable, constant, or other scalar expression. The ln expression computes the natural logarithm of the input scalar expression.</p>
<td width="54%"><p>ln(expr<sub>1</sub>, expr<sub>2</sub>)</p>
<p>expr<sub>1</sub> can be a database variable, constant, or other scalar expression. The ln expression computes the natural logarithm of the input scalar expression. expr<sub>2</sub> is optional and should be a numeric constant. It is used to replace taking the ln of non-positive values in expr<sub>1</sub>, and prevents exceptions being thrown hen they are present.</p>
<p>Example: ln(density)</p>
<p>Example: ln(u, -1e38)</p>
</td>
</tr>
<tr>
......@@ -574,9 +575,10 @@
</td>
<td width="25%"><p>Base 10 logarithm</p>
</td>
<td width="54%"><p>log(expr)</p>
<p>expr can be a database variable, constant, or other scalar expression. The log expression computes the base 10 logarithm of the input scalar expression.</p>
<td width="54%"><p>log(expr<sub>1</sub>, expr<sub>2</sub>)</p>
<p>expr<sub>1</sub> can be a database variable, constant, or other scalar expression. The log expression computes the base 10 logarithm of the input scalar expression. <sub>expr2</sub> is optional and should be a numeric constant. It is used to replace taking the log of non-positive values in expr<sub>1</sub>, and prevents exceptions being thrown in this case.</p>
<p>Example: log(density)</p>
<p>Example: log(u, -1e38)</p>
</td>
</tr>
<tr>
......
......@@ -130,8 +130,8 @@ enhancements and bug-fixes that were added to this release.</p>
<a name="Expression_changes"></a>
<p><b><font size="4">Changes to VisIt's expression language in version 1.12</font></b></p>
<ul>
<li></li>
<li></li>
<li>Added hyperbolic versions of sine, cosine and tangent: sinh, cosh, tanh</li>
<li>Added optional numeric argument for ln and log10 expressions. The value specified will be used in liu of taking ln/log10 of non-positive values and will prevent VisIt from throwing exceptions when non-positive values are encountered.</li>
<li></li>
<li></li>
</ul>
......
......@@ -162,13 +162,19 @@ def ultra_doOp_percurve(curve, t):
usevar = "<%s>"%usevar
if t.cmd in mathOpsNoArg:
newvarDef = "%s(%s)" % (t.cmd, usevar)
if t.cmd == "ln" or t.cmd == "log10":
newvarDef = "%s(%s, -1.0e38)" % (t.cmd, usevar)
createAndApplyExpression(curve, newvarDef, t.cmd)
elif t.cmd in mathOpsXNoArg:
usecmd = mathOpsNoArg[mathOpsXNoArg.index(t.cmd)]
newvarDef = "curve_domain(%s, %s(coord(%s)[0]))" % \
(usevar, usecmd, usevar)
if usecmd == "ln" or t.cmd == "log10":
newvarDef = "curve_domain(%s, %s(coord(%s)[0], -1.0e38))" % \
(usevar, usecmd, usevar)
createAndApplyExpression(curve, newvarDef, t.cmd)
ResetView()
elif t.cmd == 'ymin' or t.cmd == 'xmin':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment