Commit eade57f9 authored by Berk Geveci's avatar Berk Geveci Committed by Kitware Robot

Merge topic 'new-reader-architecture'

6d9117d2 New simplified interface for developing reader.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !4525
parents 726695e6 6d9117d2
......@@ -31,11 +31,14 @@ SET(Module_SRCS
vtkMoleculeAlgorithm.cxx
vtkMultiBlockDataSetAlgorithm.cxx
vtkMultiTimeStepAlgorithm.cxx
vtkParallelReader.cxx
vtkPassInputTypeAlgorithm.cxx
vtkPiecewiseFunctionAlgorithm.cxx
vtkPiecewiseFunctionShiftScale.cxx
vtkPointSetAlgorithm.cxx
vtkPolyDataAlgorithm.cxx
vtkReaderAlgorithm.cxx
vtkReaderExecutive.cxx
vtkRectilinearGridAlgorithm.cxx
vtkScalarTree.cxx
vtkSimpleImageToImageFilter.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkParallelReader.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 "vtkParallelReader.h"
#include "vtkInformation.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include <vector>
#include <numeric>
struct vtkParallelReaderInternal
{
using FileNamesType = std::vector<std::string>;
FileNamesType FileNames;
};
//----------------------------------------------------------------------------
vtkParallelReader::vtkParallelReader()
{
this->Internal = new vtkParallelReaderInternal;
this->CurrentFileIndex = -1;
}
//----------------------------------------------------------------------------
vtkParallelReader::~vtkParallelReader()
{
delete this->Internal;
}
//----------------------------------------------------------------------------
void vtkParallelReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
void vtkParallelReader::AddFileName(const char* fname)
{
if(fname == nullptr || strlen(fname) == 0)
{
return;
}
this->Internal->FileNames.push_back(fname);
this->Modified();
}
//----------------------------------------------------------------------------
void vtkParallelReader::ClearFileNames()
{
this->Internal->FileNames.clear();
this->Modified();
}
//----------------------------------------------------------------------------
int vtkParallelReader::GetNumberOfFileNames() const
{
return static_cast<int>(this->Internal->FileNames.size());
}
//----------------------------------------------------------------------------
const char* vtkParallelReader::GetFileName(int i) const
{
return this->Internal->FileNames[i].c_str();
}
//----------------------------------------------------------------------------
const char* vtkParallelReader::GetCurrentFileName() const
{
if (this->CurrentFileIndex < 0 ||
this->CurrentFileIndex >= (int)this->Internal->FileNames.size())
{
return nullptr;
}
return this->Internal->FileNames[this->CurrentFileIndex].c_str();
}
//----------------------------------------------------------------------------
int vtkParallelReader::ReadMetaData(vtkInformation* metadata)
{
metadata->Set(vtkAlgorithm::CAN_HANDLE_PIECE_REQUEST(), 1);
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 vtkParallelReader::ReadMesh(
int piece, int npieces, int nghosts, int timestep, vtkDataObject* output)
{
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->ReadMesh(
this->Internal->FileNames[timestep], piece, npieces, nghosts, output))
{
this->CurrentFileIndex = timestep;
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
int vtkParallelReader::ReadPoints(
int piece, int npieces, int nghosts, int timestep, vtkDataObject* output)
{
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->ReadPoints(
this->Internal->FileNames[timestep], piece, npieces, nghosts, output);
}
//----------------------------------------------------------------------------
int vtkParallelReader::ReadArrays(
int piece, int npieces, int nghosts, int timestep, vtkDataObject* output)
{
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->ReadArrays(
this->Internal->FileNames[timestep], piece, npieces, nghosts, output);
}
//----------------------------------------------------------------------------
double vtkParallelReader::GetTimeValue(const std::string&)
{
return vtkMath::Nan();
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkParallelReader.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 vtkParallelReader
* @brief Superclass for algorithms that are parallel aware
*
* vtkParallelReader is a vtkReaderAlgorithm subclass that provides
* a specialized API to develop readers that are parallel aware (i.e.
* can handle piece requests) but do not natively support time series.
* This reader adds support for file series in order to support time
* series.
*/
#ifndef vtkParallelReader_h
#define vtkParallelReader_h
#include "vtkCommonExecutionModelModule.h" // For export macro
#include "vtkReaderAlgorithm.h"
#include <string> // needed for std::string in the interface
struct vtkParallelReaderInternal;
class VTKCOMMONEXECUTIONMODEL_EXPORT vtkParallelReader : public vtkReaderAlgorithm
{
public:
vtkTypeMacro(vtkParallelReader,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 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;
//@}
protected:
vtkParallelReader();
~vtkParallelReader() 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.
*/
virtual double GetTimeValue(const std::string& fname);
/**
* 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 ReadMesh(const std::string& fname,
int piece,
int npieces,
int nghosts,
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 ReadPoints(const std::string& fname,
int piece,
int npieces,
int nghosts,
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 ReadArrays(const std::string& fname,
int piece,
int npieces,
int nghosts,
vtkDataObject* output) = 0;
int CurrentFileIndex;
private:
vtkParallelReader(const vtkParallelReader&) = delete;
void operator=(const vtkParallelReader&) = delete;
vtkParallelReaderInternal* Internal;
};
#endif
/*=========================================================================
Program: Visualization Toolkit
Module: vtkReaderAlgorithm.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 "vtkReaderAlgorithm.h"
#include "vtkObjectFactory.h"
//----------------------------------------------------------------------------
vtkReaderAlgorithm::vtkReaderAlgorithm()
{
// by default assume filters have one input and one output
// subclasses that deviate should modify this setting
this->SetNumberOfOutputPorts(1);
}
//----------------------------------------------------------------------------
vtkReaderAlgorithm::~vtkReaderAlgorithm() = default;
//----------------------------------------------------------------------------
void vtkReaderAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkReaderAlgorithm.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 vtkReaderAlgorithm
* @brief Superclass for readers that implement a simplified API.
*
* This class and associated subclasses were created to make it easier to
* develop readers. When directly subclassing from other algorithm classes
* one has to learn a general purpose API that somewhat obfuscates pipeline
* functionality behind information keys. One has to know how to find
* time and pieces requests using keys for example. Furthermore, these
* classes together with specialized executives can implement common
* reader functionality for things such as file series (for time and/or
* partitions), caching, mapping time requests to indices etc.
* This class implements the most basic API which is specialized as
* needed by subclasses (for file series for example).
*/
#ifndef vtkReaderAlgorithm_h
#define vtkReaderAlgorithm_h
#include "vtkCommonExecutionModelModule.h" // For export macro
#include "vtkAlgorithm.h"
class VTKCOMMONEXECUTIONMODEL_EXPORT vtkReaderAlgorithm : public vtkAlgorithm
{
public:
vtkTypeMacro(vtkReaderAlgorithm,vtkAlgorithm);
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
* interfaces making this simpler.
*/
virtual int ReadMetaData(vtkInformation* metadata) = 0;
/**
* Read the mesh (connectivity) for a given set of data partitioning,
* number of ghost levels and time step (index). The reader populates
* the data object passed in as the last argument. It is OK to read
* more than the mesh (points, arrays etc.). However, this may interfere
* with any caching implemented by the executive (i.e. cause more reads).
*/
virtual int ReadMesh(
int piece, int npieces, int nghosts, int timestep,
vtkDataObject* output) = 0;
/**
* Read the points. The reader populates the input data object. This is
* called after ReadMesh() so the data object should already contain the
* mesh.
*/
virtual int ReadPoints(
int piece, int npieces, int nghosts, int timestep,
vtkDataObject* output) = 0;
/**
* Read all the arrays (point, cell, field etc.). This is called after
* ReadPoints() so the data object should already contain the mesh and
* points.
*/
virtual int ReadArrays(
int piece, int npieces, int nghosts, int timestep,
vtkDataObject* output) = 0;
protected:
vtkReaderAlgorithm();
~vtkReaderAlgorithm() override;
private:
vtkReaderAlgorithm(const vtkReaderAlgorithm&) = delete;
void operator=(const vtkReaderAlgorithm&) = delete;
};
#endif
/*=========================================================================
Program: Visualization Toolkit
Module: vtkReaderExecutive.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 "vtkReaderExecutive.h"
#include "vtkAlgorithm.h"
#include "vtkDataObject.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkReaderAlgorithm.h"
vtkStandardNewMacro(vtkReaderExecutive);
//----------------------------------------------------------------------------
vtkReaderExecutive::vtkReaderExecutive()
{
}
//----------------------------------------------------------------------------
vtkReaderExecutive::~vtkReaderExecutive()
{}
//----------------------------------------------------------------------------
void vtkReaderExecutive::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
int vtkReaderExecutive::CallAlgorithm(vtkInformation* request, int direction,
vtkInformationVector** inInfo,
vtkInformationVector* outInfo)
{
// Copy default information in the direction of information flow.
this->CopyDefaultInformation(request, direction, inInfo, outInfo);
// Invoke the request on the algorithm.
this->InAlgorithm = 1;
int result = 1; // this->Algorithm->ProcessRequest(request, inInfo, outInfo);
vtkReaderAlgorithm* reader = vtkReaderAlgorithm::SafeDownCast(this->Algorithm);
if (!reader)
{
return 0;
}
if (request->Has(REQUEST_INFORMATION()))
{
result = reader->ReadMetaData(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);
if (result)
{
result = reader->ReadPoints(
piece, npieces, nghosts, timeIndex, output);
}
if (result)
{
result = reader->ReadArrays(
piece, npieces, nghosts, timeIndex, output);
}
}
this->InAlgorithm = 0;
// If the algorithm failed report it now.
if(!result)
{
vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName()
<< "(" << this->Algorithm
<< ") returned failure for request: "
<< *request);
}
return result;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkReaderExecutive.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 vtkReaderExecutive
* @brief Executive that works with vtkReaderAlgorithm and subclasses.
*
* vtkReaderExecutive is an executive that supports simplified API readers
* that are written by subclassing from the vtkReaderAlgorithm hierarchy.
* Currently, its main functionality is to call the basic reader API instead
* if the standard ProcessRequest() method that other algorithms use.
* In time, this is likely to add functionality such as caching. See
* vtkReaderAlgorithm for the API.
*
* Note that this executive assumes that the reader has one output port.
*/
#ifndef vtkReaderExecutive_h
#define vtkReaderExecutive_h
#include "vtkCommonExecutionModelModule.h" // For export macro
#include "vtkStreamingDemandDrivenPipeline.h"
class VTKCOMMONEXECUTIONMODEL_EXPORT vtkReaderExecutive :
public vtkStreamingDemandDrivenPipeline
{
public:
static vtkReaderExecutive* New();
vtkTypeMacro(vtkReaderExecutive,vtkStreamingDemandDrivenPipeline);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Overwritten to call the vtkReaderAlgorithm API instead of
* ProcessRequest().
*/
virtual int CallAlgorithm(vtkInformation* request, int direction,
vtkInformationVector** inInfo,
vtkInformationVector* outInfo) override;
protected:
vtkReaderExecutive();
~vtkReaderExecutive() override;
private:
vtkReaderExecutive(const vtkReaderExecutive&) = delete;
void operator=(const vtkReaderExecutive&) = delete;
};
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -34,9 +34,10 @@
* alpha, tuple 2: re, tuple 3: time). In addition, the solution file contains
* the flow density (scalar), flow momentum (vector), and flow energy (scalar).
*
* Note that this reader does not support time series data which is usually
* stored as a series of Q and optionally XYZ files. If you want to read such
* a file series, use vtkPlot3DMetaReader.
* This reader supports a limited form of time series data which are stored
* as a series of Q files. Using the AddFileName() method provided by the
* superclass, one can define a file series. For other cases, for example where
* the XYZ or function files vary over time, use vtkPlot3DMetaReader.
*
* The reader can generate additional scalars and vectors (or "functions")
* from this information. To use vtkMultiBlockPLOT3DReader, you must specify the
......@@ -88,7 +89,7 @@
#include <vector> // For holding function-names
#include "vtkIOParallelModule.h" // For export macro
#include "vtkMultiBlockDataSetAlgorithm.h"
#include "vtkParallelReader.h"
class vtkDataArray;
class vtkDataSetAttributes;
......@@ -98,6 +99,7 @@ class vtkMultiProcessController;
class vtkStructuredGrid;
class vtkUnsignedCharArray;
struct vtkMultiBlockPLOT3DReaderInternals;
class vtkMultiBlockDataSet;
namespace Functors
{
......@@ -120,7 +122,7 @@ namespace Functors
}
class VTKIOPARALLEL_EXPORT vtkMultiBlockPLOT3DReader : public vtkMultiBlockDataSetAlgorithm
class VTKIOPARALLEL_EXPORT vtkMultiBlockPLOT3DReader : public vtkParallelReader
{
friend class Functors::ComputeFunctor;
friend class Functors::ComputeTemperatureFunctor;
......@@ -140,25 +142,42 @@ friend class Functors::ComputeVorticityFunctor;
friend class Functors::ComputeStrainRateFunctor;
public:
static vtkMultiBlockPLOT3DReader *New();
vtkTypeMacro(vtkMultiBlockPLOT3DReader,vtkMultiBlockDataSetAlgorithm);
vtkTypeMacro(vtkMultiBlockPLOT3DReader,vtkParallelReader);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@{
/**
* Get the output data object for a port on this algorithm.
*/
vtkMultiBlockDataSet* GetOutput();
vtkMultiBlockDataSet* GetOutput(int);
//@}
//@{
/**
* Set/Get the PLOT3D geometry filename.
*/
void SetFileName(const char* name) { this->SetXYZFileName(name); }
const char* GetFileName() { return this->GetXYZFileName(); }
const char* GetFileName(int i) { return this->vtkParallelReader::GetFileName(i); }
virtual void SetXYZFileName( const char* );
vtkGetStringMacro(XYZFileName);
//@}
//@{
/**
* Set/Get the PLOT3D solution filename.