Commit 3ae631e6 authored by Berk Geveci's avatar Berk Geveci Committed by Code Review

Merge topic 'ensemble-reader' into master

e2532923 Added an ensemble source.
38851122 PERF: Removed unnecessary function call.
be279517 Added new meta-data and request capability to the pipeline.
parents 20c2e44c e2532923
......@@ -96,6 +96,45 @@ public:
void Print(vtkInformation* info);
virtual void Print(ostream& os, vtkInformation* info);
// Description:
// This function is only relevant when the pertaining key
// is used in a VTK pipeline. Specific keys that handle
// pipeline data requests (for example, UPDATE_PIECE_NUMBER)
// can overwrite this method to notify the pipeline that a
// a filter should be (re-)executed because what is in
// the current output is different that what is being requested
// by the key. For example, DATA_PIECE_NUMBER != UPDATE_PIECE_NUMBER.
virtual bool NeedToExecute(vtkInformation* vtkNotUsed(pipelineInfo),
vtkInformation* vtkNotUsed(dobjInfo)) {return false;}
// Description:
// This function is only relevant when the pertaining key
// is used in a VTK pipeline. Specific keys that handle
// pipeline data requests (for example, UPDATE_PIECE_NUMBER)
// can overwrite this method to store in the data information
// meta-data about the request that led to the current filter
// execution. This meta-data can later be used to compare what
// is being requested to decide whether the filter needs to
// re-execute. For example, a filter may store the current
// UPDATE_PIECE_NUMBER in the data object's information as
// the DATA_PIECE_NUMBER. DATA_PIECE_NUMBER can later be compared
// to a new UPDATA_PIECE_NUMBER to decide whether a filter should
// re-execute.
virtual void StoreMetaData(vtkInformation* vtkNotUsed(request),
vtkInformation* vtkNotUsed(pipelineInfo),
vtkInformation* vtkNotUsed(dobjInfo)) {}
// Description:
// This function is only relevant when the pertaining key
// is used in a VTK pipeline. By overwriting this method, a
// key can decide if/how to copy itself downstream or upstream
// during a particular pipeline pass. For example, meta-data keys
// can copy themselves during REQUEST_INFORMATION whereas request
// keys can copy themselves during REQUEST_UPDATE_EXTENT.
virtual void CopyDefaultInformation(vtkInformation* vtkNotUsed(request),
vtkInformation* vtkNotUsed(fromInfo),
vtkInformation* vtkNotUsed(toInfo)) {}
protected:
const char* Name;
const char* Location;
......@@ -129,6 +168,13 @@ private:
{ \
return CLASS##_##NAME; \
}
#define vtkInformationKeySubclassMacro(CLASS, NAME, type, super) \
static vtkInformation##type##Key* CLASS##_##NAME = \
new vtkInformation##type##Key(#NAME, #CLASS); \
vtkInformation##super##Key* CLASS::NAME() \
{ \
return CLASS##_##NAME; \
}
#define vtkInformationKeyRestrictedMacro(CLASS, NAME, type, required) \
static vtkInformation##type##Key* CLASS##_##NAME = \
new vtkInformation##type##Key(#NAME, #CLASS, required); \
......@@ -137,4 +183,5 @@ private:
return CLASS##_##NAME; \
}
#endif
......@@ -11,6 +11,7 @@ SET(Module_SRCS
vtkDataSetAlgorithm.cxx
vtkDemandDrivenPipeline.cxx
vtkDirectedGraphAlgorithm.cxx
vtkEnsembleSource.cxx
vtkExecutive.cxx
vtkExtentSplitter.cxx
vtkExtentTranslator.cxx
......@@ -24,8 +25,10 @@ SET(Module_SRCS
vtkImageProgressIterator.cxx
vtkImageToStructuredGrid.cxx
vtkImageToStructuredPoints.cxx
vtkInformationDataObjectMetaDataKey.cxx
vtkInformationExecutivePortKey.cxx
vtkInformationExecutivePortVectorKey.cxx
vtkInformationIntegerRequestKey.cxx
vtkMultiBlockDataSetAlgorithm.cxx
vtkMultiTimeStepAlgorithm.cxx
vtkPassInputTypeAlgorithm.cxx
......
......@@ -2,6 +2,7 @@ vtk_add_test_cxx(${vtk-module}CxxTests tests
NO_DATA NO_VALID
TestCopyAttributeData.cxx
TestImageDataToStructuredGrid.cxx
TestMetaData.cxx
TestSetInputDataObject.cxx
TestTemporalSupport.cxx
)
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestTemporalSupport.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// This test verifies that information keys are copied up & down the
// pipeline properly and NeedToExecute/StoreMetaData functions as expected.
#include "vtkInformation.h"
#include "vtkInformationDataObjectMetaDataKey.h"
#include "vtkInformationIntegerRequestKey.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationVector.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkPolyDataAlgorithm.h"
#include "vtkPolyDataNormals.h"
#define TEST_SUCCESS 0
#define TEST_FAILURE 1
class MySource : public vtkPolyDataAlgorithm
{
public:
static MySource *New();
vtkTypeMacro(vtkPolyDataAlgorithm,vtkAlgorithm);
static vtkInformationDataObjectMetaDataKey* META_DATA();
static vtkInformationIntegerRequestKey* REQUEST();
static vtkInformationIntegerKey* DATA();
bool Failed;
unsigned int NumberOfExecutions;
int Result;
protected:
MySource()
{
this->SetNumberOfInputPorts(0);
this->SetNumberOfOutputPorts(1);
this->Failed = false;
this->NumberOfExecutions = 0;
this->Result = -1;
}
virtual int RequestInformation(vtkInformation*,
vtkInformationVector**,
vtkInformationVector* outputVector)
{
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkPolyData* pd = vtkPolyData::New();
outInfo->Set(META_DATA(), pd);
pd->Delete();
return 1;
}
virtual int RequestData(vtkInformation*,
vtkInformationVector**,
vtkInformationVector* outputVector)
{
// Here we verify that a request set at the end of the pipeline
// made it to here properly.
vtkInformation* outInfo = outputVector->GetInformationObject(0);
if (!outInfo->Has(REQUEST()) ||
outInfo->Get(REQUEST()) != this->Result)
{
this->Failed = true;
}
this->NumberOfExecutions++;
return 1;
}
};
vtkStandardNewMacro(MySource);
vtkInformationKeyMacro(MySource, META_DATA, DataObjectMetaData);
vtkInformationKeyMacro(MySource, DATA, Integer);
class vtkInformationMyRequestKey : public vtkInformationIntegerRequestKey
{
public:
vtkInformationMyRequestKey(const char* name, const char* location) :
vtkInformationIntegerRequestKey(name, location)
{
this->DataKey = MySource::DATA();
}
};
vtkInformationKeySubclassMacro(MySource, REQUEST, MyRequest, IntegerRequest);
int TestMetaData(int, char*[])
{
vtkNew<MySource> mySource;
vtkNew<vtkPolyDataNormals> filter;
filter->SetInputConnection(mySource->GetOutputPort());
filter->UpdateInformation();
// Do we have the meta-data created by the reader at the end
// of the pipeline?
if (!filter->GetOutputInformation(0)->Has(MySource::META_DATA()))
{
return TEST_FAILURE;
}
filter->GetOutputInformation(0)->Set(MySource::REQUEST(), 2);
mySource->Result = 2;
filter->Update();
// Nothing changed. This should not cause re-execution
filter->Update();
filter->GetOutputInformation(0)->Set(MySource::REQUEST(), 3);
mySource->Result = 3;
// Request changed. This should cause re-execution
filter->Update();
if (mySource->NumberOfExecutions != 2)
{
return TEST_FAILURE;
}
if (mySource->Failed)
{
return TEST_FAILURE;
}
return TEST_SUCCESS;
}
vtk_add_test_python(
NO_DATA NO_VALID NO_OUTPUT
TestEnsemble.py
TestReleaseData.py
)
""" Tests if vtkEnsembleSource works properly. """
import vtk
from vtk.test import Testing
class TestEnsemble(Testing.vtkTest):
resolutions = [4, 8, 16, 32]
npolys = [5, 9, 17, 33]
def createSource(self):
r = vtk.vtkEnsembleSource()
aColumn = vtk.vtkIntArray()
aColumn.SetName("Resolution")
nrows = len(TestEnsemble.resolutions)
for res in TestEnsemble.resolutions:
aColumn.InsertNextValue(res)
table = vtk.vtkTable()
table.SetNumberOfRows(nrows)
table.GetRowData().AddArray(aColumn)
r.SetMetaData(table)
for res in TestEnsemble.resolutions:
c = vtk.vtkConeSource()
c.SetResolution(res)
r.AddMember(c)
return r
def test1(self):
r = self.createSource()
for i in range(len(TestEnsemble.resolutions)):
r.SetCurrentMember(i)
r.Update()
self.assertEqual(r.GetOutputDataObject(0).GetNumberOfCells(), TestEnsemble.npolys[i])
def test2(self):
global nExecutions
r = self.createSource()
nExecutions = 0
def addToCounter(obj, event):
global nExecutions
nExecutions += 1
r.AddObserver('StartEvent', addToCounter)
shrink = vtk.vtkShrinkPolyData()
shrink.SetInputConnection(r.GetOutputPort())
shrink.UpdateInformation()
self.assertTrue(shrink.GetOutputInformation(0).Has(vtk.vtkEnsembleSource.META_DATA()))
metaData = shrink.GetOutputInformation(0).Has(vtk.vtkEnsembleSource.META_DATA())
shrink.Update()
oInfo = shrink.GetOutputInformation(0)
oInfo.Set(vtk.vtkEnsembleSource.UPDATE_MEMBER(), 2)
shrink.Update()
output = shrink.GetOutputDataObject(0)
self.assertEquals(output.GetNumberOfCells(), TestEnsemble.npolys[2])
shrink.Update()
oInfo = shrink.GetOutputInformation(0)
oInfo.Set(vtk.vtkEnsembleSource.UPDATE_MEMBER(), 1)
shrink.Update()
self.assertEquals(output.GetNumberOfCells(), TestEnsemble.npolys[1])
shrink2 = vtk.vtkShrinkPolyData()
shrink2.SetInputConnection(r.GetOutputPort())
shrink2.Update()
output2 = shrink2.GetOutputDataObject(0)
self.assertEquals(output.GetNumberOfCells(), TestEnsemble.npolys[1])
self.assertEquals(nExecutions, 3)
if __name__ == "__main__":
Testing.main([(TestEnsemble, 'test')])
......@@ -1479,6 +1479,18 @@ void vtkAlgorithm::UpdateInformation()
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::UpdateDataObject()
{
vtkDemandDrivenPipeline* ddp =
vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive());
if (ddp)
{
ddp->UpdateDataObject();
}
}
//----------------------------------------------------------------------------
void vtkAlgorithm::UpdateWholeExtent()
{
......
......@@ -449,6 +449,10 @@ public:
// Bring the algorithm's information up-to-date.
virtual void UpdateInformation();
// Description:
// Create output object(s).
virtual void UpdateDataObject();
// Description::
// Propagate meta-data upstream.
virtual void PropagateUpdateExtent();
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkEnsembleSource.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkEnsembleSource.h"
#include "vtkDataObject.h"
#include "vtkInformation.h"
#include "vtkInformationDataObjectMetaDataKey.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationIntegerRequestKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkTable.h"
#include <vector>
vtkStandardNewMacro(vtkEnsembleSource);
vtkCxxSetObjectMacro(vtkEnsembleSource, MetaData, vtkTable);
vtkInformationKeyMacro(vtkEnsembleSource, META_DATA, DataObjectMetaData);
vtkInformationKeyMacro(vtkEnsembleSource, DATA_MEMBER, Integer);
// Subclass vtkInformationIntegerRequestKey to set the DataKey.
class vtkInformationEnsembleMemberRequestKey : public vtkInformationIntegerRequestKey
{
public:
vtkInformationEnsembleMemberRequestKey(const char* name, const char* location) :
vtkInformationIntegerRequestKey(name, location)
{
this->DataKey = vtkEnsembleSource::DATA_MEMBER();
}
};
vtkInformationKeySubclassMacro(vtkEnsembleSource, UPDATE_MEMBER, EnsembleMemberRequest, IntegerRequest);
struct vtkEnsembleSourceInternal
{
std::vector<vtkSmartPointer<vtkAlgorithm> > Algorithms;
};
vtkEnsembleSource::vtkEnsembleSource()
{
this->SetNumberOfInputPorts(0);
this->SetNumberOfOutputPorts(1);
this->Internal = new vtkEnsembleSourceInternal;
this->CurrentMember = 0;
this->MetaData = 0;
}
vtkEnsembleSource::~vtkEnsembleSource()
{
delete this->Internal;
if (this->MetaData)
{
this->MetaData->Delete();
this->MetaData = 0;
}
}
int vtkEnsembleSource::ProcessRequest(vtkInformation *request,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkAlgorithm* currentReader = this->GetCurrentReader(outInfo);
if (currentReader)
{
if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()))
{
// Make sure to initialize our output to the right type.
// Note all ensemble members are expected to produce the same
// data type or we are toast.
currentReader->UpdateDataObject();
vtkDataObject* rOutput = currentReader->GetOutputDataObject(0);
vtkDataObject* output = rOutput->NewInstance();
outputVector->GetInformationObject(0)->Set(vtkDataObject::DATA_OBJECT(),
output);
output->Delete();
return 1;
}
if (request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
{
if (this->MetaData)
{
outputVector->GetInformationObject(0)->Set(META_DATA(),
this->MetaData);
}
// Call RequestInformation on all readers as they may initialize
// data structures there. Note that this has to be done here
// because current reader can be changed with a pipeline request
// which does not cause REQUEST_INFORMATION to happen again.
std::vector<vtkSmartPointer<vtkAlgorithm> >::iterator iter =
this->Internal->Algorithms.begin();
std::vector<vtkSmartPointer<vtkAlgorithm> >::iterator end =
this->Internal->Algorithms.end();
for(; iter != end; iter++)
{
int retVal = (*iter)->ProcessRequest(request, inputVector, outputVector);
if (!retVal)
{
return retVal;
}
}
return 1;
}
return currentReader->ProcessRequest(request, inputVector, outputVector);
}
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}
void vtkEnsembleSource::AddMember(vtkAlgorithm* alg)
{
this->Internal->Algorithms.push_back(alg);
}
void vtkEnsembleSource::RemoveAllMembers()
{
this->Internal->Algorithms.clear();
}
unsigned int vtkEnsembleSource::GetNumberOfMembers()
{
return static_cast<unsigned int>(this->Internal->Algorithms.size());
}
vtkAlgorithm* vtkEnsembleSource::GetCurrentReader(vtkInformation* outInfo)
{
unsigned int currentMember = 0;
if (outInfo->Has(UPDATE_MEMBER()))
{
currentMember = static_cast<unsigned int>(outInfo->Get(UPDATE_MEMBER()));
}
else
{
currentMember = this->CurrentMember;
}
if (currentMember >= this->GetNumberOfMembers())
{
return 0;
}
return this->Internal->Algorithms[currentMember];
}
int vtkEnsembleSource::FillOutputPortInformation(int, vtkInformation* info)
{
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject");
return 1;
}
void vtkEnsembleSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Current member: " << this->CurrentMember << endl;
os << indent << "MetaData: " << endl;
if (this->MetaData)
{
this->MetaData->PrintSelf(os, indent.GetNextIndent());
}
else
{
os << indent << "(NULL)" << endl;
}
}
\ No newline at end of file
/*=========================================================================
Program: Visualization Toolkit
Module: vtkEnsembleSource.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkEnsembleSource - source that manages dataset ensembles
// .SECTION Description
// vtkEnsembleSource manages a collection of data sources in order to
// represent a dataset ensemble. It has the ability to provide meta-data
// about the ensemble in the form of a table, using the META_DATA key
// as well as accept a pipeline request using the UPDATE_MEMBER key.
// Note that it is expected that all ensemble members produce data of the
// same type.
#ifndef __vtkEnsembleSource_h
#define __vtkEnsembleSource_h
#include "vtkCommonExecutionModelModule.h" // For export macro
#include "vtkAlgorithm.h"
struct vtkEnsembleSourceInternal;
class vtkTable;
class vtkInformationDataObjectMetaDataKey;
class vtkInformationIntegerRequestKey;
class vtkInformationIntegerKey;
class VTKCOMMONEXECUTIONMODEL_EXPORT vtkEnsembleSource : public vtkAlgorithm
{
public:
static vtkEnsembleSource *New();
vtkTypeMacro(vtkEnsembleSource,vtkAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Descriptions:
// Add an algorithm (source) that will produce the next ensemble member.
// This algorithm will be passed the REQUEST_INFORMATION, REQUEST_UPDATE_EXTENT
// and REQUEST_DATA pipeline passes for execution.
void AddMember(vtkAlgorithm*);
// Description:
// Removes all ensemble members.
void RemoveAllMembers();
// Description:
// Returns the number of ensemble members.
unsigned int GetNumberOfMembers();
// Description:
// Set/Get the current ensemble member to process. Note that this data member
// will not be used if the UPDATE_MEMBER key is present in the pipeline. Also,
// this data member may be removed in the future. Unless it is absolutely necessary
// to use this data member, use the UPDATE_MEMBER key instead.
vtkSetMacro(CurrentMember, unsigned int);
vtkGetMacro(CurrentMember, unsigned int);
// Description:
// Set the meta-data that will be propagated downstream. Make sure that this table
// has as many rows as the ensemble members and the meta-data for each row matches
// the corresponding ensemble source.
void SetMetaData(vtkTable*);
// Description:
// Meta-data for the ensemble. This is set with SetMetaData.
static vtkInformationDataObjectMetaDataKey* META_DATA();
// Description:
// Key used to request a particular ensemble member.
static vtkInformationIntegerRequestKey* UPDATE_MEMBER();
protected:
vtkEnsembleSource();
~vtkEnsembleSource();
static vtkInformationIntegerKey* DATA_MEMBER();
friend class vtkInformationEnsembleMemberRequestKey;
virtual int ProcessRequest(vtkInformation *request,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector);
virtual int FillOutputPortInformation(int, vtkInformation*);
vtkAlgorithm* GetCurrentReader(vtkInformation*);
vtkEnsembleSourceInternal* Internal;
unsigned int CurrentMember;
vtkTable* MetaData;
private:
vtkEnsembleSource(const vtkEnsembleSource&); // Not implemented.
void operator=(const vtkEnsembleSource&); // Not implemented.
};
#endif
......@@ -22,6 +22,7 @@
#include "vtkInformationExecutivePortKey.h"
#include "vtkInformationExecutivePortVectorKey.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationIterator.h"
#include "vtkInformationKeyVectorKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
......@@ -673,6 +674,11 @@ void vtkExecutive::CopyDefaultInformation(vtkInformation* request,
vtkInformationKey** keys = request->Get(KEYS_TO_COPY());
int length = request->Length(KEYS_TO_COPY());
vtkInformation* inInfo = inInfoVec[0]->GetInformationObject(0);
vtkSmartPointer<vtkInformationIterator> infoIter =
vtkSmartPointer<vtkInformationIterator>::New();
infoIter->SetInformation(inInfo);
int oiobj = outInfoVec->GetNumberOfInformationObjects();
for(int i=0; i < oiobj; ++i)
{
......@@ -689,6 +695,15 @@ void vtkExecutive::CopyDefaultInformation(vtkInformation* request,
outInfo->CopyEntries(inInfo, vkey);
}
}
// Give the keys an opportunity to copy themselves.
infoIter->InitTraversal();
while(!infoIter->IsDoneWithTraversal())
{
vtkInformationKey* key = infoIter->GetCurrentKey();
key->CopyDefaultInformation(request, inInfo, outInfo);
infoIter->GoToNextItem();
}
}
}
}
......@@ -709,6 +724,11 @@ void vtkExecutive::CopyDefaultInformation(vtkInformation* request,
vtkInformationKey** keys = request->Get(KEYS_TO_COPY());
int length = request->Length(KEYS_TO_COPY());
vtkInformation* outInfo = outInfoVec->GetInformationObject(outputPort);
vtkSmartPointer<vtkInformationIterator> infoIter =
vtkSmartPointer<vtkInformationIterator>::New();
infoIter->SetInformation(outInfo);
for(int i=0; i < this->GetNumberOfInputPorts(); ++i)
{
for(int j=0; j < inInfoVec[i]->GetNumberOfInformationObjects(); ++j)
......@@ -726,6 +746,15 @@ void vtkExecutive::CopyDefaultInformation(vtkInformation* request,
inInfo->CopyEntries(outInfo, vkey);
}
}
// Give the keys an opportunity to copy themselves.
infoIter->InitTraversal();
while(!infoIter->IsDoneWithTraversal())
{
vtkInformationKey* key = infoIter->GetCurrentKey();
key->CopyDefaultInformation(request, outInfo, inInfo);
infoIter->GoToNextItem();
}
}
}
}
......