Commit e9bc920d authored by Berk Geveci's avatar Berk Geveci

Ported all legacy readers to the new reader architecture.

The new new reader architecture allows for things such as
time series without changes to the subclasses.  To benefit
from this, ported all legacy VTK readers to this architecture.

Also developed a simple reader superclass. This superclass
can be used to implement algorithms that are neither time
aware nor parallel.

Also rearchitected the Xdmf readers so that they don't
unnecessarily subclass from VTK legacy readers.
parent 7e1821f0
......@@ -42,6 +42,7 @@ SET(Module_SRCS
vtkRectilinearGridAlgorithm.cxx
vtkScalarTree.cxx
vtkSimpleImageToImageFilter.cxx
vtkSimpleReader.cxx
vtkSimpleScalarTree.cxx
vtkSpanSpace.cxx
vtkSphereTree.cxx
......
......@@ -17,6 +17,7 @@
#include "vtkInformation.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkReaderExecutive.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include <vector>
......@@ -41,6 +42,12 @@ vtkParallelReader::~vtkParallelReader()
delete this->Internal;
}
//----------------------------------------------------------------------------
vtkExecutive* vtkParallelReader::CreateDefaultExecutive()
{
return vtkReaderExecutive::New();
}
//----------------------------------------------------------------------------
void vtkParallelReader::PrintSelf(ostream& os, vtkIndent indent)
{
......
......@@ -90,6 +90,8 @@ protected:
vtkParallelReader();
~vtkParallelReader() override;
vtkExecutive* CreateDefaultExecutive() override;
/**
* A subclass can override this method to provide an actual
* time value for a given file (this method is called for
......
......@@ -41,12 +41,40 @@ public:
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Provide meta-data for the pipeline. These include things like
* time steps and whole extent. Subclasses may have specialized
* This can be overridden by a subclass to create an output that
* is determined by the file being read. If the output is known at
* compile time, it is easier to override FillOutputPortInformation()
* to set vtkDataObject::DATA_TYPE_NAME(). The subclass should compare
* the new output type with the type of the currentOutput argument and
* return currentOutput without changing its reference count if the
* types are same.
*/
virtual vtkDataObject* CreateOutput(vtkDataObject* currentOutput)
{
return currentOutput;
}
/**
* Provide meta-data for the pipeline. This meta-data cannot vary over
* time as this method will not be called when only a request is changed.
* These include things like time steps. Subclasses may have specialized
* interfaces making this simpler.
*/
virtual int ReadMetaData(vtkInformation* metadata) = 0;
/**
* Provide meta-data for the pipeline. This meta-data can vary over time
* as this method will be called after a request is changed (such as time)
* These include things like whole extent. Subclasses may have specialized
* interfaces making this simpler.
*/
virtual int ReadTimeDependentMetaData(
int /*timestep*/, vtkInformation* /*metadata*/)
{
return 1;
}
/**
* Read the mesh (connectivity) for a given set of data partitioning,
* number of ghost levels and time step (index). The reader populates
......
......@@ -54,40 +54,62 @@ int vtkReaderExecutive::CallAlgorithm(vtkInformation* request, int direction,
{
return 0;
}
if (request->Has(REQUEST_INFORMATION()))
using vtkSDDP = vtkStreamingDemandDrivenPipeline;
vtkInformation* reqs = outInfo->GetInformationObject(0);
int hasTime = reqs->Has(vtkSDDP::UPDATE_TIME_STEP());
double* steps =
reqs->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
int timeIndex = 0;
if (hasTime && steps)
{
double requestedTimeStep =
reqs->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
int length =
reqs->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
// find the first time value larger than requested time value
// this logic could be improved
int cnt = 0;
while (cnt < length-1 && steps[cnt] < requestedTimeStep)
{
cnt++;
}
timeIndex = cnt;
}
if (request->Has(REQUEST_DATA_OBJECT()))
{
vtkDataObject* currentOutput = vtkDataObject::GetData(outInfo);
vtkDataObject* output = reader->CreateOutput(currentOutput);
if (output)
{
result = 1;
if (output != currentOutput)
{
outInfo->GetInformationObject(0)->Set(
vtkDataObject::DATA_OBJECT(), output);
output->Delete();
}
}
}
else if (request->Has(REQUEST_INFORMATION()))
{
result = reader->ReadMetaData(outInfo->GetInformationObject(0));
}
else if (request->Has(REQUEST_TIME_DEPENDENT_INFORMATION()))
{
result = reader->ReadTimeDependentMetaData(
timeIndex, outInfo->GetInformationObject(0));
}
else if (request->Has(REQUEST_DATA()))
{
typedef vtkStreamingDemandDrivenPipeline vtkSDDP;
vtkInformation* reqs = outInfo->GetInformationObject(0);
int piece = reqs->Has(vtkSDDP::UPDATE_PIECE_NUMBER()) ?
reqs->Get(vtkSDDP::UPDATE_PIECE_NUMBER()) : 0 ;
int npieces = reqs->Has(vtkSDDP::UPDATE_NUMBER_OF_PIECES()) ?
reqs->Get(vtkSDDP::UPDATE_NUMBER_OF_PIECES()) : 1;
int nghosts = reqs->Get(UPDATE_NUMBER_OF_GHOST_LEVELS());
int hasTime = reqs->Has(vtkSDDP::UPDATE_TIME_STEP());
double* steps =
reqs->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
int timeIndex = 0;
if (hasTime && steps)
{
double requestedTimeStep =
reqs->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
int length =
reqs->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
// find the first time value larger than requested time value
// this logic could be improved
int cnt = 0;
while (cnt < length-1 && steps[cnt] < requestedTimeStep)
{
cnt++;
}
timeIndex = cnt;
}
vtkDataObject* output = vtkDataObject::GetData(outInfo);
result = reader->ReadMesh(
piece, npieces, nghosts, timeIndex, output);
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkSimpleReader.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 "vtkSimpleReader.h"
#include "vtkInformation.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkReaderExecutive.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include <vector>
#include <numeric>
struct vtkSimpleReaderInternal
{
using FileNamesType = std::vector<std::string>;
FileNamesType FileNames;
};
//----------------------------------------------------------------------------
vtkSimpleReader::vtkSimpleReader()
{
this->Internal = new vtkSimpleReaderInternal;
this->CurrentFileIndex = -1;
this->HasTemporalMetaData = false;
}
//----------------------------------------------------------------------------
vtkSimpleReader::~vtkSimpleReader()
{
delete this->Internal;
}
//----------------------------------------------------------------------------
vtkExecutive* vtkSimpleReader::CreateDefaultExecutive()
{
return vtkReaderExecutive::New();
}
//----------------------------------------------------------------------------
void vtkSimpleReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
void vtkSimpleReader::AddFileName(const char* fname)
{
if(fname == nullptr || strlen(fname) == 0)
{
return;
}
this->Internal->FileNames.push_back(fname);
this->Modified();
}
//----------------------------------------------------------------------------
void vtkSimpleReader::ClearFileNames()
{
this->Internal->FileNames.clear();
this->Modified();
}
//----------------------------------------------------------------------------
int vtkSimpleReader::GetNumberOfFileNames() const
{
return static_cast<int>(this->Internal->FileNames.size());
}
//----------------------------------------------------------------------------
const char* vtkSimpleReader::GetFileName(int i) const
{
return this->Internal->FileNames[i].c_str();
}
//----------------------------------------------------------------------------
const char* vtkSimpleReader::GetCurrentFileName() const
{
if (this->CurrentFileIndex < 0 ||
this->CurrentFileIndex >= (int)this->Internal->FileNames.size())
{
return nullptr;
}
return this->Internal->FileNames[this->CurrentFileIndex].c_str();
}
//----------------------------------------------------------------------------
int vtkSimpleReader::ReadTimeDependentMetaData(
int timestep, vtkInformation* metadata)
{
if(!this->HasTemporalMetaData)
{
return 1;
}
int nTimes = static_cast<int>(this->Internal->FileNames.size());
if (timestep >= nTimes)
{
vtkErrorMacro("Cannot read time step " << timestep << ". Only " <<
nTimes << " time steps are available.");
return 0;
}
return this->ReadMetaDataSimple(
this->Internal->FileNames[timestep], metadata);
}
//----------------------------------------------------------------------------
int vtkSimpleReader::ReadMetaData(vtkInformation* metadata)
{
if(this->HasTemporalMetaData)
{
metadata->Set(
vtkStreamingDemandDrivenPipeline::TIME_DEPENDENT_INFORMATION(), 1);
}
else
{
if (!this->Internal->FileNames.empty())
{
// Call the meta-data function on the first file.
int retval =
this->ReadMetaDataSimple(this->Internal->FileNames[0], metadata);
if (!retval)
{
return retval;
}
}
}
if(this->Internal->FileNames.empty())
{
// No file names specified. No meta-data. There is still
// no need to return with an error.
return 1;
}
size_t nTimes = this->Internal->FileNames.size();
std::vector<double> times(nTimes);
bool hasTime = true;
auto iter = times.begin();
for(const auto& fname: this->Internal->FileNames)
{
auto time = this->GetTimeValue(fname);
if (vtkMath::IsNan(time))
{
hasTime = false;
break;
}
*iter++ = time;
}
if (!hasTime)
{
std::iota(times.begin(), times.end(), 0);
}
double timeRange[2];
timeRange[0] = times[0];
timeRange[1] = times[nTimes - 1];
metadata->Set(
vtkStreamingDemandDrivenPipeline::TIME_STEPS(), &times[0], (int)nTimes);
metadata->Set(
vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2);
return 1;
}
//----------------------------------------------------------------------------
int vtkSimpleReader::ReadMesh(
int piece, int, int, int timestep, vtkDataObject* output)
{
// Not a parallel reader. Cannot handle anything other than the first piece,
// which will have everyhing.
if (piece > 0)
{
return 1;
}
int nTimes = static_cast<int>(this->Internal->FileNames.size());
if (timestep >= nTimes)
{
vtkErrorMacro("Cannot read time step " << timestep << ". Only " <<
nTimes << " time steps are available.");
return 0;
}
if (this->ReadMeshSimple(
this->Internal->FileNames[timestep], output))
{
this->CurrentFileIndex = timestep;
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
int vtkSimpleReader::ReadPoints(
int piece, int , int , int timestep, vtkDataObject* output)
{
// Not a parallel reader. Cannot handle anything other than the first piece,
// which will have everyhing.
if (piece > 0)
{
return 1;
}
int nTimes = static_cast<int>(this->Internal->FileNames.size());
if (timestep >= nTimes)
{
vtkErrorMacro("Cannot read time step " << timestep << ". Only " <<
nTimes << " time steps are available.");
return 0;
}
return this->ReadPointsSimple(
this->Internal->FileNames[timestep], output);
}
//----------------------------------------------------------------------------
int vtkSimpleReader::ReadArrays(
int piece, int , int , int timestep, vtkDataObject* output)
{
// Not a parallel reader. Cannot handle anything other than the first piece,
// which will have everyhing.
if (piece > 0)
{
return 1;
}
int nTimes = static_cast<int>(this->Internal->FileNames.size());
if (timestep >= nTimes)
{
vtkErrorMacro("Cannot read time step " << timestep << ". Only " <<
nTimes << " time steps are available.");
return 0;
}
return this->ReadArraysSimple(
this->Internal->FileNames[timestep], output);
}
//----------------------------------------------------------------------------
double vtkSimpleReader::GetTimeValue(const std::string&)
{
return vtkMath::Nan();
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkSimpleReader.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.
=========================================================================*/
/**
* @class vtkSimpleReader
* @brief Superclass for algorithms that are not time or parallel aware
*
*/
#ifndef vtkSimpleReader_h
#define vtkSimpleReader_h
#include "vtkCommonExecutionModelModule.h" // For export macro
#include "vtkReaderAlgorithm.h"
#include <string> // needed for std::string in the interface
struct vtkSimpleReaderInternal;
class VTKCOMMONEXECUTIONMODEL_EXPORT vtkSimpleReader : public vtkReaderAlgorithm
{
public:
vtkTypeMacro(vtkSimpleReader,vtkReaderAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Add a filename to be read. Since this superclass handles
* file series to support time, multiple filenames can be added.
* Note that the time values are either integers growing sequentially,
* or are obtained from individual files as supported by the subclass.
*/
void AddFileName(const char* fname);
/**
* Removes all filenames stored by the reader.
*/
void ClearFileNames();
/**
* Returns the number of filenames stored by the reader.
*/
int GetNumberOfFileNames() const;
/**
* Returns a particular filename stored by the reader.
*/
const char* GetFileName(int i) const;
/**
* Returns the filename that was last loaded by the reader.
* This is set internally in ReadMesh()
*/
const char* GetCurrentFileName() const;
//@{
/**
* This is the superclass API overridden by this class
* to provide time support internally. Subclasses should
* not normally have to override these methods.
*/
int ReadTimeDependentMetaData(
int timestep, vtkInformation* metadata) override;
int ReadMetaData(vtkInformation* metadata) override;
int ReadMesh(
int piece, int npieces, int nghosts, int timestep,
vtkDataObject* output) override;
int ReadPoints(
int piece, int npieces, int nghosts, int timestep,
vtkDataObject* output) override;
int ReadArrays(
int piece, int npieces, int nghosts, int timestep,
vtkDataObject* output) override;
//@}
/**
* A subclass can override this method to provide an actual
* time value for a given file (this method is called for
* each filename stored by the reader). If time values is not
* available, the subclass does not have to override. This
* will return vtkMath::NaN() if no time value is present
* in the file.
*/
virtual double GetTimeValue(const std::string& fname);
/**
* A subclass can override this method to provide meta data
* specific to a particular file. In order for this method
* to be called, HasTemporalMetaData has to be set to true.
*/
virtual int ReadMetaDataSimple(const std::string& /*fname*/,
vtkInformation* /*metadata*/)
{
return 1;
}
/**
* A method that needs to be override by the subclass to provide
* the mesh (topology). Note that the filename is passed to this
* method and should be used by the subclass. The subclass directly
* adds the structure/topology to the provided data object.
*/
virtual int ReadMeshSimple(const std::string& fname,
vtkDataObject* output) = 0;
/**
* A method that needs to be override by the subclass to provide
* the point coordinates. Note that the filename is passed to this
* method and should be used by the subclass. The subclass directly
* adds the coordinates to the provided data object.
*/
virtual int ReadPointsSimple(const std::string& fname,
vtkDataObject* output) = 0;
/**
* A method that needs to be override by the subclass to provide
* data arrays. Note that the filename is passed to this
* method and should be used by the subclass. The subclass directly
* adds data arrays to the provided data object.
*/
virtual int ReadArraysSimple(const std::string& fname,
vtkDataObject* output) = 0;
protected:
vtkSimpleReader();
~vtkSimpleReader() override;
vtkExecutive* CreateDefaultExecutive() override;
int CurrentFileIndex;
bool HasTemporalMetaData;
private:
vtkSimpleReader(const vtkSimpleReader&) = delete;
void operator=(const vtkSimpleReader&) = delete;
vtkSimpleReaderInternal* Internal;
};
#endif
......@@ -176,27 +176,40 @@ int vtkStreamingDemandDrivenPipeline
return result;
}
// Look for specially supported requests.
// Look for specially supported requests.
if(request->Has(REQUEST_TIME_DEPENDENT_INFORMATION()))
{
int result = 1;
int outputPort = -1;
if(request->Has(FROM_OUTPUT_PORT()))
{
outputPort = request->Get(FROM_OUTPUT_PORT());
}
int N2E = 1;
if(outputPort>=0)
int N2E = this->Superclass::NeedToExecuteData(outputPort, inInfoVec,outInfoVec);
if(!N2E && outputPort>=0)
{
vtkInformation* outInfo = outInfoVec->GetInformationObject(outputPort);
if(!outInfo->Has(TIME_DEPENDENT_INFORMATION()))
vtkDataObject* dataObject = outInfo->Get(vtkDataObject::DATA_OBJECT());
if (outInfo->Has(TIME_DEPENDENT_INFORMATION()))
{
N2E = this->NeedToExecuteBasedOnTime(outInfo,dataObject);
}
else
{
N2E = 0;
}
}
if(!N2E)
if(N2E)
{
return 1;
if(!this->ForwardUpstream(request))
{
return 0;
}
result = this->CallAlgorithm(request, vtkExecutive::RequestUpstream,
inInfoVec, outInfoVec);
}
return result;
}
if(request->Has(REQUEST_UPDATE_EXTENT()))
......
......@@ -70,53 +70,21 @@ void vtkBiomTableReader::SetOutput(vtkTable *output)
}
//----------------------------------------------------------------------------
// I do not think this should be here, but I do not want to remove it now.
int vtkBiomTableReader::RequestUpdateExtent(
vtkInformation *,
vtkInformationVector **,
vtkInformationVector *outputVector)
int vtkBiomTableReader::ReadMeshSimple(const std::string& fname,
vtkDataObject* doOutput)
{
vtkInformation *outInfo = outputVector->GetInformationObject(0);
int piece, numPieces;
piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
// make sure piece is valid
if (piece < 0 || piece >= numPieces)
{
return 1;
}
return 1;
}
//----------------------------------------------------------------------------
int vtkBiomTableReader::RequestData(
vtkInformation *,
vtkInformationVector **,
vtkInformationVector *outputVector)
{
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// Return all data in the first piece ...
if(outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
{
return 1;
}
vtkDebugMacro(<<"Reading biom table...");
if(this->GetFileName() == nullptr || strcmp(this->GetFileName(), "") == 0)
if(fname.empty())
{
vtkErrorMacro(<<"Input filename not set");
return 1;
}
std::ifstream ifs( this->GetFileName(), std::ifstream::in );
std::ifstream ifs( fname, std::ifstream::in );
if(!ifs.good())
{
vtkErrorMacro(<<"Unable to open " << this->GetFileName() << " for reading");
vtkErrorMacro(<<"Unable to open " << fname << " for reading");
return 1;
}
......@@ -132,7 +100,8 @@ int vtkBiomTableReader::RequestData(
vtkNew<vtkStringArray> rowNames;
rowNames->SetName("name");
this->GetOutput()->AddColumn(rowNames);
vtkTable* output = vtkTable::SafeDownCast(doOutput);
output->AddColumn(rowNames);
for ( int i = 1; i < this->NumberOfColumns + 1; ++i )
{
switch(this->DataType)
......@@ -140,26 +109,26 @@ int vtkBiomTableReader::RequestData(
case VTK_INT:
{
vtkNew<vtkIntArray> intCol;
this->GetOutput()->AddColumn(intCol);