[vtkusers] Extract csv row and column into points

Polly Pui polly_sukting at hotmail.com
Thu Nov 15 01:25:59 EST 2018


Hi Cory,
Thanks for your reply.
I edited my codes by following your advice. However, I am not able to visualize the point of cluster and got an error message.

I have a few questions here.
Is it possible to call VTK unstructured grid data into vtkKmeansStatistics?

Actually what i wanted to do is very simple.
I want to read my csv or vtk file and then cluster the points using kmeansclustering.
Initially, I extracted points from csv file manually and I could get my desired output. But it is too time consuming.
Currently, I want to input the csv or vtk file and get the cluster automatically and store in a datasheet.
I attach my code as follows:

#include <vtkVersion.h>
#include "library.h"

#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkPointData.h>
#include <vtkPolyData.h>
#include <vtkXMLPolyDataWriter.h>


std::string inputFilename = argv[1];

vtkSmartPointer<vtkDelimitedTextReader> reader =
 vtkSmartPointer<vtkDelimitedTextReader>::New();
reader->SetFileName(inputFilename.c_str());
reader->SetFieldDelimiterCharacters(",");
reader->DetectNumericColumnsOn();
reader->Update();

///////KmeansCluster

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
 vtkSmartPointer<vtkKMeansStatistics>::New();
kMeansStatistics->SetInputConnection(reader->GetOutputPort());
kMeansStatistics->SetColumnStatus("Column 3", 1);
kMeansStatistics->SetColumnStatus("Column 4", 1);
kMeansStatistics->SetColumnStatus("Column 5", 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(2);
//kMeansStatistics->SetMaxNumIterations(15);
kMeansStatistics->Update();

// Display the results in CMD (each row)
kMeansStatistics->GetOutput()->Dump();

//Group the points according to ID number
vtkSmartPointer<vtkIntArray> clusterArray =
 vtkSmartPointer<vtkIntArray>::New();
clusterArray->SetNumberOfComponents(1);
clusterArray->SetName("ClusterId");

for (int r = 0; r < kMeansStatistics->GetOutput()->GetNumberOfRows(); r++)
{
 vtkVariant v = kMeansStatistics->GetOutput()->GetValue(r, kMeansStatistics->GetOutput()->GetNumberOfColumns() - 1);
 std::cout << "Point " << r << " is in cluster " << v.ToInt() << std::endl;
 clusterArray->InsertNextValue(v.ToInt());
}

// Create a lookup table to map cell data to colors
vtkSmartPointer<vtkLookupTable> lut =
 vtkSmartPointer<vtkLookupTable>::New();
int tableSize = (kMeansStatistics + 1, 10);
lut->SetNumberOfTableValues(tableSize);
lut->Build();

//ColorCells
vtkSmartPointer<vtkNamedColors> colors =
 vtkSmartPointer<vtkNamedColors>::New();
lut->SetTableValue(0, colors->GetColor4d("Black").GetData());
lut->SetTableValue(1, colors->GetColor4d("Banana").GetData());
lut->SetTableValue(2, colors->GetColor4d("Tomato").GetData());
lut->SetTableValue(3, colors->GetColor4d("Peacock").GetData());
lut->SetTableValue(4, colors->GetColor4d("Lavender").GetData());
lut->SetTableValue(5, colors->GetColor4d("Flesh").GetData());
lut->SetTableValue(6, colors->GetColor4d("Raspberry").GetData());
lut->SetTableValue(7, colors->GetColor4d("Salmon").GetData());
lut->SetTableValue(8, colors->GetColor4d("Mint").GetData());
lut->SetTableValue(9, colors->GetColor4d("Wheat").GetData());

// Output the cluster centers

vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast(kMeansStatistics->GetOutputDataObject(vtkStatisticsAlgorithm::OUTPUT_MODEL));
vtkSmartPointer<vtkTable> outputMeta = vtkTable::SafeDownCast(outputMetaDS->GetBlock(0));
//vtkSmartPointer<vtkTable> outputMeta = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 1 ) );
vtkDoubleArray* coord0 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Column 0"));
vtkDoubleArray* coord1 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Column 1"));
vtkDoubleArray* coord2 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Column 2"));

for (unsigned int i = 0; i < coord0->GetNumberOfTuples(); ++i)
{
 std::cout << coord0->GetValue(i) << " " << coord1->GetValue(i) << " " << coord2->GetValue(i) << std::endl;

}

vtkSmartPointer<vtkPolyData> polydata =
 vtkSmartPointer<vtkPolyData>::New();
polydata->GetPointData()->SetScalars(clusterArray);

vtkSmartPointer<vtkPolyDataMapper> mapper =
 vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(kMeansStatistics->GetOutputPort());

vtkSmartPointer<vtkActor> actor =
 vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetPointSize(3);
actor->GetProperty()->SetColor(1, 0, 0);

vtkSmartPointer<vtkRenderer> renderer =
 vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
 vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(640, 480);

vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
 vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);

renderer->AddActor(actor);
renderer->SetBackground(0, 0, 0); // Background color black

renderWindow->Render();
renderWindowInteractor->Start();

return EXIT_SUCCESS;
}


Thank you so much.

Regards,
Polly
________________________________
From: Cory Quammen <cory.quammen at kitware.com>
Sent: Tuesday, November 13, 2018 11:34 PM
To: Polly Pui
Cc: vtkusers
Subject: Re: [vtkusers] Extract csv row and column into points

Ah, so you want to use the vtkKMeansStatistics filter. That filter operates on vtkTable data. To use it, you don't need to create points at all. Instead, you can connect the  vtkDelimitedTextReader directly to the vtkKMeansStatistics filter like so:

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
 vtkSmartPointer<vtkKMeansStatistics>::New();
kMeansStatistics->SetInputConnection(reader->GetOutputPort());
kMeansStatistics->SetColumnStatus("column1", 1);
kMeansStatistics->SetColumnStatus("column2", 1);
kMeansStatistics->SetColumnStatus("column3, 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(1);
//kMeansStatistics->SetMaxNumIterations(15);
kMeansStatistics->Update();

Here, I've altered your calls to SetColumnStatus() under the assumption you know the column names of interest.

HTH,
Cory


On Fri, Nov 9, 2018 at 10:16 AM Polly Pui <polly_sukting at hotmail.com<mailto:polly_sukting at hotmail.com>> wrote:
Hi,
Thanks for your reply.
Is it possible to have more elaborations from you?

How can I get the number of points from vtkTableToPolyData?
I got an error saying that vtkTableToPolyData has no members of GetNumberOfPoints.
I need those points to proceed to KmeansStatistics.

This is my code:
......
std::string inputFilename = argv[1];

vtkSmartPointer<vtkDelimitedTextReader> reader =
 vtkSmartPointer<vtkDelimitedTextReader>::New();
reader->SetFileName(inputFilename.c_str());
reader->SetFieldDelimiterCharacters(" ");
reader->DetectNumericColumnsOn();
reader->Update();
int numberOfRows = reader->GetOutput()->GetNumberOfRows();

vtkSmartPointer<vtkTableToPolyData> inputData =
 vtkSmartPointer<vtkTableToPolyData>::New();
inputData->SetInputConnection(reader->GetOutputPort);

for (int c = 0; c < 3; ++c)
{
 std::stringstream colName;
 colName << "coord " << c;
 vtkSmartPointer<vtkDoubleArray> doubleArray =
  vtkSmartPointer<vtkDoubleArray>::New();
 doubleArray->SetNumberOfComponents(1);
 doubleArray->SetName(colName.str().c_str());
 doubleArray->SetNumberOfTuples(inputData->GetNumberOfPoints());


 for (int r = 0; r < inputData->GetNumberOfPoints(); ++r)
 {
  double p[3];
  inputData->GetPoint(r, p);
  doubleArray->SetValue(r, p[c]);
 }
 inputData->AddColumn(doubleArray);
}

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
 vtkSmartPointer<vtkKMeansStatistics>::New();

#if VTK_MAJOR_VERSION <= 5
kMeansStatistics->SetInput(vtkStatisticsAlgorithm::INPUT_DATA, inputData);
#else
kMeansStatistics->SetInputData(vtkStatisticsAlgorithm::INPUT_DATA, inputData);
#endif
kMeansStatistics->SetColumnStatus(inputData->GetColumnName(0), 1);
kMeansStatistics->SetColumnStatus(inputData->GetColumnName(1), 1);
kMeansStatistics->SetColumnStatus(inputData->GetColumnName(2), 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(1);
//kMeansStatistics->SetMaxNumIterations(15);
kMeansStatistics->Update();

Thanks again.

Regards,
Polly
________________________________
From: Cory Quammen <cory.quammen at kitware.com<mailto:cory.quammen at kitware.com>>
Sent: Friday, November 9, 2018 10:07 PM
To: Polly Pui
Cc: vtkusers
Subject: Re: [vtkusers] Extract csv row and column into points

vtkDelimitedTextReader -> vtkTableToPolyData is a pipeline that should make this much simpler.

On Fri, Nov 9, 2018 at 1:14 AM Polly Pui <polly_sukting at hotmail.com<mailto:polly_sukting at hotmail.com>> wrote:
Hi,
Is there any clue that i can extract the row and column data from a csv file and read them as points?
Currently I am using vtkpoints to read points by inserting points manually to my .cpp .
Is it possible for me to call the csv directly and read the data (eg. column 3-5, row 2-10)?

I attach my code here.
......
int main(int, char*[])
{

vtkSmartPointer<vtkPoints> points =
 vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(8.4312, -36.489, -1500.7);
points->InsertNextPoint(8.8408, -37.726, -1500.4);
points->InsertNextPoint(11.372, -37.787, -1501.5);
points->InsertNextPoint(11.263, -36.384, -1501.9);
points->InsertNextPoint(9.3914, -40.819, -1500.8);
points->InsertNextPoint(11.685, -42.482, -1502.7);
points->InsertNextPoint(14.235, -38.096, -1503.5);
points->InsertNextPoint(13.972, -43.051, -1504.2);
points->InsertNextPoint(9.22, -43.904, -1504);

vtkSmartPointer<vtkTable> inputData =
 vtkSmartPointer<vtkTable>::New();
for (int c = 0; c < 3; ++c)
{
 std::stringstream colName;
 colName << "coord " << c;
 vtkSmartPointer<vtkDoubleArray> doubleArray =
  vtkSmartPointer<vtkDoubleArray>::New();
 doubleArray->SetNumberOfComponents(1);
 doubleArray->SetName(colName.str().c_str());
 doubleArray->SetNumberOfTuples(points->GetNumberOfPoints());

 for (int r = 0; r < points->GetNumberOfPoints(); ++r)
 {
  double p[3];
  points->GetPoint(r, p);
  doubleArray->SetValue(r, p[c]);
 }
 inputData->AddColumn(doubleArray);
}

Thank you very much.

Regards,
Polly
_______________________________________________
Powered by www.kitware.com<http://www.kitware.com>

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ

Search the list archives at: http://markmail.org/search/?q=vtkusers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtkusers


--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.


--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://public.kitware.com/pipermail/vtkusers/attachments/20181115/04ccf14b/attachment.html>


More information about the vtkusers mailing list