Commit 10d3924c authored by hrchilds's avatar hrchilds

Add support for spatial coordinates to data binning.


git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@16152 18c085ea-50e0-402c-830e-de6fd14e8384
parent b483208c
......@@ -150,8 +150,38 @@ avtDataBinningConstructor::~avtDataBinningConstructor()
// Hank Childs, Sat Aug 21 14:05:14 PDT 2010
// Better support for mixed centering, r2f's that don't require a variable.
//
// Hank Childs, Tue Sep 13 14:17:34 PDT 2011
// Add support for data binning's based on spatial coordinates.
//
// ****************************************************************************
class ValueRetriever
{
public:
virtual double GetValue(int) = 0;
};
class VariableValueRetriever : public ValueRetriever
{
public:
VariableValueRetriever(vtkDataArray *a) { arr = a; };
double GetValue(int v) { return arr->GetTuple1(v); };
private:
vtkDataArray *arr;
};
class CoordinateValueRetriever : public ValueRetriever
{
public:
CoordinateValueRetriever(vtkDataSet *m, int c) { mesh = m; coord = c; };
double GetValue(int v) { double p[3]; mesh->GetPoint(v, p); return p[coord]; };
private:
vtkDataSet *mesh;
int coord;
};
avtDataBinning *
avtDataBinningConstructor::ConstructDataBinning(
ConstructDataBinningAttributes *atts,
......@@ -184,6 +214,29 @@ avtDataBinningConstructor::ConstructDataBinning(
return NULL;
}
}
if ((atts->GetBinType().size() != atts->GetNumBins().size()) &&
(atts->GetBinType().size() != 0))
{
debug1 << "Bin types were specified, but the wrong number were "
<< "specified." << endl;
EXCEPTION1(ImproperUseException,
"If you specify bin types, the number of bin types must "
"match the number of variables.");
return NULL;
}
// For legacy reasons, binType might be a zero-length array. In that
// case, the binType should be assumed to be all "Variable". Make an
// array following this assumption, so coding below can be a bit easier.
int *binType = new int[atts->GetNumBins().size()];
for (i = 0 ; i < atts->GetNumBins().size() ; i++)
{
if (atts->GetBinType().size() == 0)
binType[i] = ConstructDataBinningAttributes::Variable;
else
binType[i] = atts->GetBinType()[i];
}
if (atts->GetNumBins().size() != atts->GetVarnames().size())
{
debug1 << "There must be the same number of samples "
......@@ -239,8 +292,8 @@ avtDataBinningConstructor::ConstructDataBinning(
nvals[i] = atts->GetNumBins()[i];
avtBinningScheme *bs = new avtUniformBinningScheme(nvars, minmax, nvals);
std::vector<std::string> varnames = atts->GetVarnames();
avtDataBinningFunctionInfo *info = new avtDataBinningFunctionInfo(bs, varnames,
atts->GetVarForReductionOperator());
avtDataBinningFunctionInfo *info = new avtDataBinningFunctionInfo(bs,
varnames, atts->GetBinType(), atts->GetVarForReductionOperator());
//
// Now create the "relation-to-function operator".
......@@ -317,7 +370,8 @@ avtDataBinningConstructor::ConstructDataBinning(
if (atts->GetVarForReductionOperator() != "")
dataRequest->AddSecondaryVariable(atts->GetVarForReductionOperator().c_str());
for (i = 0 ; i < atts->GetVarnames().size() ; i++)
dataRequest->AddSecondaryVariable(atts->GetVarnames()[i].c_str());
if (binType[i] == ConstructDataBinningAttributes::Variable)
dataRequest->AddSecondaryVariable(atts->GetVarnames()[i].c_str());
dataRequest->SetTimestep(time);
if (mustReExecute)
GetInput()->Update(spec2);
......@@ -348,14 +402,24 @@ avtDataBinningConstructor::ConstructDataBinning(
{
for (k = 0 ; k < nvars ; k++)
{
const char *varname = info->GetDomainTupleName(k).c_str();
if (leaves[0]->GetPointData()->GetArray(varname) != NULL)
isNodal[k] = true;
else if (leaves[0]->GetCellData()->GetArray(varname)
!= NULL)
isNodal[k] = false;
avtDataBinningFunctionInfo::BinBasedOn bbo =
info->GetBinBasedOnType(k);
if (bbo == avtDataBinningFunctionInfo::VARIABLE)
{
const char *varname=info->GetDomainTupleName(k).c_str();
if (leaves[0]->GetPointData()->GetArray(varname)!=NULL)
isNodal[k] = true;
else if (leaves[0]->GetCellData()->GetArray(varname)
!= NULL)
isNodal[k] = false;
else
hasError = true;
}
else
hasError = true;
{
// Coordinate, so nodal
isNodal[k] = true;
}
}
if (atts->ReductionRequiresVariable())
......@@ -394,7 +458,7 @@ avtDataBinningConstructor::ConstructDataBinning(
return NULL;
}
vtkDataArray **arr = new vtkDataArray*[nvars];
ValueRetriever **val_ret = new ValueRetriever*[nvars];
float *args = new float[nvars];
for (j = 0 ; j < nLeaves ; j++)
{
......@@ -403,10 +467,22 @@ avtDataBinningConstructor::ConstructDataBinning(
: leaves[j]->GetCellData()->GetArray(codomain_varname));
for (k = 0 ; k < nvars ; k++)
{
const char *varname = info->GetDomainTupleName(k).c_str();
arr[k] = (isNodal[k]
? leaves[j]->GetPointData()->GetArray(varname)
: leaves[j]->GetCellData()->GetArray(varname));
avtDataBinningFunctionInfo::BinBasedOn bbo =
info->GetBinBasedOnType(k);
if (bbo == avtDataBinningFunctionInfo::VARIABLE)
{
const char *varname = info->GetDomainTupleName(k).c_str();
vtkDataArray *arr = (isNodal[k]
? leaves[j]->GetPointData()->GetArray(varname)
: leaves[j]->GetCellData()->GetArray(varname));
val_ret[k] = new VariableValueRetriever(arr);
}
else if (bbo == avtDataBinningFunctionInfo::X)
val_ret[k] = new CoordinateValueRetriever(leaves[j], 0);
else if (bbo == avtDataBinningFunctionInfo::Y)
val_ret[k] = new CoordinateValueRetriever(leaves[j], 1);
else if (bbo == avtDataBinningFunctionInfo::Z)
val_ret[k] = new CoordinateValueRetriever(leaves[j], 2);
}
int nvals;
bool doCells = true;
......@@ -459,7 +535,7 @@ avtDataBinningConstructor::ConstructDataBinning(
if (!mixedCentering)
{
for (k = 0 ; k < nvars ; k++)
args[k] = arr[k]->GetTuple1(l);
args[k] = val_ret[k]->GetValue(l);
int binId = bs->GetBinId(args);
float cval = 0.;
if (atts->ReductionRequiresVariable())
......@@ -475,9 +551,9 @@ avtDataBinningConstructor::ConstructDataBinning(
vtkIdType ptId = cell->GetPointId(p);
for (k = 0 ; k < nvars ; k++)
if (isNodal[k])
args[k] = arr[k]->GetTuple1(ptId);
args[k] = val_ret[k]->GetValue(ptId);
else
args[k] = arr[k]->GetTuple1(l);
args[k] = val_ret[k]->GetValue(l);
int binId = bs->GetBinId(args);
float cval = 0;
if (atts->ReductionRequiresVariable())
......@@ -490,7 +566,9 @@ avtDataBinningConstructor::ConstructDataBinning(
}
}
}
delete [] arr;
for (j = 0 ; j < nvars ; j++)
delete val_ret[j];
delete [] val_ret;
delete [] args;
delete [] leaves;
delete [] isNodal;
......@@ -510,6 +588,7 @@ avtDataBinningConstructor::ConstructDataBinning(
delete R2Foperator;
delete [] minmax;
delete [] nvals;
delete [] binType;
// Don't delete binning scheme (bs) function info (info), or "vals"
// since the data binning now owns them.
......
......@@ -57,10 +57,17 @@ using std::vector;
// Programmer: Hank Childs
// Creation: February 12, 2006
//
// Modifications:
//
// Hank Childs, Mon Aug 1 06:48:26 PDT 2011
// Add support for bin types.
//
// ****************************************************************************
avtDataBinningFunctionInfo::avtDataBinningFunctionInfo(avtBinningScheme *bs,
const vector<string> &tn, const string &cv)
const vector<string> &tn,
const vector<unsigned char> &bn,
const string &cv)
{
if (tn.size() <= 0)
{
......@@ -68,6 +75,8 @@ avtDataBinningFunctionInfo::avtDataBinningFunctionInfo(avtBinningScheme *bs,
}
binningScheme = bs;
for (int i = 0 ; i < bn.size() ; i++)
binBasedOn.push_back((BinBasedOn) bn[i]);
tupleNames = tn;
codomainVariable = cv;
}
......@@ -110,3 +119,30 @@ avtDataBinningFunctionInfo::GetDomainTupleName(int idx) const
}
// ****************************************************************************
// Method: avtDataBinningFunctionInfo::GetBinBasedOnType
//
// Purpose:
// Get the category of for the bin ... is it based on X, Y, Z, or a
// variable.
//
// Programmer: Hank Childs
// Creation: August 1, 2011
//
// ****************************************************************************
avtDataBinningFunctionInfo::BinBasedOn
avtDataBinningFunctionInfo::GetBinBasedOnType(int idx) const
{
if (binBasedOn.size() == 0)
return VARIABLE;
if (idx < 0 || idx >= binBasedOn.size())
{
EXCEPTION2(BadIndexException, idx, binBasedOn.size());
}
return binBasedOn[idx];
}
......@@ -74,28 +74,39 @@ class avtBinningScheme;
// Hank Childs, Sat Aug 21 14:05:14 PDT 2010
// Renamed from DDF to DataBinning.
//
// Hank Childs, Mon Aug 1 06:48:26 PDT 2011
// Add support for spatial coordinates.
//
// ****************************************************************************
class AVTDBIN_API avtDataBinningFunctionInfo
{
public:
avtDataBinningFunctionInfo(avtBinningScheme *,
const std::vector<std::string> &,
const std::string &);
typedef enum
{
VARIABLE, X, Y, Z
} BinBasedOn;
avtDataBinningFunctionInfo(avtBinningScheme *,
const std::vector<std::string> &,
const std::vector<unsigned char> &,
const std::string &);
virtual ~avtDataBinningFunctionInfo();
int GetDomainNumberOfTuples(void) const
{ return tupleNames.size(); };
const std::string &GetDomainTupleName(int) const;
BinBasedOn GetBinBasedOnType(int) const;
const std::string &GetCodomainName(void) const
{ return codomainVariable; };
avtBinningScheme *GetBinningScheme(void)
{ return binningScheme; };
private:
avtBinningScheme *binningScheme;
std::vector<std::string> tupleNames;
std::string codomainVariable;
avtBinningScheme *binningScheme;
std::vector<std::string> tupleNames;
std::vector<BinBasedOn> binBasedOn;
std::string codomainVariable;
};
......
......@@ -153,6 +153,44 @@ ConstructDataBinningAttributes::OutOfBoundsBehavior_FromString(const std::string
return false;
}
//
// Enum conversion methods for ConstructDataBinningAttributes::BinType
//
static const char *BinType_strings[] = {
"Variable", "X", "Y",
"Z"};
std::string
ConstructDataBinningAttributes::BinType_ToString(ConstructDataBinningAttributes::BinType t)
{
int index = int(t);
if(index < 0 || index >= 4) index = 0;
return BinType_strings[index];
}
std::string
ConstructDataBinningAttributes::BinType_ToString(int t)
{
int index = (t < 0 || t >= 4) ? 0 : t;
return BinType_strings[index];
}
bool
ConstructDataBinningAttributes::BinType_FromString(const std::string &s, ConstructDataBinningAttributes::BinType &val)
{
val = ConstructDataBinningAttributes::Variable;
for(int i = 0; i < 4; ++i)
{
if(s == BinType_strings[i])
{
val = (BinType)i;
return true;
}
}
return false;
}
// ****************************************************************************
// Method: ConstructDataBinningAttributes::ConstructDataBinningAttributes
//
......@@ -201,6 +239,7 @@ void ConstructDataBinningAttributes::Copy(const ConstructDataBinningAttributes &
{
name = obj.name;
varnames = obj.varnames;
binType = obj.binType;
binBoundaries = obj.binBoundaries;
reductionOperator = obj.reductionOperator;
varForReductionOperator = obj.varForReductionOperator;
......@@ -371,6 +410,7 @@ ConstructDataBinningAttributes::operator == (const ConstructDataBinningAttribute
// Create the return value
return ((name == obj.name) &&
(varnames == obj.varnames) &&
(binType == obj.binType) &&
(binBoundaries == obj.binBoundaries) &&
(reductionOperator == obj.reductionOperator) &&
(varForReductionOperator == obj.varForReductionOperator) &&
......@@ -527,6 +567,7 @@ ConstructDataBinningAttributes::SelectAll()
{
Select(ID_name, (void *)&name);
Select(ID_varnames, (void *)&varnames);
Select(ID_binType, (void *)&binType);
Select(ID_binBoundaries, (void *)&binBoundaries);
Select(ID_reductionOperator, (void *)&reductionOperator);
Select(ID_varForReductionOperator, (void *)&varForReductionOperator);
......@@ -582,6 +623,12 @@ ConstructDataBinningAttributes::CreateNode(DataNode *parentNode, bool completeSa
node->AddNode(new DataNode("varnames", varnames));
}
if(completeSave || !FieldsEqual(ID_binType, &defaultObject))
{
addToParent = true;
node->AddNode(new DataNode("binType", binType));
}
if(completeSave || !FieldsEqual(ID_binBoundaries, &defaultObject))
{
addToParent = true;
......@@ -688,6 +735,8 @@ ConstructDataBinningAttributes::SetFromNode(DataNode *parentNode)
SetName(node->AsString());
if((node = searchNode->GetNode("varnames")) != 0)
SetVarnames(node->AsStringVector());
if((node = searchNode->GetNode("binType")) != 0)
SetBinType(node->AsUnsignedCharVector());
if((node = searchNode->GetNode("binBoundaries")) != 0)
SetBinBoundaries(node->AsDoubleVector());
if((node = searchNode->GetNode("reductionOperator")) != 0)
......@@ -772,6 +821,13 @@ ConstructDataBinningAttributes::SetVarnames(const stringVector &varnames_)
Select(ID_varnames, (void *)&varnames);
}
void
ConstructDataBinningAttributes::SetBinType(const unsignedCharVector &binType_)
{
binType = binType_;
Select(ID_binType, (void *)&binType);
}
void
ConstructDataBinningAttributes::SetBinBoundaries(const doubleVector &binBoundaries_)
{
......@@ -877,6 +933,18 @@ ConstructDataBinningAttributes::GetVarnames()
return varnames;
}
const unsignedCharVector &
ConstructDataBinningAttributes::GetBinType() const
{
return binType;
}
unsignedCharVector &
ConstructDataBinningAttributes::GetBinType()
{
return binType;
}
const doubleVector &
ConstructDataBinningAttributes::GetBinBoundaries() const
{
......@@ -977,6 +1045,12 @@ ConstructDataBinningAttributes::SelectVarnames()
Select(ID_varnames, (void *)&varnames);
}
void
ConstructDataBinningAttributes::SelectBinType()
{
Select(ID_binType, (void *)&binType);
}
void
ConstructDataBinningAttributes::SelectBinBoundaries()
{
......@@ -1021,6 +1095,7 @@ ConstructDataBinningAttributes::GetFieldName(int index) const
{
case ID_name: return "name";
case ID_varnames: return "varnames";
case ID_binType: return "binType";
case ID_binBoundaries: return "binBoundaries";
case ID_reductionOperator: return "reductionOperator";
case ID_varForReductionOperator: return "varForReductionOperator";
......@@ -1058,6 +1133,7 @@ ConstructDataBinningAttributes::GetFieldType(int index) const
{
case ID_name: return FieldType_string;
case ID_varnames: return FieldType_stringVector;
case ID_binType: return FieldType_ucharVector;
case ID_binBoundaries: return FieldType_doubleVector;
case ID_reductionOperator: return FieldType_enum;
case ID_varForReductionOperator: return FieldType_string;
......@@ -1095,6 +1171,7 @@ ConstructDataBinningAttributes::GetFieldTypeName(int index) const
{
case ID_name: return "string";
case ID_varnames: return "stringVector";
case ID_binType: return "ucharVector";
case ID_binBoundaries: return "doubleVector";
case ID_reductionOperator: return "enum";
case ID_varForReductionOperator: return "string";
......@@ -1142,6 +1219,11 @@ ConstructDataBinningAttributes::FieldsEqual(int index_, const AttributeGroup *rh
retval = (varnames == obj.varnames);
}
break;
case ID_binType:
{ // new scope
retval = (binType == obj.binType);
}
break;
case ID_binBoundaries:
{ // new scope
retval = (binBoundaries == obj.binBoundaries);
......
Target: xml2python
Code: PyConstructDataBinningAttributes_setattr
Prefix:
Postfix:
// try to handle old ddf attributes
if(strcmp(name, "ddfName") == 0)
obj = ConstructDataBinningAttributes_SetName(self, tuple);
else if(strcmp(name, "ranges") == 0)
obj = ConstructDataBinningAttributes_SetBinBoundaries(self, tuple);
else if(strcmp(name, "statisticalOperator") == 0)
obj = ConstructDataBinningAttributes_SetReductionOperator(self, tuple);
else if(strcmp(name, "codomainName") == 0)
obj = ConstructDataBinningAttributes_SetVarForReductionOperator(self, tuple);
else if(strcmp(name, "numSamples") == 0)
obj = ConstructDataBinningAttributes_SetNumBins(self, tuple);
Code: PyConstructDataBinningAttributes_getattr
Prefix:
Postfix:
......@@ -31,6 +14,21 @@ Postfix:
if(strcmp(name, "numSamples") == 0)
return ConstructDataBinningAttributes_GetNumBins(self, NULL);
Code: PyConstructDataBinningAttributes_setattr
Prefix:
Postfix:
// try to handle old ddf attributes
if(strcmp(name, "ddfName") == 0)
obj = ConstructDataBinningAttributes_SetName(self, tuple);
else if(strcmp(name, "ranges") == 0)
obj = ConstructDataBinningAttributes_SetBinBoundaries(self, tuple);
else if(strcmp(name, "statisticalOperator") == 0)
obj = ConstructDataBinningAttributes_SetReductionOperator(self, tuple);
else if(strcmp(name, "codomainName") == 0)
obj = ConstructDataBinningAttributes_SetVarForReductionOperator(self, tuple);
else if(strcmp(name, "numSamples") == 0)
obj = ConstructDataBinningAttributes_SetNumBins(self, tuple);
Target: xml2atts
Function: ReductionRequiresVariable
Declaration: bool ReductionRequiresVariable(void);
......
......@@ -83,6 +83,13 @@ public:
Clamp,
Discard
};
enum BinType
{
Variable,
X,
Y,
Z
};
// These constructors are for objects of this class
ConstructDataBinningAttributes();
......@@ -111,6 +118,7 @@ public:
virtual void SelectAll();
void SelectName();
void SelectVarnames();
void SelectBinType();
void SelectBinBoundaries();
void SelectVarForReductionOperator();
void SelectNumBins();
......@@ -118,6 +126,7 @@ public:
// Property setting methods
void SetName(const std::string &name_);
void SetVarnames(const stringVector &varnames_);
void SetBinType(const unsignedCharVector &binType_);
void SetBinBoundaries(const doubleVector &binBoundaries_);
void SetReductionOperator(ReductionOperator reductionOperator_);
void SetVarForReductionOperator(const std::string &varForReductionOperator_);
......@@ -131,24 +140,26 @@ public:
void SetOutOfBoundsBehavior(OutOfBoundsBehavior outOfBoundsBehavior_);
// Property getting methods
const std::string &GetName() const;
std::string &GetName();
const stringVector &GetVarnames() const;
stringVector &GetVarnames();
const doubleVector &GetBinBoundaries() const;
doubleVector &GetBinBoundaries();
ReductionOperator GetReductionOperator() const;
const std::string &GetVarForReductionOperator() const;
std::string &GetVarForReductionOperator();
double GetUndefinedValue() const;
BinningScheme GetBinningScheme() const;
const intVector &GetNumBins() const;
intVector &GetNumBins();
bool GetOverTime() const;
int GetTimeStart() const;
int GetTimeEnd() const;
int GetTimeStride() const;
OutOfBoundsBehavior GetOutOfBoundsBehavior() const;
const std::string &GetName() const;
std::string &GetName();
const stringVector &GetVarnames() const;
stringVector &GetVarnames();
const unsignedCharVector &GetBinType() const;
unsignedCharVector &GetBinType();
const doubleVector &GetBinBoundaries() const;
doubleVector &GetBinBoundaries();
ReductionOperator GetReductionOperator() const;
const std::string &GetVarForReductionOperator() const;
std::string &GetVarForReductionOperator();
double GetUndefinedValue() const;
BinningScheme GetBinningScheme() const;
const intVector &GetNumBins() const;
intVector &GetNumBins();
bool GetOverTime() const;
int GetTimeStart() const;
int GetTimeEnd() const;
int GetTimeStride() const;
OutOfBoundsBehavior GetOutOfBoundsBehavior() const;
// Persistence methods
virtual bool CreateNode(DataNode *node, bool completeSave, bool forceAdd);
......@@ -170,6 +181,11 @@ public:
protected:
static std::string OutOfBoundsBehavior_ToString(int);
public:
static std::string BinType_ToString(BinType);
static bool BinType_FromString(const std::string &, BinType &);
protected:
static std::string BinType_ToString(int);
public:
// Keyframing methods
virtual std::string GetFieldName(int index) const;
......@@ -184,6 +200,7 @@ public:
enum {
ID_name = 0,
ID_varnames,
ID_binType,
ID_binBoundaries,
ID_reductionOperator,
ID_varForReductionOperator,
......@@ -199,24 +216,25 @@ public:
};
private:
std::string name;
stringVector varnames;
doubleVector binBoundaries;
int reductionOperator;
std::string varForReductionOperator;
double undefinedValue;
int binningScheme;
intVector numBins;
bool overTime;
int timeStart;
int timeEnd;
int timeStride;
int outOfBoundsBehavior;
std::string name;
stringVector varnames;
unsignedCharVector binType;
doubleVector binBoundaries;
int reductionOperator;
std::string varForReductionOperator;
double undefinedValue;
int binningScheme;
intVector numBins;
bool overTime;
int timeStart;
int timeEnd;
int timeStride;
int outOfBoundsBehavior;
// Static class format string for type map.
static const char *TypeMapFormatString;
static const private_tmfs_t TmfsStruct;
};
#define CONSTRUCTDATABINNINGATTRIBUTES_TMFS "ss*d*isdii*biiii"
#define CONSTRUCTDATABINNINGATTRIBUTES_TMFS "ss*u*d*isdii*biiii"
#endif
......@@ -19,10 +19,18 @@
Clamp
Discard
</Enum>
<Enum name="BinType">
Variable
X
Y
Z
</Enum>
<Field name="name" label="name" type="string">
</Field>
<Field name="varnames" label="varnames" type="stringVector">
</Field>
<Field name="binType" label="binType" type="ucharVector">
</Field>
<Field name="binBoundaries" label="binBoundaries" type="doubleVector">
</Field>
<Field name="reductionOperator" label="reduction operator" type="enum" subtype="ReductionOperator">
......
......@@ -39,6 +39,7 @@
package llnl.visit;
import java.util.Vector;
import java.lang.Byte;
import java.lang.Double;
import java.lang.Integer;
......@@ -59,7 +60,7 @@ import java.lang.Integer;
public class ConstructDataBinningAttributes extends AttributeSubject
{
private static int ConstructDataBinningAttributes_numAdditionalAtts = 13;
private static int ConstructDataBinningAttributes_numAdditionalAtts = 14;
// Enum values
public final static int BINNINGSCHEME_UNIFORM = 0;
......@@ -78,6 +79,11 @@ public class ConstructDataBinningAttributes extends AttributeSubject
public final static int OUTOFBOUNDSBEHAVIOR_CLAMP = 0;
public final static int OUTOFBOUNDSBEHAVIOR_DISCARD = 1;
public final static int BINTYPE_VARIABLE = 0;
public final static int BINTYPE_X = 1;
public final static int BINTYPE_Y = 2;
public final static int BINTYPE_Z = 3;
public ConstructDataBinningAttributes()
{
......@@ -85,6 +91,7 @@ public class ConstructDataBinningAttributes extends AttributeSubject
name = new String("");
varnames = new Vector();
binType = new Vector();
binBoundaries = new Vector();
reductionOperator = REDUCTIONOPERATOR_AVERAGE;
varForReductionOperator = new String("");
......@@ -104,6 +111,7 @@ public class ConstructDataBinningAttributes extends AttributeSubject