Commit a3ced84d authored by bonnell's avatar bonnell
Browse files

Add ability for Time Picks to be performed on multiple variables

git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@14295 18c085ea-50e0-402c-830e-de6fd14e8384
parent cb397e81
......@@ -174,6 +174,10 @@ avtCurveConstructorFilter::~avtCurveConstructorFilter()
// Kathleen Bonnell, Tue Dec 14 12:57:14 PST 2010
// Ensure the output variable is named.
//
// Kathleen Bonnell, Thu Feb 17 09:19:06 PST 2011
// Moved bulk of dataset construction into CreateSingleOutput method,
// which will allow creation of multiple outputs when necessary.
//
// ****************************************************************************
void avtCurveConstructorFilter::Execute()
......@@ -265,28 +269,91 @@ void avtCurveConstructorFilter::Execute()
return;
}
avtDataTree_p outTree;
stringVector labels;
inTree->GetAllLabels(labels);
if (labels.size() == 0)
{
vtkDataSet *outGrid;
outGrid = CreateSingleOutput(inTree);
if (outGrid == NULL)
{
SetOutputDataTree(inTree);
return;
}
const char *vname = (pipelineVariable != NULL ? pipelineVariable : "");
avtDataRepresentation dr(outGrid, -1, vname);
outTree = new avtDataTree(dr);
outGrid->Delete();
}
else
{
vtkDataSet **ds = new vtkDataSet *[labels.size()];
for (size_t i = 0; i < labels.size(); ++i)
{
ds[i] = NULL;
avtDataTree_p oneTree = inTree->PruneTree(labels[i]);
ds[i] = CreateSingleOutput(oneTree);
if (ds[i] == NULL)
{
for (size_t j = 0; j < i; ++j)
{
if (ds[j] != NULL)
ds[j]->Delete();
}
delete [] ds;
SetOutputDataTree(inTree);
return;
}
}
outTree = new avtDataTree(labels.size(), ds, -1, labels);
}
SetOutputDataTree(outTree);
}
// ****************************************************************************
// Method: avtCurveConstructorFilter::CreateSingleOutput
//
// Notes: Moved from Execute mthod.
//
// Purpose:
// Does the actual VTK code to modify the dataset.
//
// Arguments:
// inTree The input data tree.
//
// Returns: The output dataset.
//
// Programmer: Kathleen Bonnell
// Creation: February 17, 2011
//
// Modifications:
//
// ****************************************************************************
vtkDataSet *
avtCurveConstructorFilter::CreateSingleOutput(avtDataTree_p inTree)
{
//
// This filter doesn't do much right now. Basically just a
// "connect-the-dots" between the vertices.
//
int nleaves, j, k;
double x;
avtDataTree_p outTree;
vtkDataSet **ds;
ds = inTree->GetAllLeaves(nleaves);
if (nleaves == 0)
{
// Kind of a bizarre error, since "IsEmpty" above should have returned
// true. This situation does occur, and it is a little dangerous to
// change the behavior of IsEmpty, so just accomodate.
delete [] ds;
SetOutputDataTree(inTree);
return;
return NULL;
}
DoubleIntMap minX;
//
......@@ -474,16 +541,12 @@ void avtCurveConstructorFilter::Execute()
// make sure the outputvar is named.
sortedVal->SetName(varname);
avtDataRepresentation dr(outGrid, -1, varname);
outTree = new avtDataTree(dr);
outGrid->Delete();
SetOutputDataTree(outTree);
//
// Clean up.
//
delete [] ds;
return outGrid;
}
// ****************************************************************************
......
......@@ -78,6 +78,9 @@
// Kathleen Bonnell, Mon Mar 23 09:53:17 PDT 2009
// Removed 'ForceConstruction'.
//
// Kathleen Bonnell, Thu Feb 17 09:18:43 PST 2011
// Added CreateSingeOutput method.
//
// ****************************************************************************
class AVTFILTERS_API avtCurveConstructorFilter : public avtDatasetToDatasetFilter
......@@ -93,6 +96,8 @@ class AVTFILTERS_API avtCurveConstructorFilter : public avtDatasetToDatasetFilte
protected:
doubleVector outputArray;
vtkDataSet *CreateSingleOutput(avtDataTree_p inTree);
virtual void Execute(void);
virtual void PostExecute(void);
virtual void VerifyInput(void);
......
......@@ -1540,3 +1540,30 @@ avtDataTree::DebugDump(avtWebpage *webpage, const char *prefix,
}
// ****************************************************************************
// Method: avtDataTree::PruneTree
//
// Purpose:
// Prunes tree based on single label.
//
// Returns:
// The pruned tree.
//
// Arguments:
// label The label that we want to include in the pruned tree.
//
// Programmer: Kathleen Bonnell
// Creation: February 16, 2011
//
// Modifications:
//
// ****************************************************************************
avtDataTree_p
avtDataTree::PruneTree(const string &label)
{
vector<string> sv;
sv.push_back(label);
return PruneTree(sv);
}
......@@ -124,6 +124,9 @@ typedef void (*TraverseFunc)(avtDataRepresentation &, void *, bool &);
// won't insert a second, undesired assignment operator that does have
// a const argument (and is used unexpectedly).
//
// Kathleen Bonnell, Thu Feb 17 09:16:46 PST 2011
// Added a PruneTree method that accepts a single string.
//
// ****************************************************************************
class PIPELINE_API avtDataTree
......@@ -171,6 +174,7 @@ class PIPELINE_API avtDataTree
avtDataTree_p PruneTree(const vector<int> &);
avtDataTree_p PruneTree(const vector<int> &, vector<int> &);
avtDataTree_p PruneTree(const vector<string> &);
avtDataTree_p PruneTree(const string &);
avtDataTree_p PruneTree(const vector<string> &, vector<string>&);
void WriteTreeStructure(ostream &, int indent = 0);
......
......@@ -53,7 +53,6 @@
// Method: avtLabeledCurveMapper constructor
//
// Arguments:
// l The label this mapper should use.
//
// Programmer: Kathleen Bonnell
// Creation: July 12, 2002
......@@ -68,7 +67,7 @@
//
// ****************************************************************************
avtLabeledCurveMapper::avtLabeledCurveMapper()
avtLabeledCurveMapper::avtLabeledCurveMapper(): labels(), actorsInputNum()
{
label = "";
labelVis = true;
......@@ -181,6 +180,10 @@ avtLabeledCurveMapper::SetUpFilters(int nInputs)
// Kathleen Bonnell, Mon Sep 15 13:33:52 PDT 2003
// Don't assume input contains cells and/or points.
//
// Kathleen Bonnell, Thu Feb 17 09:14:55 PST 2011
// Use label associated with input if multiple labels set.
// Keep track of input number an actor is associated with.
//
// ****************************************************************************
void
......@@ -213,10 +216,18 @@ avtLabeledCurveMapper::SetDatasetInput(vtkDataSet *ds, int inNum)
points->GetPoint(i, pos);
avtLabelActor_p la = new avtLabelActor;
la->SetAttachmentPoint(pos);
la->SetDesignator(label.c_str());
if (labels.size() > 0)
{
la->SetDesignator(labels[inNum].c_str());
}
else
{
la->SetDesignator(label.c_str());
}
la->SetForegroundColor(labelColor);
la->SetScale(scale);
actors.push_back(la);
actorsInputNum.push_back(inNum);
}
}
......@@ -371,3 +382,28 @@ avtLabeledCurveMapper::SetLabelVisibility(bool labelsOn)
}
}
// ****************************************************************************
// Method: avtLabeledCurveMapper::SetLabels
//
// Purpose:
// Sets the labels to be used by this mapper.
//
// Arguments:
// l The new labels.
//
// Programmer: Kathleen Bonnell
// Creation: February 16, 2011l
//
// Modifications:
//
// ****************************************************************************
void
avtLabeledCurveMapper::SetLabels(std::vector<std::string> &l)
{
labels = l;
for (int i = 0; i < actors.size(); i++)
{
actors[i]->SetDesignator(labels[actorsInputNum[i]].c_str());
}
}
......@@ -65,6 +65,10 @@ class vtkDataSet;
// Kathleen Bonnell, Tue Jul 23 15:01:55 PDT 2002
// Added member to keep track of label visibility.
//
// Kathleen Bonnell, Thu Feb 17 09:09:41 PST 2011
// Add ability to set multiple labels, keep track of which input an actor
// is associated with.
//
// ****************************************************************************
class PLOTTER_API avtLabeledCurveMapper : public avtDecorationsMapper
......@@ -76,11 +80,14 @@ class PLOTTER_API avtLabeledCurveMapper : public avtDecorationsMapper
void SetLabelColor(double [3]);
void SetLabelColor(double, double, double);
void SetLabel(std::string &);
void SetLabels(std::vector<std::string> &);
void SetScale(double);
void SetLabelVisibility(bool);
protected:
std::string label;
std::vector<std::string> labels;
std::vector<int> actorsInputNum;
bool labelVis;
double labelColor[3];
double scale;
......
......@@ -102,6 +102,9 @@ class vtkDataSet;
// Cyrus Harrison, Tue Dec 18 08:16:10 PST 2007
// Added GetXmlResult(), SetXmlResult() and xmlResult.
//
// Kathleen Bonnell, Tue Mar 1 15:59:48 PST 2011
// Removed AddResultValue, not used.
//
// ****************************************************************************
class QUERY_API avtDatasetQuery : public avtDataObjectQuery,
......@@ -120,8 +123,6 @@ class QUERY_API avtDatasetQuery : public avtDataObjectQuery,
virtual double GetResultValue(const int i = 0);
virtual void SetResultValue(const double &d, const int i = 0);
virtual void AddResultValue(const double &d)
{ resValue.push_back(d); };
virtual doubleVector GetResultValues(void) { return resValue; };
virtual void SetResultValues(const doubleVector &d)
{ resValue = d; };
......
......@@ -299,8 +299,12 @@ avtQueryFactory::Instance()
// Cyrus Harrison, Tue Sep 21 11:12:17 PDT 2010
// Added explicit passing of args to the python filter query.
//
// Dave Pugmire, Tue Nov 9 14:57:20 EST 2010
// Add Streamline Info query.
// Dave Pugmire, Tue Nov 9 14:57:20 EST 2010
// Add Streamline Info query.
//
// Kathleen Bonnell, Thu Feb 17 09:51:44 PST 2011
// Set number of vars for LocateAndPickNode/Zone queries, and
// VariableyByNode/Zone queries.
//
// ****************************************************************************
......@@ -484,11 +488,15 @@ avtQueryFactory::CreateQuery(const QueryAttributes *qa)
}
else if (qname == "Variable by Zone")
{
query = new avtVariableByZoneQuery();
avtVariableByZoneQuery *vzq = new avtVariableByZoneQuery();
vzq->SetNumVars((int)qa->GetVariables().size());
query = vzq;
}
else if (qname == "Variable by Node")
{
query = new avtVariableByNodeQuery();
avtVariableByNodeQuery *vnq = new avtVariableByNodeQuery();
vnq->SetNumVars((int)qa->GetVariables().size());
query = vnq;
}
else if (qname == "MinMax")
{
......@@ -619,11 +627,15 @@ avtQueryFactory::CreateQuery(const QueryAttributes *qa)
}
else if( qname == "Locate and Pick Zone")
{
query = new avtLocateAndPickZoneQuery();
avtLocateAndPickZoneQuery *lpzq = new avtLocateAndPickZoneQuery();
lpzq->SetNumVars((int)qa->GetVariables().size());
query = lpzq;
}
else if( qname == "Locate and Pick Node")
{
query = new avtLocateAndPickNodeQuery();
avtLocateAndPickNodeQuery *lpnq = new avtLocateAndPickNodeQuery();
lpnq->SetNumVars((int)qa->GetVariables().size());
query = lpnq;
}
else if( qname == "Shapelet Decomposition")
{
......
......@@ -407,6 +407,9 @@ avtQueryOverTimeFilter::FilterSupportsTimeParallelization(void)
// Hank Childs, Thu Aug 26 13:47:30 PDT 2010
// Change extents names.
//
// Kathleen Bonnell, Thu Mar 3 12:40:41 PST 2011
// Set output Atts labels to be the variable names used for the query.
//
// ****************************************************************************
void
......@@ -457,7 +460,7 @@ avtQueryOverTimeFilter::UpdateDataObjectInfo(void)
outAtts.SetXUnits(atts.GetQueryAtts().GetXUnits());
outAtts.SetYUnits(atts.GetQueryAtts().GetYUnits());
}
outAtts.SetLabels(atts.GetQueryAtts().GetVariables());
double bounds[6];
avtDataset_p ds = GetTypedOutput();
avtDatasetExaminer::GetSpatialExtents(ds, bounds);
......@@ -508,6 +511,10 @@ avtQueryOverTimeFilter::SetSILAtts(const SILRestrictionAttributes *silAtts)
// Hank Childs, Fri Dec 24 21:01:29 PST 2010
// Add support for parallelization over time.
//
// Kathleen Bonnell, Thu Mar 3 12:42:35 PST 2011
// In support of multiple-variable time picks, create an output Tree instead
// of a single grid.
//
// ****************************************************************************
void
......@@ -575,7 +582,7 @@ avtQueryOverTimeFilter::CreateFinalOutput()
SetOutputDataTree(dummy);
return;
}
if (useTimeForXAxis && qRes.size() != times.size())
if (useTimeForXAxis && qRes.size()/nResultsToStore != times.size())
{
debug4 << "QueryOverTime ERROR, number of results ("
<< qRes.size() << ") does not equal number "
......@@ -610,23 +617,25 @@ avtQueryOverTimeFilter::CreateFinalOutput()
avtCallback::IssueWarning(osm.str());
}
vtkRectilinearGrid *outgrid = CreateRGrid(times, qRes);
avtDataTree_p tree = new avtDataTree(outgrid, 0);
outgrid->Delete();
stringVector vars = atts.GetQueryAtts().GetVariables();
bool multiCurve = atts.GetQueryAtts().GetTimeCurvePlotType() == QueryAttributes::Multiple_Y_Axes;
avtDataTree_p tree = CreateTree(times, qRes, vars, multiCurve);
SetOutputDataTree(tree);
finalOutputCreated = true;
}
// ****************************************************************************
// Method: CreateRGrid
// Method: CreateTree
//
// Purpose:
// Creates a 1D Rectilinear dataset with point data scalars.
// Creates a 1D Rectilinear datasets with point data scalars.
//
// Arguments:
// x The values to use for x-coordinates.
// y The values to use for point data scalars.
// times The values to use for x-coordinates.
// res The values to use for point data scalars.
// vars The variables associated with each output.
// doMultiCurvePlot The type of plot to create.
//
// Programmer: Kathleen Bonnell
// Creation: March 15, 2004
......@@ -638,13 +647,20 @@ avtQueryOverTimeFilter::CreateFinalOutput()
// Kathleen Bonnell, Thu Jul 27 17:43:38 PDT 2006
// Renamed from CreatePolys to CreateRGrid.
//
// Kathleen Bonnell, Thu Feb 17 09:43:16 PST 2011
// Renamed from CreateRGrid to CreateTree, to reflect the possibility
// of creating multiple outputs. Added vars and doMultiCurvePlot args.
//
// ****************************************************************************
vtkRectilinearGrid *
avtQueryOverTimeFilter::CreateRGrid(const doubleVector &times,
const doubleVector &res)
avtDataTree_p
avtQueryOverTimeFilter::CreateTree(const doubleVector &times,
const doubleVector &res,
stringVector &vars,
const bool doMultiCurvePlot)
{
int nPts = 0;
bool singleCurve = true;
if (useTimeForXAxis && nResultsToStore == 1)
{
// Single curve with time for x axis. NORMAL case.
......@@ -658,44 +674,162 @@ avtQueryOverTimeFilter::CreateRGrid(const doubleVector &times,
}
else if (useTimeForXAxis && nResultsToStore > 1)
{
// Create multiple curves with time as x-axis
// NOT IMPLEMENTED YET, need to create multiple
// vtkPolyData objects, but pipeline for the Curve
// plot not yet set up correctly.
singleCurve = false;
}
else if (!useTimeForXAxis && nResultsToStore > 2)
{
// multiple curves, res[odd] = x, res[even] = y.
}
vtkRectilinearGrid *rgrid = vtkVisItUtility::Create1DRGrid(nPts);
if (singleCurve)
{
vtkRectilinearGrid *rgrid = vtkVisItUtility::Create1DRGrid(nPts);
if (nPts == 0)
return rgrid;
if (nPts == 0)
{
avtDataTree_p tree = new avtDataTree(rgrid, 0);
rgrid->Delete();
return tree;
}
vtkDataArray *xc = rgrid->GetXCoordinates();
vtkFloatArray *sc = vtkFloatArray::New();
vtkDataArray *xc = rgrid->GetXCoordinates();
vtkFloatArray *sc = vtkFloatArray::New();
sc->SetNumberOfComponents(1);
sc->SetNumberOfTuples(nPts);
sc->SetNumberOfComponents(1);
sc->SetNumberOfTuples(nPts);
rgrid->GetPointData()->SetScalars(sc);
rgrid->SetDimensions(nPts, 1 , 1);
rgrid->GetPointData()->SetScalars(sc);
rgrid->SetDimensions(nPts, 1 , 1);
sc->Delete();
sc->Delete();
for (int i = 0; i < nPts; i++)
for (int i = 0; i < nPts; i++)
{
if (useTimeForXAxis)
{
xc->SetTuple1(i, times[i]);
sc->SetTuple1(i, res[i]);
}
else
{
xc->SetTuple1(i, res[i*2]);
sc->SetTuple1(i, res[i*2+1]);
}
}
avtDataTree_p tree = new avtDataTree(rgrid, 0);
rgrid->Delete();
return tree;
}
else if(doMultiCurvePlot)
{
if (useTimeForXAxis)
// Setup for a MultiCurve plot
nPts = times.size();
vtkRectilinearGrid *rgrid =
vtkVisItUtility::CreateEmptyRGrid(nPts, nResultsToStore, 1, VTK_FLOAT);
if (nPts == 0)
{
avtDataTree_p tree = new avtDataTree(rgrid, 0);
rgrid->Delete();
return tree;
}
if (res.size() != nPts*nResultsToStore)
{
debug1 << "Mismatch in QOT times/results sizes: " << endl;
debug1 << " times size: " << times.size() << endl;
debug1 << " nResultsToStore: " << nResultsToStore << endl;
debug1 << " results size: " << res.size() << endl;
avtDataTree_p tree = new avtDataTree(rgrid, 0);
rgrid->Delete();
return tree;
}
vtkDataArray *xc = rgrid->GetXCoordinates();
vtkDataArray *yc = rgrid->GetYCoordinates();
vtkFloatArray *sc = vtkFloatArray::New();
sc->SetNumberOfComponents(1);
sc->SetNumberOfTuples(nPts*nResultsToStore);
rgrid->GetPointData()->SetScalars(sc);
sc->Delete();
for (int i = 0; i < nPts; i++)
{
xc->SetTuple1(i, times[i]);
sc->SetTuple1(i, res[i]);
}
else
for (int i = 0; i < nResultsToStore; i++)
{
yc->SetTuple1(i, i);
for (int j = 0; j < nPts; j++)
sc->SetTuple1(i*nPts+j, res[i + nResultsToStore*j]);
}
avtDataTree_p tree = new avtDataTree(rgrid, 0);
rgrid->Delete();
return tree;
}
else
{
// Setup for a Curve plot with multiple curves.
nPts = times.size();
if (nPts == 0)
{
vtkRectilinearGrid *rgrid =
vtkVisItUtility::Create1DRGrid(nPts, VTK_FLOAT);
avtDataTree_p tree = new avtDataTree(rgrid, 0);
rgrid->Delete();
return tree;
}
if (res.size() != nPts*nResultsToStore)
{
vtkRectilinearGrid *rgrid =
vtkVisItUtility::Create1DRGrid(nPts, VTK_FLOAT);
debug1 << "Mismatch in QOT times/results sizes: " << endl;
debug1 << " times size: " << times.size() << endl;
debug1 << " nResultsToStore: " << nResultsToStore << endl;
debug1 << " results size: " << res.size() << endl;
avtDataTree_p tree = new avtDataTree(rgrid, 0);
rgrid->Delete();
return tree;
}
if (vars.size() != nResultsToStore)
{
xc->SetTuple1(i, res[i*2]);
sc->SetTuple1(i, res[i*2+1]);
vtkRectilinearGrid *rgrid =
vtkVisItUtility::Create1DRGrid(nPts, VTK_FLOAT);
debug1 << "Mismatch in QOT vars/nresults sizes: " << endl;
debug1 << " vars size: " << times.size() << endl;
debug1 << " nResultsTo