Commit 2d305ac9 authored by Utkarsh Ayachit's avatar Utkarsh Ayachit Committed by Kitware Robot

Merge topic 'fix_vtkExtractTemporalFieldData'

bc563cc9 Add support for composite datasets to vtkExtractTemporalFieldData.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Reviewed-by: Shawn Waldon's avatarShawn Waldon <shawn.waldon@kitware.com>
Merge-request: !1947
parents 1b4edd95 bc563cc9
Pipeline #26092 canceled with stage
vtk_add_test_python(
ExtractEdgesQuadraticCells.py
ExtractTensors.py
extractPolyData.py
extractRectGrid.py
extractTemporalFieldData.py,NO_RT,NO_VALID
ExtractTensors.py
extractUGrid.py
extractVectors.py
)
#!/usr/bin/env python
import vtk
from vtk.test import Testing
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
reader = vtk.vtkExodusIIReader()
reader.SetFileName(VTK_DATA_ROOT + "/Data/can.ex2")
reader.UpdateInformation()
for i in range(reader.GetNumberOfObjectArrays(reader.GLOBAL)):
name = reader.GetObjectArrayName(reader.GLOBAL, i)
reader.SetObjectArrayStatus(reader.GLOBAL, name, 1)
extractTFD = vtk.vtkExtractTemporalFieldData()
extractTFD.SetInputConnection(reader.GetOutputPort())
extractTFD.Update()
data = extractTFD.GetOutputDataObject(0)
assert data.IsA("vtkMultiBlockDataSet")
block = data.GetBlock(0).GetBlock(0)
assert block.IsA("vtkTable")
assert block.GetNumberOfRows() == reader.GetNumberOfTimeSteps()
assert block.GetNumberOfColumns() > 0
extractTFD.HandleCompositeDataBlocksIndividuallyOff()
extractTFD.Update()
data = extractTFD.GetOutputDataObject(0)
assert data.IsA("vtkTable")
assert data.GetNumberOfRows() == reader.GetNumberOfTimeSteps()
assert data.GetNumberOfColumns() > 0
......@@ -2,12 +2,13 @@ vtk_module(vtkFiltersExtraction
GROUPS
StandAlone
TEST_DEPENDS
vtkInteractionStyle
vtkIOExodus
vtkIOLegacy
vtkIOXML
vtkIOExodus
vtkRendering${VTK_RENDERING_BACKEND}
vtkTestingRendering
vtkInteractionStyle
KIT
vtkFilters
DEPENDS
......@@ -18,4 +19,4 @@ vtk_module(vtkFiltersExtraction
vtkCommonDataModel
vtkFiltersCore
vtkFiltersStatistics
)
\ No newline at end of file
)
......@@ -14,44 +14,53 @@
=========================================================================*/
#include "vtkExtractTemporalFieldData.h"
#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkCompositeDataIterator.h"
#include "vtkDataSetAttributes.h"
#include "vtkDataSet.h"
#include "vtkDoubleArray.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkTable.h"
#include "vtkSelection.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkUnsignedCharArray.h"
#include "vtkGenericCell.h"
#include "vtkStdString.h"
#include <vector>
#include "vtkTable.h"
#include <vector>
vtkStandardNewMacro(vtkExtractTemporalFieldData);
class vtkExtractTemporalFieldData::vtkInternals
{
public:
std::vector<double> TimeSteps;
};
vtkObjectFactoryNewMacro(vtkExtractTemporalFieldData);
//----------------------------------------------------------------------------
vtkExtractTemporalFieldData::vtkExtractTemporalFieldData()
{
this->NumberOfTimeSteps = 0;
this->Internals = new vtkExtractTemporalFieldData::vtkInternals();
this->HandleCompositeDataBlocksIndividually = true;
}
//----------------------------------------------------------------------------
vtkExtractTemporalFieldData::~vtkExtractTemporalFieldData()
{
delete this->Internals;
this->Internals = NULL;
}
//----------------------------------------------------------------------------
int vtkExtractTemporalFieldData::GetNumberOfTimeSteps()
{
return static_cast<int>(this->Internals->TimeSteps.size());
}
//----------------------------------------------------------------------------
void vtkExtractTemporalFieldData::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "NumberOfTimeSteps: " << this->NumberOfTimeSteps << endl;
os << indent << "HandleCompositeDataBlocksIndividually: "
<< this->HandleCompositeDataBlocksIndividually << endl;
}
//----------------------------------------------------------------------------
......@@ -59,32 +68,35 @@ int vtkExtractTemporalFieldData::FillInputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkCompositeDataSet");
return 1;
}
//----------------------------------------------------------------------------
int vtkExtractTemporalFieldData::ProcessRequest(
vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
int vtkExtractTemporalFieldData::RequestDataObject(
vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
{
if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
vtkDataObject* input = vtkDataObject::GetData(inputVector[0], 0);
if (vtkCompositeDataSet::SafeDownCast(input) &&
this->HandleCompositeDataBlocksIndividually)
{
return this->RequestInformation(request, inputVector, outputVector);
if (vtkMultiBlockDataSet::GetData(outputVector, 0) == NULL)
{
vtkNew<vtkMultiBlockDataSet> mb;
outputVector->GetInformationObject(0)->Set(
vtkDataObject::DATA_OBJECT(), mb.Get());
}
}
else if(
request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_DATA()))
else if (vtkTable::GetData(outputVector, 0) == NULL)
{
return this->RequestData(request,
inputVector,
outputVector);
vtkNew<vtkTable> table;
outputVector->GetInformationObject(0)->Set(
vtkDataObject::DATA_OBJECT(), table.Get());
}
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
return 1;
}
//----------------------------------------------------------------------------
int vtkExtractTemporalFieldData::RequestInformation(
vtkInformation* vtkNotUsed(request),
......@@ -92,14 +104,18 @@ int vtkExtractTemporalFieldData::RequestInformation(
vtkInformationVector* outputVector)
{
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
if ( inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()) )
if (inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()))
{
this->NumberOfTimeSteps =
inInfo->Length( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
int size = inInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
this->Internals->TimeSteps.resize(size);
if (size > 0)
{
inInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS(), &this->Internals->TimeSteps[0]);
}
}
else
{
this->NumberOfTimeSteps = 0;
this->Internals->TimeSteps.clear();
}
// The output of this filter does not contain a specific time, rather
......@@ -107,98 +123,107 @@ int vtkExtractTemporalFieldData::RequestInformation(
// respond to time requests. Therefore, we remove all time information
// from the output.
vtkInformation* outInfo = outputVector->GetInformationObject(0);
if (outInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()))
{
outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
}
if (outInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_RANGE()))
{
outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_RANGE());
}
int wholeExtent[6] = {0, 0, 0, 0, 0, 0};
wholeExtent[1] = this->NumberOfTimeSteps - 1;
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
wholeExtent, 6);
outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_RANGE());
return 1;
}
//----------------------------------------------------------------------------
int vtkExtractTemporalFieldData::RequestData(
vtkInformation*,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
if (this->NumberOfTimeSteps == 0)
if (this->GetNumberOfTimeSteps() == 0)
{
vtkErrorMacro("No time steps in input data!");
return 0;
}
// get the output data object
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkTable *output = vtkTable::GetData(outInfo);
// get the input data object
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
vtkDataSet *input = vtkDataSet::GetData(inInfo);
this->CopyDataToOutput(inInfo, input, output);
vtkDataObject* inputDO = vtkDataObject::GetData(inputVector[0], 0);
if (vtkCompositeDataSet* cd = vtkCompositeDataSet::SafeDownCast(inputDO))
{
vtkSmartPointer<vtkCompositeDataIterator> iter;
iter.TakeReference(cd->NewIterator());
if (this->HandleCompositeDataBlocksIndividually)
{
vtkMultiBlockDataSet* output = vtkMultiBlockDataSet::GetData(outputVector, 0);
assert(output);
output->CopyStructure(cd);
for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
{
if (vtkDataSet* inputDS = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject()))
{
vtkNew<vtkTable> outputBlock;
this->CopyDataToOutput(inputDS, outputBlock.Get());
output->SetDataSet(iter, outputBlock.Get());
}
}
}
else
{
vtkTable *output = vtkTable::GetData(outputVector, 0);
assert(output);
for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
{
if (vtkDataSet* inputDS = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject()))
{
if (this->CopyDataToOutput(inputDS, output))
{
break;
}
}
}
}
}
else if (vtkDataSet* input = vtkDataSet::SafeDownCast(inputDO))
{
vtkTable *output = vtkTable::GetData(outputVector, 0);
this->CopyDataToOutput(input, output);
}
else
{
vtkErrorMacro("Incorrect input type.");
return 0;
}
return 1;
}
//----------------------------------------------------------------------------
void vtkExtractTemporalFieldData::CopyDataToOutput(
vtkInformation* inInfo,
vtkDataSet *input, vtkTable *output)
bool vtkExtractTemporalFieldData::CopyDataToOutput(vtkDataSet *input, vtkTable *output)
{
vtkDataSetAttributes *opd = output->GetRowData();
vtkDataSetAttributes *outRowData = output->GetRowData();
vtkFieldData *ifd = input->GetFieldData();
int numArrays = 0;
if(!ifd || !opd)
if (!ifd || !outRowData)
{
vtkErrorMacro("Unsupported field type.");
return;
return false;
}
int numTimeSteps = this->GetNumberOfTimeSteps();
assert(numTimeSteps > 0);
for (vtkIdType j=0; j<ifd->GetNumberOfArrays(); j++)
{
vtkDataArray* inFieldArray = ifd->GetArray(j);
if (inFieldArray &&
inFieldArray->GetName() &&
!inFieldArray->IsA("vtkIdTypeArray") &&
inFieldArray->GetNumberOfTuples() == this->NumberOfTimeSteps)
inFieldArray->GetNumberOfTuples() == numTimeSteps)
{
vtkDataArray *outPointArray = vtkDataArray::CreateDataArray(inFieldArray->GetDataType());
//outPointArray->DeepCopy(inFieldArray);
outPointArray->SetNumberOfComponents(inFieldArray->GetNumberOfComponents());
outPointArray->SetNumberOfTuples(this->NumberOfTimeSteps);
for(vtkIdType i=0; i<inFieldArray->GetNumberOfComponents(); i++)
{
outPointArray->CopyComponent(i,inFieldArray,i);
}
outPointArray->SetName(inFieldArray->GetName());
opd->AddArray(outPointArray);
outPointArray->Delete();
numArrays++;
vtkDataArray *outArray = inFieldArray->NewInstance();
outArray->ShallowCopy(inFieldArray);
outRowData->AddArray(outArray);
outArray->Delete();
}
}
double *timesteps = NULL;
if ( inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()) )
if (outRowData->GetNumberOfArrays() == 0)
{
timesteps = inInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
return false;
}
// Add an array to hold the time at each step
vtkDoubleArray *timeArray = vtkDoubleArray::New();
vtkNew<vtkDoubleArray> timeArray;
timeArray->SetNumberOfComponents(1);
timeArray->SetNumberOfTuples(this->NumberOfTimeSteps);
timeArray->SetNumberOfTuples(numTimeSteps);
if (ifd->GetArray("Time"))
{
timeArray->SetName("TimeData");
......@@ -207,25 +232,8 @@ void vtkExtractTemporalFieldData::CopyDataToOutput(
{
timeArray->SetName("Time");
}
for(int m=0; m<this->NumberOfTimeSteps; m++)
{
timeArray->SetTuple1(m, timesteps[m]);
}
opd->AddArray(timeArray);
timeArray->Delete();
// This array is used to make particular samples as invalid.
// This happens when we are looking at a location which is not contained
// by a cell or at a cell or point id that is destroyed.
// It is used in the parallel subclass as well.
vtkUnsignedCharArray* validPts = vtkUnsignedCharArray::New();
validPts->SetName("vtkValidPointMask");
validPts->SetNumberOfTuples(this->NumberOfTimeSteps);
opd->AddArray(validPts);
// if no valid field arrays were found, which would happen if the reader
// did not have the requested data, set validity to 0, otherwise 1.
int validity = numArrays ? 1 : 0;
validPts->FillComponent(0,validity);
validPts->Delete();
std::copy(this->Internals->TimeSteps.begin(), this->Internals->TimeSteps.end(),
timeArray->GetPointer(0));
outRowData->AddArray(timeArray.Get());
return true;
}
......@@ -17,11 +17,19 @@
// vtkExtractTemporalFieldData extracts arrays from the input vtkFieldData.
// These arrays are assumed to contain temporal data, where the nth tuple
// contains the value for the nth timestep.
// The output is a 1D rectilinear grid where the
// XCoordinates correspond to time (the same array is also copied to
// a point array named Time or TimeData (if Time exists in the input).
//
// For composite datasets, the filter has two modes, it can treat each block in
// the dataset individually (default) or just look at the first non-empty field data
// (common for readers vtkExodusIIReader). For latter, set
// HandleCompositeDataBlocksIndividually to false.
//
// The output is a vtkTable (or a multiblock of vtkTables) based of whether
// HandleCompositeDataBlocksIndividually is true and input is a composite
// dataset.
//
// This algorithm does not produce a TIME_STEPS or TIME_RANGE information
// because it works across time.
//
// .Section Caveat
// This algorithm works only with source that produce TIME_STEPS().
// Continuous time range is not yet supported.
......@@ -30,55 +38,59 @@
#define vtkExtractTemporalFieldData_h
#include "vtkFiltersExtractionModule.h" // For export macro
#include "vtkTableAlgorithm.h"
#include "vtkDataObjectAlgorithm.h"
class vtkDataSet;
class vtkTable;
class vtkDataSetAttributes;
class VTKFILTERSEXTRACTION_EXPORT vtkExtractTemporalFieldData : public vtkTableAlgorithm
class VTKFILTERSEXTRACTION_EXPORT vtkExtractTemporalFieldData : public vtkDataObjectAlgorithm
{
public:
static vtkExtractTemporalFieldData *New();
vtkTypeMacro(vtkExtractTemporalFieldData,vtkTableAlgorithm);
vtkTypeMacro(vtkExtractTemporalFieldData,vtkDataObjectAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Get the number of time steps
vtkGetMacro(NumberOfTimeSteps,int);
int GetNumberOfTimeSteps();
// Description:
// When set to true (default), if the input is a vtkCompositeDataSet, then
// each block in the input dataset in processed separately. If false, then the first
// non-empty FieldData is considered.
vtkSetMacro(HandleCompositeDataBlocksIndividually, bool);
vtkGetMacro(HandleCompositeDataBlocksIndividually, bool);
vtkBooleanMacro(HandleCompositeDataBlocksIndividually, bool);
protected:
vtkExtractTemporalFieldData();
~vtkExtractTemporalFieldData();
virtual int ProcessRequest(vtkInformation*,
vtkInformationVector**,
vtkInformationVector*);
virtual int RequestInformation(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
virtual int RequestData(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
virtual int FillInputPortInformation(int port, vtkInformation* info);
int RequestDataObject(vtkInformation*,
vtkInformationVector**,
vtkInformationVector*) VTK_OVERRIDE;
int RequestInformation(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector) VTK_OVERRIDE;
int RequestData(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector) VTK_OVERRIDE;
int FillInputPortInformation(int port, vtkInformation* info) VTK_OVERRIDE;
// Description:
// This looks at the arrays in the vtkFieldData of input and copies them
// to the output point data.
void CopyDataToOutput(vtkInformation* inInfo,
vtkDataSet *input, vtkTable *output);
int NumberOfTimeSteps;
// Returns true if the input had an "appropriate" field data.
bool CopyDataToOutput(vtkDataSet *input, vtkTable *output);
bool HandleCompositeDataBlocksIndividually;
private:
vtkExtractTemporalFieldData(const vtkExtractTemporalFieldData&) VTK_DELETE_FUNCTION;
void operator=(const vtkExtractTemporalFieldData&) VTK_DELETE_FUNCTION;
class vtkInternals;
vtkInternals* Internals;
};
#endif
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