Commit 884b5fff authored by John Biddiscombe's avatar John Biddiscombe
Browse files

ENH: Add Time support to Reader. We check for CollectionType attribute on the...

ENH: Add Time support to Reader. We check for CollectionType attribute on the main top level grid, and if it is temporal, we collect the list of time values from each sub grid. This is exported. When Time values are requested we output the correct sub grid.
Lots of internal changes to tidy up the code and handle information.
BUG: Several bug fixes for reading in parallel. Extents were not always correct. Seem to be ok for image data now
parent 3b30c806
......@@ -215,8 +215,8 @@ protected:
XdmfInt32 UpdateInformationUniform();
XdmfInt32 UpdateInformationCollection();
XdmfInt32 UpdateInformationTree();
XdmfInt32 UpdateInformationFunction(); // HpyerSlab, Coordinates or Function
XdmfInt32 UpdateFunction(); // HpyerSlab, Coordinates or Function
XdmfInt32 UpdateInformationFunction(); // HyperSlab, Coordinates or Function
XdmfInt32 UpdateFunction(); // HyperSlab, Coordinates or Function
};
#endif // __XdmfDataItem_h
/*=========================================================================
/*=========================================================================
Program: Visualization Toolkit
Module: vtkXdmfReader.cxx
......@@ -74,19 +74,23 @@
#include "XdmfGrid.h"
#include "XdmfTopology.h"
#include "XdmfGeometry.h"
#include "XdmfTime.h"
#include <sys/stat.h>
#include <vtkstd/set>
#include <vtkstd/map>
#include <vtkstd/string>
#include <vtkstd/vector>
#include <vtksys/SystemTools.hxx>
#include <assert.h>
#include <functional>
#include <algorithm>
#define USE_IMAGE_DATA // otherwise uniformgrid
//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkXdmfReader);
vtkCxxRevisionMacro(vtkXdmfReader, "1.35");
vtkCxxRevisionMacro(vtkXdmfReader, "1.36");
//----------------------------------------------------------------------------
vtkCxxSetObjectMacro(vtkXdmfReader,Controller,vtkMultiProcessController);
......@@ -103,11 +107,11 @@ vtkCxxSetObjectMacro(vtkXdmfReader,Controller,vtkMultiProcessController);
#define vtkMIN(x, y) (((x)<(y))?(x):(y))
#define PRINT_EXTENT(x) "[" << (x)[0] << " " << (x)[1] << " " << (x)[2] << " " << (x)[3] << " " << (x)[4] << " " << (x)[5] << "]"
//============================================================================
//----------------------------------------------------------------------------
class vtkXdmfReaderGrid
{
public:
//
vtkXdmfReaderGrid()
: XMGrid(0), DataDescription(0), Enabled(0), vtkType(-1)
{
......@@ -116,10 +120,10 @@ public:
~vtkXdmfReaderGrid()
{
delete this->XMGrid;
vtkstd::map<vtkstd::string, vtkXdmfReaderGrid*>::iterator it;
vtkstd::vector<vtkXdmfReaderGrid*>::iterator it;
for (it = Children.begin(); it != Children.end(); it++)
{
delete it->second;
delete *it;
}
}
......@@ -140,44 +144,53 @@ public:
int Enabled;
int vtkType;
vtkstd::map<vtkstd::string, vtkXdmfReaderGrid*> Children;
vtkstd::vector<vtkXdmfReaderGrid*> Children;
vtkSmartPointer<vtkInformation> Information;
};
//----------------------------------------------------------------------------
vtkXdmfReaderGrid* vtkXdmfReaderGrid::GetChild(const char *gridName)
class vtkXdmfReaderMatchName : public vtkstd::binary_function<vtkXdmfReaderGrid *, const char *, bool>
{
//find the grid with that name or make one up
vtkstd::map<vtkstd::string, vtkXdmfReaderGrid*>::iterator it =
this->Children.find(gridName);
if ( it == this->Children.end() || it->second == 0 )
public:
bool operator()(vtkXdmfReaderGrid *child, const char *name) const
{
return NULL;
//this->Children[gridName] = new vtkXdmfReaderGrid;
return (child->Name==name);
}
return this->Children[gridName];
};
//----------------------------------------------------------------------------
vtkXdmfReaderGrid* vtkXdmfReaderGrid::GetChild(const char *gridName)
{
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it =
vtkstd::find_if(this->Children.begin(), this->Children.end(),
vtkstd::bind2nd(vtkXdmfReaderMatchName(),gridName));
if (it!=this->Children.end())
{
return *it;
}
return NULL;
}
//----------------------------------------------------------------------------
vtkXdmfReaderGrid* vtkXdmfReaderGrid::GetChild(int idx)
{
if ( idx < 0 )
if ( idx<0 || idx>=(int)this->Children.size())
{
return NULL;
}
vtkstd::map<vtkstd::string,vtkXdmfReaderGrid*>::iterator it;
return this->Children[idx];
/*
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it;
int cnt = 0;
for ( it = this->Children.begin();
it != this->Children.end();
++ it )
for ( it = this->Children.begin(); it != this->Children.end(); ++ it )
{
if ( cnt == idx )
{
return it->second;
return *it;
}
cnt ++;
}
return NULL;
*/
}
//============================================================================
......@@ -191,6 +204,9 @@ public:
this->DomainPtr = NULL;
this->Data = NULL;
this->DsmBuffer = NULL;
this->UpdatePiece = 0;
this->UpdateNumPieces = 1;
}
~vtkXdmfReaderInternal()
......@@ -211,7 +227,7 @@ public:
vtkXdmfReaderGrid* GetGrid(const char* gridName);
vtkXdmfReaderGrid* GetGrid(int idx);
vtkXdmfReaderGrid *MakeGrid(
vtkXdmfReaderGrid *AddGrid(
vtkXdmfReaderGrid *parent,
const char *gridName);
......@@ -224,6 +240,7 @@ public:
double progressS, double progressE);
vtkstd::vector<XdmfFloat64> TimeValues;
vtkstd::vector<vtkstd::string> DomainList;
XdmfXmlNode DomainPtr;
vtkXdmfReaderGrid *Data;
......@@ -234,6 +251,10 @@ public:
// For converting arrays from XDMF to VTK format
vtkXdmfDataArray *ArrayConverter;
int UpdatePiece;
int UpdateNumPieces;
};
//----------------------------------------------------------------------------
......@@ -258,7 +279,7 @@ vtkXdmfReaderGrid* vtkXdmfReaderInternal::GetGrid(int idx)
//----------------------------------------------------------------------------
vtkXdmfReaderGrid*
vtkXdmfReaderInternal::MakeGrid(
vtkXdmfReaderInternal::AddGrid(
vtkXdmfReaderGrid* parent,
const char *gridName)
{
......@@ -268,12 +289,13 @@ vtkXdmfReaderGrid*
}
//finds or makes up an ActualGrid in the global list
vtkXdmfReaderGrid* grid = parent->GetChild(gridName);
if ( !grid )
{
grid = new vtkXdmfReaderGrid;
parent->Children[gridName] = grid;
}
// vtkXdmfReaderGrid* grid = parent->GetChild(gridName);
// if ( !grid )
// {
vtkXdmfReaderGrid* grid = grid = new vtkXdmfReaderGrid;
grid->Name = gridName;
parent->Children.push_back(grid);
// }
return grid;
}
......@@ -375,7 +397,12 @@ vtkXdmfReader::vtkXdmfReader()
this->CellDataArraySelection->AddObserver(vtkCommand::ModifiedEvent,
this->SelectionObserver);
this->OutputVTKType = -1;
this->OutputVTKType = -1;
this->OutputTemporal = 0;
this->TimeStep = 0;
this->ActualTimeStep = 0;
this->TimeStepRange[0] = 0.0;
this->TimeStepRange[1] = 0.0;
}
//----------------------------------------------------------------------------
......@@ -925,11 +952,13 @@ int vtkXdmfReader::GetNumberOfGrids()
//----------------------------------------------------------------------------
const char* vtkXdmfReader::GetGridName(int idx)
{
if ( idx < 0 )
if ( idx<0 || idx>=(int)this->Internals->Data->Children.size())
{
return 0;
}
vtkstd::map<vtkstd::string,vtkXdmfReaderGrid*>::iterator it;
return this->Internals->Data->Children[idx]->Name.c_str();
/*
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it;
int cnt = 0;
for ( it = this->Internals->Data->Children.begin();
it != this->Internals->Data->Children.end();
......@@ -937,11 +966,12 @@ const char* vtkXdmfReader::GetGridName(int idx)
{
if ( cnt == idx )
{
return it->first.c_str();
return (*it)->Name.c_str();
}
cnt ++;
}
return 0;
*/
}
//----------------------------------------------------------------------------
......@@ -951,13 +981,13 @@ int vtkXdmfReader::GetGridIndex(const char* name)
{
return -1;
}
vtkstd::map<vtkstd::string,vtkXdmfReaderGrid *>::iterator it;
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it;
int cnt = 0;
for ( it = this->Internals->Data->Children.begin();
it != this->Internals->Data->Children.end();
++ it )
{
if ( it->first == name )
if ( (*it)->Name == name )
{
return cnt;
}
......@@ -1010,15 +1040,15 @@ void vtkXdmfReader::EnableGrid(int idx)
void vtkXdmfReader::EnableAllGrids()
{
vtkDebugMacro("Enable all grids");
vtkstd::map<vtkstd::string,vtkXdmfReaderGrid*>::iterator it;
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it;
int changed=0;
for ( it = this->Internals->Data->Children.begin();
it != this->Internals->Data->Children.end();
++ it )
{
if(!it->second->Enabled)
if(!(*it)->Enabled)
{
it->second->Enabled = 1;
(*it)->Enabled = 1;
++this->NumberOfEnabledActualGrids;
changed=1;
}
......@@ -1079,15 +1109,15 @@ void vtkXdmfReader::DisableGrid(int idx)
void vtkXdmfReader::DisableAllGrids()
{
vtkDebugMacro("Disable all grids");
vtkstd::map<vtkstd::string,vtkXdmfReaderGrid*>::iterator it;
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it;
int changed=0;
for ( it = this->Internals->Data->Children.begin();
it != this->Internals->Data->Children.end();
++ it )
{
if(it->second->Enabled)
if((*it)->Enabled)
{
it->second->Enabled = 0;
(*it)->Enabled = 0;
--this->NumberOfEnabledActualGrids;
changed=1;
}
......@@ -1105,7 +1135,7 @@ void vtkXdmfReader::DisableAllGrids()
void vtkXdmfReader::RemoveAllGrids()
{
vtkDebugMacro("Remove all grids");
vtkstd::map<vtkstd::string,vtkXdmfReaderGrid*>::iterator it;
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it;
if (this->Internals->Data)
{
delete this->Internals->Data;
......@@ -1237,9 +1267,15 @@ void vtkXdmfReader::UpdateRootGrid()
this->UpdateGrids(ptr, domain);
int nchildren = ptr->Children.size();
//vtkDebugMacro("Created " << nchildren << " top level grids.");
this->OutputTemporal = 0;
if (nchildren == 1)
{
this->OutputVTKType = this->Internals->GetGrid(0)->vtkType;
if (this->OutputVTKType==VTK_TEMPORAL_DATA_SET)
{
this->OutputVTKType = this->Internals->GetGrid(0)->GetChild(this->ActualTimeStep)->vtkType;
this->OutputTemporal = 1;
}
}
else
{
......@@ -1257,6 +1293,7 @@ void vtkXdmfReader::UpdateGrids(
return;
}
int usedIndexes = 0;
int done = 0;
int NGrid;
XdmfXmlNode gridNode = 0;
......@@ -1283,8 +1320,6 @@ void vtkXdmfReader::UpdateGrids(
str << gridName << ends;
}
gridName = str.str();
char *gridNameCopy = new char[strlen(gridName)+1];
strcpy(gridNameCopy, gridName);
vtkDebugMacro("Reading Light Data for " << gridName);
// What Type of Grid
......@@ -1296,21 +1331,27 @@ void vtkXdmfReader::UpdateGrids(
}
vtkXdmfReaderGrid *sub;
if(XDMF_WORD_CMP(gridType, "Tree")||
XDMF_WORD_CMP(gridType, "Collection"))
{
vtkDebugMacro(" Grid is a Tree ");
sub = this->Internals->MakeGrid(parent, gridNameCopy);
if (sub)
vtkDebugMacro(" Grid is a Collection/Tree ");
sub = this->Internals->AddGrid(parent, gridName);
this->UpdateGrids(sub, gridNode);
sub->vtkType = VTK_MULTIBLOCK_DATA_SET;
// If grid is a collection, is it a temporal one?
XdmfConstString collType = this->DOM->GetAttribute((XdmfXmlNode)gridNode, "CollectionType");
if(XDMF_WORD_CMP(collType, "Temporal"))
{
this->UpdateGrids(sub, gridNode);
sub->vtkType = VTK_MULTIBLOCK_DATA_SET;
vtkDebugMacro(" Grid is a TemporalDataSetCollection ");
// we will not output a TemporalDataset, but use this as a flag for later
sub->vtkType = VTK_TEMPORAL_DATA_SET;
}
}
}
else
{
// It's a Uniform Grid
sub = this->Internals->MakeGrid(parent, gridNameCopy);
sub = this->Internals->AddGrid(parent, gridName);
if ( sub )
{
if ( !sub->XMGrid )
......@@ -1350,7 +1391,6 @@ void vtkXdmfReader::UpdateGrids(
}
}
delete [] gridNameCopy;
str.rdbuf()->freeze(0);
}
}
......@@ -1438,97 +1478,77 @@ int vtkXdmfReader::RequestDataObject(vtkInformationVector *outputVector)
// Produce an empty data object of the proper type for RequestData to fill
// in later.
vtkIdType cc;
XdmfConstString CurrentFileName;
vtkstd::string directory;
// Reading from File or String
if(this->GetReadFromInputString()){
if (this->GetReadFromInputString()){
char *InputTxt;
InputTxt = new char[this->InputStringLength + 1];
if ( !this->DOM ){
this->DOM = new XdmfDOM();
}
if ( !this->Internals->DataItem ){
this->Internals->DataItem = new XdmfDataItem();
this->Internals->DataItem->SetDOM(this->DOM);
}
if ( !this->DOM )
{
this->DOM = new XdmfDOM();
}
if ( !this->Internals->DataItem )
{
this->Internals->DataItem = new XdmfDataItem();
this->Internals->DataItem->SetDOM(this->DOM);
}
memcpy(InputTxt, this->GetInputString(), this->InputStringLength);
InputTxt[this->InputStringLength] = 0;
this->DOM->Parse(InputTxt);
this->GridsModified = 1;
delete InputTxt;
}else{
}
else
{
// Parse the file...
if ( !this->FileName )
{
vtkErrorMacro("File name not set");
return 1;
}
// First make sure the file exists. This prevents an empty file
// from being created on older compilers.
struct stat fs;
if(stat(this->FileName, &fs) != 0)
{
if (!vtksys::SystemTools::FileExists(this->FileName)) {
vtkErrorMacro("Error opening file " << this->FileName);
return 1;
}
if ( !this->DOM )
{
this->DOM = new XdmfDOM();
}
//Tell the parser what the working directory is.
char* filename = 0;
if ( this->FileName )
{
filename = new char[ strlen(this->FileName)+ 1];
strcpy(filename, this->FileName);
}
int len = static_cast<int>(strlen(filename));
for ( cc = len-1; cc >= 0; cc -- )
{
if ( filename[cc] != '/' && filename[cc] != '\\' )
if ( !this->DOM )
{
filename[cc] = 0;
this->DOM = new XdmfDOM();
}
else
//Tell the parser what the working directory is.
directory = vtksys::SystemTools::GetFilenamePath(this->FileName) + "/";
if (directory == "")
{
break;
directory = vtksys::SystemTools::GetCurrentWorkingDirectory() + "/";
}
}
if ( filename[0] == 0 )
{
char buffer[1024];
if ( GETCWD(buffer, 1023) )
directory = vtksys::SystemTools::ConvertToOutputPath(directory.c_str());
this->DOM->SetWorkingDirectory(directory.c_str());
// this->DOM->GlobalDebugOn();
if ( !this->Internals->DataItem )
{
delete [] filename;
if ( buffer[0] )
{
filename = new char[ strlen(buffer)+ 1];
strcpy(filename, buffer);
}
this->Internals->DataItem = new XdmfDataItem();
this->Internals->DataItem->SetDOM(this->DOM);
}
CurrentFileName = this->DOM->GetInputFileName();
// Only re-parse when necessary. Reparsing can be slow and can reset
// parameters and stride that we read from file but then allow user to
// modify.
if ((CurrentFileName == NULL) ||
(STRCASECMP(CurrentFileName, this->FileName) != 0 ))
{
this->DOM->SetInputFileName(this->FileName);
vtkDebugMacro(".!!............Preparing to Parse " << this->FileName);
this->DOM->Parse(this->FileName);
this->GridsModified = 1;
}
}
this->DOM->SetWorkingDirectory(filename);
delete [] filename;
// this->DOM->GlobalDebugOn();
if ( !this->Internals->DataItem )
{
this->Internals->DataItem = new XdmfDataItem();
this->Internals->DataItem->SetDOM(this->DOM);
}
CurrentFileName = this->DOM->GetInputFileName();
// Only re-parse when necessary. Reparsing can be slow and can reset
// parameters and stride that we read from file but then allow user to
// modify.
if((CurrentFileName == NULL) ||
(STRCASECMP(CurrentFileName, this->FileName) != 0 ))
{
this->DOM->SetInputFileName(this->FileName);
vtkDebugMacro(".!!............Preparing to Parse " << this->FileName);
this->DOM->Parse();
this->GridsModified = 1;
}
}
//TODO: avoid everything below if nothing has changed? Or is this taken
......@@ -1565,25 +1585,25 @@ int vtkXdmfReader::RequestDataObject(vtkInformationVector *outputVector)
int vtkXdmfReaderInternal::RequestGridInformation(
vtkXdmfReaderGrid *grid)
{
if (grid->vtkType == VTK_MULTIBLOCK_DATA_SET)
if (grid->Children.size()>0)
{
//recurse inside composite datasets
vtkDebugWithObjectMacro(this->Reader,
"Requesting info in collection or tree "
<< grid->Name.c_str());
vtkstd::map<vtkstd::string,vtkXdmfReaderGrid*>::iterator it;
vtkstd::vector<vtkXdmfReaderGrid *>::iterator it;
for ( it = grid->Children.begin();
it != grid->Children.end();
++it )
{
//if (it->second->Enabled ) //only top level grids can be disabled
//if ((*it)->Enabled ) //only top level grids can be disabled
{
this->RequestGridInformation(it->second);
this->RequestGridInformation((*it));
}
}
return 1;
}
vtkInformation* outInfo = grid->GetInformation();
vtkInformation* gridInfo = grid->GetInformation();
XdmfInt32 Rank;
XdmfInt64 Dimensions[ XDMF_MAX_DIMENSION ];
......@@ -1644,7 +1664,7 @@ int vtkXdmfReaderInternal::RequestGridInformation(
<< (vtkIdType)EndExtent[1] << ", "
<< (vtkIdType)EndExtent[2]);
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
gridInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
0, EndExtent[2], 0, EndExtent[1], 0, EndExtent[0]);
vtkDebugWithObjectMacro(this->Reader,
......@@ -1659,14 +1679,14 @@ int vtkXdmfReaderInternal::RequestGridInformation(
{
vtkDebugWithObjectMacro(this->Reader,
"Setting Extents for vtkStructuredGrid");
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
gridInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
0, EndExtent[2], 0, EndExtent[1], 0, EndExtent[0]);
}
else if ( xdmfGrid->GetTopology()->GetTopologyType() == XDMF_2DCORECTMESH||
xdmfGrid->GetTopology()->GetTopologyType() == XDMF_3DCORECTMESH )
{
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
gridInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
0, EndExtent[2], 0, EndExtent[1], 0, EndExtent[0]);
XdmfGeometry *Geometry = xdmfGrid->GetGeometry();
......@@ -1677,9 +1697,9 @@ int vtkXdmfReaderInternal::RequestGridInformation(
XdmfFloat64 *origin = Geometry->GetOrigin();
XdmfFloat64 *spacing = Geometry->GetDxDyDz();
outInfo->Set(vtkDataObject::ORIGIN(),
gridInfo->Set(vtkDataObject::ORIGIN(),
origin[2], origin[1], origin[0]);
outInfo->Set(vtkDataObject::SPACING(),
gridInfo->Set(vtkDataObject::SPACING(),
spacing[2], spacing[1], spacing[0]);
}
}
......@@ -1688,7 +1708,7 @@ int vtkXdmfReaderInternal::RequestGridInformation(
{
vtkDebugWithObjectMacro(this->Reader,
"Setting Extents for vtkRectilinearGrid");
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
gridInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
0, EndExtent[2], 0, EndExtent[1], 0, EndExtent[0]);
}
......@@ -1700,7 +1720,14 @@ int vtkXdmfReaderInternal::RequestGridInformation(
int uExt[6];
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExt);
if (gridInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()))
{
gridInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExt);
}
else
{
memcpy(uExt, EndExtent, sizeof(int)*6);
}
vtkDebugWithObjectMacro(this->Reader,
"Update Extents: " <<
......@@ -1711,9 +1738,28 @@ int vtkXdmfReaderInternal::RequestGridInformation(
uExt[4] << ", " <<
uExt[5] );
}
return 1;
}
//-----------------------------------------------------------------------------
void vtkXdmfReader::FindTimeValues()
{
vtkXdmfReaderGrid *ptr = this->Internals->Data;
if (!ptr)
{