How to Isosurface for nc/netcdf Data?

Hi all,
I am trying to read a .nc file with the vtkNetCDFCFReader and use a vtkContourFilter on it. But as soon as I use the vtkContourFilter I see nothing but a black window. What am I doing wrong?
My Code:

string inputFilename = "C:\\snapshot_ql_00081.nc";

vtkSmartPointer<vtkNetCDFCFReader> cdfCFReader = vtkSmartPointer<vtkNetCDFCFReader>::New();
cdfCFReader->SetFileName(inputFilename.c_str());
cdfCFReader->UpdateInformation();
cdfCFReader->SetDimensions("z,y,x");
cdfCFReader->SetVariableArrayStatus("ql_3D", 1);

cdfCFReader->Update();

vtkSmartPointer<vtkContourFilter> contours = vtkSmartPointer<vtkContourFilter>::New();
contours->SetInputConnection(cdfCFReader->GetOutputPort());
contours->GenerateValues(10, 0, 0.257);
contours->Update();

vtkSmartPointer<vtkDataSetMapper> dataMapper = vtkSmartPointer<vtkDataSetMapper>::New();
dataMapper->SetInputConnection(contours->GetOutputPort());

vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(dataMapper);

vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderer->AddActor(actor);
renderer->ResetCamera();
renWin->AddRenderer(renderer);

interactor->SetRenderWindow(renWin);

renWin->Render();
interactor->Start();

Here is the rendered Image with and without the vtkContoutFilter:

Without: withoutContour
With: withContour

If I open the same file in ParaView with Contours I get a different result:

I can provide the test file if needed.
Thanks for your help in advance.

Hello, Alex,

According to the documentation of vtkContourFilter: https://vtk.org/doc/nightly/html/classvtkContourFilter.html#details, you need to compute the normals (with vtkPolyDataNormals) for the resulting vtkPolyData, assuming the output of vtkNetCDFCFReader is either a vtkUnstructuredGrid or a vtkStructuredGrid. Incorrect or null normals usually lead to problems with rendering.

all the best,

Paulo

Hello Paulo,
I get vtkImageDaten from the vtkCDFCFReader. I have tried to change the data type with
vtkCDFCFReader() -> SetOutputTypeToStructured();
and then calculating the normals with vtkPolyDateNormals, but unfortunately that didn’t work.
Do you have an idea how it could work with the vtkImageDate and vtkContourFilter?
Thanks for your help in advance.

Can you, please, post the strings returned by cdfCFReader->GetAllDimensions()?

According to the documentation, you could:

  • Remove the call to SetVariableArrayStatus();
  • Change the call to SetDimensions() to cdfCFReader->SetDimensions("z,y,x,ql_3D").

Alternativelly, try:

  • Remove the call to SetDimensions();
  • Add a call to SetDimensions() for each variable:
cdfCFReader->SetVariableArrayStatus("x", 1);
cdfCFReader->SetVariableArrayStatus("y", 1);
cdfCFReader->SetVariableArrayStatus("z", 1);
cdfCFReader->SetVariableArrayStatus("ql_3D", 1);

With cdfCFReader->GetAllDimensions():

vtkSmartPointer<vtkStringArray> stringallDims = vtkSmartPointer<vtkStringArray>::New();
stringallDims = cdfCFReader->GetAllDimensions();

for (int i = 0; i < stringallDims->GetNumberOfValues(); i++) {
	cout << "This is Dim: "<< i << " " << stringallDims->GetValue(i) << endl;
}

I get the following output:
“This is Dim: 0 (z,y,x)”

If I use cdfCFReader->SetDimensions("z,y,x,ql_3D") I get the same result with the black window like in the first post.
But if I use

cdfCFReader->SetVariableArrayStatus("x", 1);
cdfCFReader->SetVariableArrayStatus("y", 1);
cdfCFReader->SetVariableArrayStatus("z", 1);
cdfCFReader->SetVariableArrayStatus("ql_3D", 1);

i get the following error messages:

Warning: In G:\VTK-8.2.0\src\IO\NetCDF\vtkNetCDFReader.cxx, line 823
vtkNetCDFCFReader (000000985E5EC5A0): Variable x dimensions (x) are different than the other variable dimensions (z y x).  Skipping

Warning: In G:\VTK-8.2.0\src\IO\NetCDF\vtkNetCDFReader.cxx, line 823
vtkNetCDFCFReader (000000985E5EC5A0): Variable y dimensions (y) are different than the other variable dimensions (z y x).  Skipping

Warning: In G:\VTK-8.2.0\src\IO\NetCDF\vtkNetCDFReader.cxx, line 823
vtkNetCDFCFReader (000000985E5EC5A0): Variable z dimensions (z) are different than the other variable dimensions (z y x).  Skipping

Ok… can you try this:

cdfCFReader->SetVariableArrayStatus("z,y,x", 1);
cdfCFReader->SetVariableArrayStatus("ql_3D", 1);

?

If i do this I get a new error:

ERROR: In G:\VTK-8.2.0\src\IO\NetCDF\vtkNetCDFReader.cxx, line 202
vtkNetCDFCFReader (000000D3BD9EC5A0): netCDF Error: NetCDF: Variable not found

ERROR: In G:\VTK-8.2.0\src\Common\ExecutionModel\vtkExecutive.cxx, line 782
vtkCompositeDataPipeline (000000D3BD9ECC30): Algorithm vtkNetCDFCFReader(000000D3BD9EC5A0) returned failure for request: vtkInformation (000000D3BDE3D820)
  Debug: Off
  Modified Time: 1404
  Reference Count: 1
  Registered Events: (none)
  Request: REQUEST_INFORMATION
  FORWARD_DIRECTION: 0
  ALGORITHM_AFTER_FORWARD: 1



ERROR: In G:\VTK-8.2.0\src\IO\NetCDF\vtkNetCDFReader.cxx, line 761
vtkNetCDFCFReader (000000D3BD9EC5A0): netCDF Error: NetCDF: Variable not found

ERROR: In G:\VTK-8.2.0\src\Common\ExecutionModel\vtkExecutive.cxx, line 782
vtkCompositeDataPipeline (000000D3BD9ECC30): Algorithm vtkNetCDFCFReader(000000D3BD9EC5A0) returned failure for request: vtkInformation (000000D3BDE3F2A0)
  Debug: Off
  Modified Time: 1660
  Reference Count: 1
  Registered Events: (none)
  Request: REQUEST_DATA
  FORWARD_DIRECTION: 0
  ALGORITHM_AFTER_FORWARD: 1
  FROM_OUTPUT_PORT: 0

It seems that your original code is correct afterall, based on the almost absent documentation of the vtkNetCDFCFReader class. In that case, I’d report a bug: https://gitlab.kitware.com/vtk/vtk/issues

I suspect it’s a bug because ParaView uses a custom class: https://github.com/Kitware/ParaView/blob/df2aad3888107a6d61cd28bc755b535c7adcf471/Plugins/CDIReader/Reader/vtkCDIReader.h

Perhaps you could copy that over to your project (possibly along with some other source files) and give it a try while you wait for a feedback.

I have a solution for my Problem to use vtkAssignAttribute and vtkDataSetSurfaceFilter
Here the full code:

    vtkSmartPointer<vtkNetCDFCFReader> cdfCFReader = vtkSmartPointer<vtkNetCDFCFReader>::New();
    cdfCFReader->SetFileName(filenameNC.c_str());
    cdfCFReader->UpdateMetaData();
    cdfCFReader->SetVariableArrayStatus("ql_3D", 1);
    cdfCFReader->Update();

    vtkSmartPointer<vtkAssignAttribute> assignAttribute = vtkSmartPointer<vtkAssignAttribute>::New();
    assignAttribute->SetInputConnection(cdfCFReader->GetOutputPort());
    assignAttribute->Assign("ql_3D", "SCALARS", "POINT_DATA");
    
 
    vtkSmartPointer<vtkContourFilter> contour = vtkSmartPointer<vtkContourFilter>::New();
    contour->SetInputConnection(assignAttribute->GetOutputPort());
    contour->GenerateValues(10, 0.0, 0.257);

    vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    surfaceFilter->SetInputConnection(contour->GetOutputPort());

    vtkSmartPointer<vtkPolyDataMapper> polyMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    polyMapper->SetInputConnection(surfaceFilter->GetOutputPort());
    //polyMapper->SetScalarRange(0, 0.257);

    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(polyMapper);

    vtkSmartPointer<vtkRenderer> = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(actor);
	
    vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
    renWin->AddRenderer(renderer);
    renWin->Render();```

![grafik|506x500](upload://nD7XXQUXjxx2xS9h2UN1uolBE4A.png)
1 Like