Discussion:
[vtkusers] Extract csv row and column into points
Polly Pui
2018-11-09 06:13:58 UTC
Permalink
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
Cory Quammen
2018-11-09 14:07:52 UTC
Permalink
vtkDelimitedTextReader -> vtkTableToPolyData is a pipeline that should make
this much simpler.

On Fri, Nov 9, 2018 at 1:14 AM Polly Pui <***@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
>
> 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.
Polly Pui
2018-11-09 15:16:25 UTC
Permalink
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 <***@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 <***@hotmail.com<mailto:***@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
2018-11-13 15:34:21 UTC
Permalink
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 <***@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 <***@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 <***@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
>
> 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.
Polly Pui
2018-11-15 06:25:59 UTC
Permalink
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 <***@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 <***@hotmail.com<mailto:***@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 <***@kitware.com<mailto:***@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 <***@hotmail.com<mailto:***@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.
Cory Quammen
2018-11-19 14:52:58 UTC
Permalink
On Thu, Nov 15, 2018 at 1:26 AM Polly Pui <***@hotmail.com> wrote:

> 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?
>

No, vtkKMeansStatistics requires a vtkTable input (it is a subclass of
vtkTableAlgorithm). vtkTable is different from a vtkPolyData, which is what
you are trying to create. See more inline comments further down.


> 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);
>
>
The below won't work. vtkKMeansStatistics produces a vtkTable, while the
vtkPolyDataMapper requires a vtkPolyData. To convert a vtkTable to a
vtkPolyData, which is the key piece you are missing, use
vtkTableToPolyData. This class iterates over the rows, treats the columns
you designate as X, Y, Z coordinates, and adds the remaining columns as
point data arrays in the output vtkPolyData.

It will look something like this:

vtkSmartPointer<vtkTableToPolyData> t2pd =
vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("name of column to be used as x-coordinate");
t2pd->SetYColumn("name of column to be used as y-coordinate");
t2pd->SetZColumn("name of column to be used as z-coordinate");

Now, change, the code below from:


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

to

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

That should do it.

Cory


> 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 <***@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 <***@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 <***@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 <***@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
>
> 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.
>


--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.
Polly Pui
2018-11-21 06:01:36 UTC
Permalink
Hi Cory,
Thanks for your reply.
I followed your advice and changed the lines as you mentioned.
But I still couldn't get the output successfully.

I would like to clarify if I called the column of interest correctly.
Please refer to the attachment. The columns that to be called as X,Y,Z coordinates are named as "X", "Y", "Z".
When i run the exe file. It failed to load and couldn't get the correct cluster.

This is the codes that I am using.
..............
int main(int argc, char* argv[])
{
std::string inputFilename = argv[1];

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

///////KmeansCluster

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
vtkSmartPointer<vtkKMeansStatistics>::New();
kMeansStatistics->SetInputConnection(reader->GetOutputPort());
kMeansStatistics->SetColumnStatus("X", 1);
kMeansStatistics->SetColumnStatus("Y", 1);
kMeansStatistics->SetColumnStatus("Z", 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(5);
//kMeansStatistics->SetLearnOption(1);//to learn the cluster value
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));
vtkTable* outputMeta = vtkTable::SafeDownCast(outputMetaDS->GetBlock(0));

vtkDoubleArray* coord0 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("X"));
vtkDoubleArray* coord1 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Y"));
vtkDoubleArray* coord2 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Z"));

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

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("X");
t2pd->SetYColumn("Y");
t2pd->SetZColumn("Z");

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

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

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;
}
.........
Please advice. Thank you again!

Regards,
Polly

________________________________
From: Cory Quammen <***@kitware.com>
Sent: Monday, November 19, 2018 10:52 PM
To: Polly Pui
Cc: vtkusers
Subject: Re: [vtkusers] Extract csv row and column into points



On Thu, Nov 15, 2018 at 1:26 AM Polly Pui <***@hotmail.com<mailto:***@hotmail.com>> wrote:
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?

No, vtkKMeansStatistics requires a vtkTable input (it is a subclass of vtkTableAlgorithm). vtkTable is different from a vtkPolyData, which is what you are trying to create. See more inline comments further down.

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);


The below won't work. vtkKMeansStatistics produces a vtkTable, while the vtkPolyDataMapper requires a vtkPolyData. To convert a vtkTable to a vtkPolyData, which is the key piece you are missing, use vtkTableToPolyData. This class iterates over the rows, treats the columns you designate as X, Y, Z coordinates, and adds the remaining columns as point data arrays in the output vtkPolyData.

It will look something like this:

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("name of column to be used as x-coordinate");
t2pd->SetYColumn("name of column to be used as y-coordinate");
t2pd->SetZColumn("name of column to be used as z-coordinate");

Now, change, the code below from:

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

to

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

That should do it.

Cory

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 <***@kitware.com<mailto:***@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 <***@hotmail.com<mailto:***@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 <***@kitware.com<mailto:***@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 <***@hotmail.com<mailto:***@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.


--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.
Polly Pui
2018-11-21 06:16:46 UTC
Permalink
And also I tried to remove the lines in order to test if the columns are called successfully. I received the error stated "Failed to locate the columns to use for the point coordinates".

These are the codes:
std::string inputFilename = argv[1];

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

reader->GetOutput()->Dump();
///////KmeansCluster

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
vtkSmartPointer<vtkKMeansStatistics>::New();
kMeansStatistics->SetInputConnection(reader->GetOutputPort());
kMeansStatistics->SetColumnStatus("X", 1);
kMeansStatistics->SetColumnStatus("Y", 1);
kMeansStatistics->SetColumnStatus("Z", 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(5);
//kMeansStatistics->SetLearnOption(1);//to learn the cluster value
kMeansStatistics->SetMaxNumIterations(15);
kMeansStatistics->Update();

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("X");
t2pd->SetYColumn("Y");
t2pd->SetZColumn("Z");

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

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

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;
}

I supposed the column of interest to be called are "X", "Y" and "Z".
Please advice.
Thank you very much.

Regards,
Polly
________________________________
From: vtkusers <vtkusers-***@public.kitware.com> on behalf of Polly Pui <***@hotmail.com>
Sent: Wednesday, November 21, 2018 2:01 PM
To: Cory Quammen
Cc: vtkusers
Subject: Re: [vtkusers] Extract csv row and column into points

Hi Cory,
Thanks for your reply.
I followed your advice and changed the lines as you mentioned.
But I still couldn't get the output successfully.

I would like to clarify if I called the column of interest correctly.
Please refer to the attachment. The columns that to be called as X,Y,Z coordinates are named as "X", "Y", "Z".
When i run the exe file. It failed to load and couldn't get the correct cluster.

This is the codes that I am using.
..............
int main(int argc, char* argv[])
{
std::string inputFilename = argv[1];

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

///////KmeansCluster

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
vtkSmartPointer<vtkKMeansStatistics>::New();
kMeansStatistics->SetInputConnection(reader->GetOutputPort());
kMeansStatistics->SetColumnStatus("X", 1);
kMeansStatistics->SetColumnStatus("Y", 1);
kMeansStatistics->SetColumnStatus("Z", 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(5);
//kMeansStatistics->SetLearnOption(1);//to learn the cluster value
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));
vtkTable* outputMeta = vtkTable::SafeDownCast(outputMetaDS->GetBlock(0));

vtkDoubleArray* coord0 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("X"));
vtkDoubleArray* coord1 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Y"));
vtkDoubleArray* coord2 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Z"));

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

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("X");
t2pd->SetYColumn("Y");
t2pd->SetZColumn("Z");

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

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

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;
}
.........
Please advice. Thank you again!

Regards,
Polly

________________________________
From: Cory Quammen <***@kitware.com>
Sent: Monday, November 19, 2018 10:52 PM
To: Polly Pui
Cc: vtkusers
Subject: Re: [vtkusers] Extract csv row and column into points



On Thu, Nov 15, 2018 at 1:26 AM Polly Pui <***@hotmail.com<mailto:***@hotmail.com>> wrote:
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?

No, vtkKMeansStatistics requires a vtkTable input (it is a subclass of vtkTableAlgorithm). vtkTable is different from a vtkPolyData, which is what you are trying to create. See more inline comments further down.

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);


The below won't work. vtkKMeansStatistics produces a vtkTable, while the vtkPolyDataMapper requires a vtkPolyData. To convert a vtkTable to a vtkPolyData, which is the key piece you are missing, use vtkTableToPolyData. This class iterates over the rows, treats the columns you designate as X, Y, Z coordinates, and adds the remaining columns as point data arrays in the output vtkPolyData.

It will look something like this:

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("name of column to be used as x-coordinate");
t2pd->SetYColumn("name of column to be used as y-coordinate");
t2pd->SetZColumn("name of column to be used as z-coordinate");

Now, change, the code below from:

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

to

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

That should do it.

Cory

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 <***@kitware.com<mailto:***@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 <***@hotmail.com<mailto:***@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 <***@kitware.com<mailto:***@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 <***@hotmail.com<mailto:***@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.


--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.
Cory Quammen
2018-11-27 16:53:11 UTC
Permalink
Polly,

It seems I was mistaken about the output of the vtkKMeansStatistics filter.
It looks like it does not pass through the input columns with something
like a cluster label. I have no experience with the filter, so I'm not sure
how to guide you from here. David Thompson (CC'ed) would know more since he
was an author of the filter. He may be able to help if he has time.

Some resources that may help:

Doxygen page:
https://www.vtk.org/doc/nightly/html/classvtkKMeansStatistics.html#details

Example:
https://www.vtk.org/gitweb?p=VTK.git;a=blob;f=Examples/Statistics/ExampleKMeansStatistics.cxx

Cory

On Wed, Nov 21, 2018 at 1:16 AM Polly Pui <***@hotmail.com> wrote:

> And also I tried to remove the lines in order to test if the columns are
> called successfully. I received the error stated "Failed to locate the
> columns to use for the point coordinates".
>
> These are the codes:
> std::string inputFilename = argv[1];
>
> vtkSmartPointer<vtkDelimitedTextReader> reader =
> vtkSmartPointer<vtkDelimitedTextReader>::New();
> reader->SetFileName(inputFilename.c_str());
> reader->SetFieldDelimiterCharacters(",");
> reader->DetectNumericColumnsOn();
> //reader->GetHaveHeaders();
> reader->Update();
>
> reader->GetOutput()->Dump();
> ///////KmeansCluster
>
> vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
> vtkSmartPointer<vtkKMeansStatistics>::New();
> kMeansStatistics->SetInputConnection(reader->GetOutputPort());
> kMeansStatistics->SetColumnStatus("X", 1);
> kMeansStatistics->SetColumnStatus("Y", 1);
> kMeansStatistics->SetColumnStatus("Z", 1);
> kMeansStatistics->RequestSelectedColumns();
> kMeansStatistics->SetAssessOption(true);
> kMeansStatistics->SetDefaultNumberOfClusters(5);
> //kMeansStatistics->SetLearnOption(1);//to learn the cluster value
> kMeansStatistics->SetMaxNumIterations(15);
> kMeansStatistics->Update();
>
> vtkSmartPointer<vtkTableToPolyData> t2pd =
> vtkSmartPointer<vtkTableToPolyData>::New();
> t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
> t2pd->SetXColumn("X");
> t2pd->SetYColumn("Y");
> t2pd->SetZColumn("Z");
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(t2pd->GetOutputPort());
>
> vtkSmartPointer<vtkActor> actor =
> vtkSmartPointer<vtkActor>::New();
> actor->SetMapper(mapper);
> actor->GetProperty()->SetPointSize(3);
> actor->GetProperty()->SetColor(1, 1, 1);
>
> 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;
> }
>
> I supposed the column of interest to be called are "X", "Y" and "Z".
> Please advice.
> Thank you very much.
>
> Regards,
> Polly
> ------------------------------
> *From:* vtkusers <vtkusers-***@public.kitware.com> on behalf of Polly
> Pui <***@hotmail.com>
> *Sent:* Wednesday, November 21, 2018 2:01 PM
> *To:* Cory Quammen
> *Cc:* vtkusers
> *Subject:* Re: [vtkusers] Extract csv row and column into points
>
> Hi Cory,
> Thanks for your reply.
> I followed your advice and changed the lines as you mentioned.
> But I still couldn't get the output successfully.
>
> I would like to clarify if I called the column of interest correctly.
> Please refer to the attachment. The columns that to be called as X,Y,Z
> coordinates are named as "X", "Y", "Z".
> When i run the exe file. It failed to load and couldn't get the correct
> cluster.
>
> This is the codes that I am using.
> ..............
> int main(int argc, char* argv[])
> {
> std::string inputFilename = argv[1];
>
> vtkSmartPointer<vtkDelimitedTextReader> reader =
> vtkSmartPointer<vtkDelimitedTextReader>::New();
> reader->SetFileName(inputFilename.c_str());
> reader->SetFieldDelimiterCharacters(",");
> reader->DetectNumericColumnsOn();
> //reader->GetHaveHeaders();
> reader->Update();
>
> ///////KmeansCluster
>
> vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
> vtkSmartPointer<vtkKMeansStatistics>::New();
> kMeansStatistics->SetInputConnection(reader->GetOutputPort());
> kMeansStatistics->SetColumnStatus("X", 1);
> kMeansStatistics->SetColumnStatus("Y", 1);
> kMeansStatistics->SetColumnStatus("Z", 1);
> kMeansStatistics->RequestSelectedColumns();
> kMeansStatistics->SetAssessOption(true);
> kMeansStatistics->SetDefaultNumberOfClusters(5);
> //kMeansStatistics->SetLearnOption(1);//to learn the cluster value
> 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));
> vtkTable* outputMeta = vtkTable::SafeDownCast(outputMetaDS->GetBlock(0));
>
> vtkDoubleArray* coord0 =
> vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("X"));
> vtkDoubleArray* coord1 =
> vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Y"));
> vtkDoubleArray* coord2 =
> vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Z"));
>
> for (unsigned int i = 0; i < coord0->GetNumberOfTuples(); ++i)
> {
> std::cout << coord0->GetValue(i) << " " << coord1->GetValue(i) << " " <<
> coord2->GetValue(i) << std::endl;
> }
>
> vtkSmartPointer<vtkTableToPolyData> t2pd =
> vtkSmartPointer<vtkTableToPolyData>::New();
> t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
> t2pd->SetXColumn("X");
> t2pd->SetYColumn("Y");
> t2pd->SetZColumn("Z");
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(t2pd->GetOutputPort());
>
> vtkSmartPointer<vtkActor> actor =
> vtkSmartPointer<vtkActor>::New();
> actor->SetMapper(mapper);
> actor->GetProperty()->SetPointSize(3);
> actor->GetProperty()->SetColor(1, 1, 1);
>
> 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;
> }
> .........
> Please advice. Thank you again!
>
> Regards,
> Polly
>
> ------------------------------
> *From:* Cory Quammen <***@kitware.com>
> *Sent:* Monday, November 19, 2018 10:52 PM
> *To:* Polly Pui
> *Cc:* vtkusers
> *Subject:* Re: [vtkusers] Extract csv row and column into points
>
>
>
> On Thu, Nov 15, 2018 at 1:26 AM Polly Pui <***@hotmail.com>
> wrote:
>
> 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?
>
>
> No, vtkKMeansStatistics requires a vtkTable input (it is a subclass of
> vtkTableAlgorithm). vtkTable is different from a vtkPolyData, which is what
> you are trying to create. See more inline comments further down.
>
>
> 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);
>
>
> The below won't work. vtkKMeansStatistics produces a vtkTable, while the
> vtkPolyDataMapper requires a vtkPolyData. To convert a vtkTable to a
> vtkPolyData, which is the key piece you are missing, use
> vtkTableToPolyData. This class iterates over the rows, treats the columns
> you designate as X, Y, Z coordinates, and adds the remaining columns as
> point data arrays in the output vtkPolyData.
>
> It will look something like this:
>
> vtkSmartPointer<vtkTableToPolyData> t2pd =
> vtkSmartPointer<vtkTableToPolyData>::New();
> t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
> t2pd->SetXColumn("name of column to be used as x-coordinate");
> t2pd->SetYColumn("name of column to be used as y-coordinate");
> t2pd->SetZColumn("name of column to be used as z-coordinate");
>
> Now, change, the code below from:
>
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(kMeansStatistics->GetOutputPort());
>
>
> to
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(t2pd->GetOutputPort());
>
> That should do it.
>
> Cory
>
>
> 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 <***@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 <***@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 <***@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 <***@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
>
> 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.
>
>
>
> --
> Cory Quammen
> Staff R&D Engineer
> Kitware, Inc.
>


--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.
Polly Pui
2018-12-03 14:11:24 UTC
Permalink
Thanks Cory, you are so helpful. I am trying to figure out how to skip the header of the csv file before calling for Kmeansclustering.
I am getting there. If you have any idea on how to skip reading the header, please advice:)

Thank you so much.

Regards,
Polly
________________________________
From: Cory Quammen <***@kitware.com>
Sent: Wednesday, November 28, 2018 12:53 AM
To: Polly Pui
Cc: vtkusers; David Thompson
Subject: Re: [vtkusers] Extract csv row and column into points

Polly,

It seems I was mistaken about the output of the vtkKMeansStatistics filter. It looks like it does not pass through the input columns with something like a cluster label. I have no experience with the filter, so I'm not sure how to guide you from here. David Thompson (CC'ed) would know more since he was an author of the filter. He may be able to help if he has time.

Some resources that may help:

Doxygen page:
https://www.vtk.org/doc/nightly/html/classvtkKMeansStatistics.html#details

Example:
https://www.vtk.org/gitweb?p=VTK.git;a=blob;f=Examples/Statistics/ExampleKMeansStatistics.cxx

Cory

On Wed, Nov 21, 2018 at 1:16 AM Polly Pui <***@hotmail.com<mailto:***@hotmail.com>> wrote:
And also I tried to remove the lines in order to test if the columns are called successfully. I received the error stated "Failed to locate the columns to use for the point coordinates".

These are the codes:
std::string inputFilename = argv[1];

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

reader->GetOutput()->Dump();
///////KmeansCluster

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
vtkSmartPointer<vtkKMeansStatistics>::New();
kMeansStatistics->SetInputConnection(reader->GetOutputPort());
kMeansStatistics->SetColumnStatus("X", 1);
kMeansStatistics->SetColumnStatus("Y", 1);
kMeansStatistics->SetColumnStatus("Z", 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(5);
//kMeansStatistics->SetLearnOption(1);//to learn the cluster value
kMeansStatistics->SetMaxNumIterations(15);
kMeansStatistics->Update();

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("X");
t2pd->SetYColumn("Y");
t2pd->SetZColumn("Z");

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

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

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;
}

I supposed the column of interest to be called are "X", "Y" and "Z".
Please advice.
Thank you very much.

Regards,
Polly
________________________________
From: vtkusers <vtkusers-***@public.kitware.com<mailto:vtkusers-***@public.kitware.com>> on behalf of Polly Pui <***@hotmail.com<mailto:***@hotmail.com>>
Sent: Wednesday, November 21, 2018 2:01 PM
To: Cory Quammen
Cc: vtkusers
Subject: Re: [vtkusers] Extract csv row and column into points

Hi Cory,
Thanks for your reply.
I followed your advice and changed the lines as you mentioned.
But I still couldn't get the output successfully.

I would like to clarify if I called the column of interest correctly.
Please refer to the attachment. The columns that to be called as X,Y,Z coordinates are named as "X", "Y", "Z".
When i run the exe file. It failed to load and couldn't get the correct cluster.

This is the codes that I am using.
..............
int main(int argc, char* argv[])
{
std::string inputFilename = argv[1];

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

///////KmeansCluster

vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
vtkSmartPointer<vtkKMeansStatistics>::New();
kMeansStatistics->SetInputConnection(reader->GetOutputPort());
kMeansStatistics->SetColumnStatus("X", 1);
kMeansStatistics->SetColumnStatus("Y", 1);
kMeansStatistics->SetColumnStatus("Z", 1);
kMeansStatistics->RequestSelectedColumns();
kMeansStatistics->SetAssessOption(true);
kMeansStatistics->SetDefaultNumberOfClusters(5);
//kMeansStatistics->SetLearnOption(1);//to learn the cluster value
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));
vtkTable* outputMeta = vtkTable::SafeDownCast(outputMetaDS->GetBlock(0));

vtkDoubleArray* coord0 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("X"));
vtkDoubleArray* coord1 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Y"));
vtkDoubleArray* coord2 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Z"));

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

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("X");
t2pd->SetYColumn("Y");
t2pd->SetZColumn("Z");

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

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

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;
}
.........
Please advice. Thank you again!

Regards,
Polly

________________________________
From: Cory Quammen <***@kitware.com<mailto:***@kitware.com>>
Sent: Monday, November 19, 2018 10:52 PM
To: Polly Pui
Cc: vtkusers
Subject: Re: [vtkusers] Extract csv row and column into points



On Thu, Nov 15, 2018 at 1:26 AM Polly Pui <***@hotmail.com<mailto:***@hotmail.com>> wrote:
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?

No, vtkKMeansStatistics requires a vtkTable input (it is a subclass of vtkTableAlgorithm). vtkTable is different from a vtkPolyData, which is what you are trying to create. See more inline comments further down.

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);


The below won't work. vtkKMeansStatistics produces a vtkTable, while the vtkPolyDataMapper requires a vtkPolyData. To convert a vtkTable to a vtkPolyData, which is the key piece you are missing, use vtkTableToPolyData. This class iterates over the rows, treats the columns you designate as X, Y, Z coordinates, and adds the remaining columns as point data arrays in the output vtkPolyData.

It will look something like this:

vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
t2pd->SetXColumn("name of column to be used as x-coordinate");
t2pd->SetYColumn("name of column to be used as y-coordinate");
t2pd->SetZColumn("name of column to be used as z-coordinate");

Now, change, the code below from:

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

to

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

That should do it.

Cory

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 <***@kitware.com<mailto:***@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 <***@hotmail.com<mailto:***@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 <***@kitware.com<mailto:***@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 <***@hotmail.com<mailto:***@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.


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


--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.
Cory Quammen via vtkusers
2018-12-03 14:18:01 UTC
Permalink
Polly,

To skip headers when reading the CSV file, call

vtkDelimitedTextReader::SetHaveHeaders(true);

The default behavior is to assume there is no header line.

HTH,
Cory
On Mon, Dec 3, 2018 at 9:11 AM Polly Pui <***@hotmail.com> wrote:
>
> Thanks Cory, you are so helpful. I am trying to figure out how to skip the header of the csv file before calling for Kmeansclustering.
> I am getting there. If you have any idea on how to skip reading the header, please advice:)
>
> Thank you so much.
>
> Regards,
> Polly
> ________________________________
> From: Cory Quammen <***@kitware.com>
> Sent: Wednesday, November 28, 2018 12:53 AM
> To: Polly Pui
> Cc: vtkusers; David Thompson
> Subject: Re: [vtkusers] Extract csv row and column into points
>
> Polly,
>
> It seems I was mistaken about the output of the vtkKMeansStatistics filter. It looks like it does not pass through the input columns with something like a cluster label. I have no experience with the filter, so I'm not sure how to guide you from here. David Thompson (CC'ed) would know more since he was an author of the filter. He may be able to help if he has time.
>
> Some resources that may help:
>
> Doxygen page:
> https://www.vtk.org/doc/nightly/html/classvtkKMeansStatistics.html#details
>
> Example:
> https://www.vtk.org/gitweb?p=VTK.git;a=blob;f=Examples/Statistics/ExampleKMeansStatistics.cxx
>
> Cory
>
> On Wed, Nov 21, 2018 at 1:16 AM Polly Pui <***@hotmail.com> wrote:
>
> And also I tried to remove the lines in order to test if the columns are called successfully. I received the error stated "Failed to locate the columns to use for the point coordinates".
>
> These are the codes:
> std::string inputFilename = argv[1];
>
> vtkSmartPointer<vtkDelimitedTextReader> reader =
> vtkSmartPointer<vtkDelimitedTextReader>::New();
> reader->SetFileName(inputFilename.c_str());
> reader->SetFieldDelimiterCharacters(",");
> reader->DetectNumericColumnsOn();
> //reader->GetHaveHeaders();
> reader->Update();
>
> reader->GetOutput()->Dump();
> ///////KmeansCluster
>
> vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
> vtkSmartPointer<vtkKMeansStatistics>::New();
> kMeansStatistics->SetInputConnection(reader->GetOutputPort());
> kMeansStatistics->SetColumnStatus("X", 1);
> kMeansStatistics->SetColumnStatus("Y", 1);
> kMeansStatistics->SetColumnStatus("Z", 1);
> kMeansStatistics->RequestSelectedColumns();
> kMeansStatistics->SetAssessOption(true);
> kMeansStatistics->SetDefaultNumberOfClusters(5);
> //kMeansStatistics->SetLearnOption(1);//to learn the cluster value
> kMeansStatistics->SetMaxNumIterations(15);
> kMeansStatistics->Update();
>
> vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
> t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
> t2pd->SetXColumn("X");
> t2pd->SetYColumn("Y");
> t2pd->SetZColumn("Z");
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(t2pd->GetOutputPort());
>
> vtkSmartPointer<vtkActor> actor =
> vtkSmartPointer<vtkActor>::New();
> actor->SetMapper(mapper);
> actor->GetProperty()->SetPointSize(3);
> actor->GetProperty()->SetColor(1, 1, 1);
>
> 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;
> }
>
> I supposed the column of interest to be called are "X", "Y" and "Z".
> Please advice.
> Thank you very much.
>
> Regards,
> Polly
> ________________________________
> From: vtkusers <vtkusers-***@public.kitware.com> on behalf of Polly Pui <***@hotmail.com>
> Sent: Wednesday, November 21, 2018 2:01 PM
> To: Cory Quammen
> Cc: vtkusers
> Subject: Re: [vtkusers] Extract csv row and column into points
>
> Hi Cory,
> Thanks for your reply.
> I followed your advice and changed the lines as you mentioned.
> But I still couldn't get the output successfully.
>
> I would like to clarify if I called the column of interest correctly.
> Please refer to the attachment. The columns that to be called as X,Y,Z coordinates are named as "X", "Y", "Z".
> When i run the exe file. It failed to load and couldn't get the correct cluster.
>
> This is the codes that I am using.
> ..............
> int main(int argc, char* argv[])
> {
> std::string inputFilename = argv[1];
>
> vtkSmartPointer<vtkDelimitedTextReader> reader =
> vtkSmartPointer<vtkDelimitedTextReader>::New();
> reader->SetFileName(inputFilename.c_str());
> reader->SetFieldDelimiterCharacters(",");
> reader->DetectNumericColumnsOn();
> //reader->GetHaveHeaders();
> reader->Update();
>
> ///////KmeansCluster
>
> vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
> vtkSmartPointer<vtkKMeansStatistics>::New();
> kMeansStatistics->SetInputConnection(reader->GetOutputPort());
> kMeansStatistics->SetColumnStatus("X", 1);
> kMeansStatistics->SetColumnStatus("Y", 1);
> kMeansStatistics->SetColumnStatus("Z", 1);
> kMeansStatistics->RequestSelectedColumns();
> kMeansStatistics->SetAssessOption(true);
> kMeansStatistics->SetDefaultNumberOfClusters(5);
> //kMeansStatistics->SetLearnOption(1);//to learn the cluster value
> 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));
> vtkTable* outputMeta = vtkTable::SafeDownCast(outputMetaDS->GetBlock(0));
>
> vtkDoubleArray* coord0 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("X"));
> vtkDoubleArray* coord1 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Y"));
> vtkDoubleArray* coord2 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("Z"));
>
> for (unsigned int i = 0; i < coord0->GetNumberOfTuples(); ++i)
> {
> std::cout << coord0->GetValue(i) << " " << coord1->GetValue(i) << " " << coord2->GetValue(i) << std::endl;
> }
>
> vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
> t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
> t2pd->SetXColumn("X");
> t2pd->SetYColumn("Y");
> t2pd->SetZColumn("Z");
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(t2pd->GetOutputPort());
>
> vtkSmartPointer<vtkActor> actor =
> vtkSmartPointer<vtkActor>::New();
> actor->SetMapper(mapper);
> actor->GetProperty()->SetPointSize(3);
> actor->GetProperty()->SetColor(1, 1, 1);
>
> 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;
> }
> .........
> Please advice. Thank you again!
>
> Regards,
> Polly
>
> ________________________________
> From: Cory Quammen <***@kitware.com>
> Sent: Monday, November 19, 2018 10:52 PM
> To: Polly Pui
> Cc: vtkusers
> Subject: Re: [vtkusers] Extract csv row and column into points
>
>
>
> On Thu, Nov 15, 2018 at 1:26 AM Polly Pui <***@hotmail.com> wrote:
>
> 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?
>
>
> No, vtkKMeansStatistics requires a vtkTable input (it is a subclass of vtkTableAlgorithm). vtkTable is different from a vtkPolyData, which is what you are trying to create. See more inline comments further down.
>
>
> 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);
>
>
> The below won't work. vtkKMeansStatistics produces a vtkTable, while the vtkPolyDataMapper requires a vtkPolyData. To convert a vtkTable to a vtkPolyData, which is the key piece you are missing, use vtkTableToPolyData. This class iterates over the rows, treats the columns you designate as X, Y, Z coordinates, and adds the remaining columns as point data arrays in the output vtkPolyData.
>
> It will look something like this:
>
> vtkSmartPointer<vtkTableToPolyData> t2pd = vtkSmartPointer<vtkTableToPolyData>::New();
> t2pd->SetInputConnection(kMeansStatistics->GetOutputPort());
> t2pd->SetXColumn("name of column to be used as x-coordinate");
> t2pd->SetYColumn("name of column to be used as y-coordinate");
> t2pd->SetZColumn("name of column to be used as z-coordinate");
>
> Now, change, the code below from:
>
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(kMeansStatistics->GetOutputPort());
>
>
> to
>
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> mapper->SetInputConnection(t2pd->GetOutputPort());
>
> That should do it.
>
> Cory
>
>
> 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 <***@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 <***@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 <***@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 <***@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
>
> 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.
>
>
>
> --
> Cory Quammen
> Staff R&D Engineer
> Kitware, Inc.
>
>
>
> --
> Cory Quammen
> Staff R&D Engineer
> Kitware, Inc.



--
Cory Quammen
Staff R&D Engineer
Kitware, Inc.
_______________________________________________
Powered by 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
Continue reading on narkive:
Loading...