[vtkusers] Extract csv row and column into points

Cory Quammen cory.quammen at kitware.com
Mon Nov 19 09:52:58 EST 2018


On Thu, Nov 15, 2018 at 1:26 AM Polly Pui <polly_sukting at 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 <cory.quammen at kitware.com>
> *Sent:* Tuesday, November 13, 2018 11:34 PM
> *To:* Polly Pui
> *Cc:* vtkusers
> *Subject:* Re: [vtkusers] Extract csv row and column into points
>
> Ah, so you want to use the vtkKMeansStatistics filter. That filter
> operates on vtkTable data. To use it, you don't need to create points at
> all. Instead, you can connect the  vtkDelimitedTextReader directly to the vtkKMeansStatistics
> filter like so:
>
> vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
>  vtkSmartPointer<vtkKMeansStatistics>::New();
> kMeansStatistics->SetInputConnection(reader->GetOutputPort());
> kMeansStatistics->SetColumnStatus("column1", 1);
> kMeansStatistics->SetColumnStatus("column2", 1);
> kMeansStatistics->SetColumnStatus("column3, 1);
> kMeansStatistics->RequestSelectedColumns();
> kMeansStatistics->SetAssessOption(true);
> kMeansStatistics->SetDefaultNumberOfClusters(1);
> //kMeansStatistics->SetMaxNumIterations(15);
> kMeansStatistics->Update();
>
> Here, I've altered your calls to SetColumnStatus() under the assumption
> you know the column names of interest.
>
> HTH,
> Cory
>
>
> On Fri, Nov 9, 2018 at 10:16 AM Polly Pui <polly_sukting at hotmail.com>
> wrote:
>
> Hi,
> Thanks for your reply.
> Is it possible to have more elaborations from you?
>
> How can I get the number of points from vtkTableToPolyData?
> I got an error saying that vtkTableToPolyData has no members of
> GetNumberOfPoints.
> I need those points to proceed to KmeansStatistics.
>
> This is my code:
> ......
> std::string inputFilename = argv[1];
>
> vtkSmartPointer<vtkDelimitedTextReader> reader =
>  vtkSmartPointer<vtkDelimitedTextReader>::New();
> reader->SetFileName(inputFilename.c_str());
> reader->SetFieldDelimiterCharacters(" ");
> reader->DetectNumericColumnsOn();
> reader->Update();
> int numberOfRows = reader->GetOutput()->GetNumberOfRows();
>
> vtkSmartPointer<vtkTableToPolyData> inputData =
>  vtkSmartPointer<vtkTableToPolyData>::New();
> inputData->SetInputConnection(reader->GetOutputPort);
>
> for (int c = 0; c < 3; ++c)
> {
>  std::stringstream colName;
>  colName << "coord " << c;
>  vtkSmartPointer<vtkDoubleArray> doubleArray =
>   vtkSmartPointer<vtkDoubleArray>::New();
>  doubleArray->SetNumberOfComponents(1);
>  doubleArray->SetName(colName.str().c_str());
>  doubleArray->SetNumberOfTuples(inputData->GetNumberOfPoints());
>
>
>  for (int r = 0; r < inputData->GetNumberOfPoints(); ++r)
>  {
>   double p[3];
>   inputData->GetPoint(r, p);
>   doubleArray->SetValue(r, p[c]);
>  }
>  inputData->AddColumn(doubleArray);
> }
>
> vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =
>  vtkSmartPointer<vtkKMeansStatistics>::New();
>
> #if VTK_MAJOR_VERSION <= 5
> kMeansStatistics->SetInput(vtkStatisticsAlgorithm::INPUT_DATA, inputData);
> #else
> kMeansStatistics->SetInputData(vtkStatisticsAlgorithm::INPUT_DATA,
> inputData);
> #endif
> kMeansStatistics->SetColumnStatus(inputData->GetColumnName(0), 1);
> kMeansStatistics->SetColumnStatus(inputData->GetColumnName(1), 1);
> kMeansStatistics->SetColumnStatus(inputData->GetColumnName(2), 1);
> kMeansStatistics->RequestSelectedColumns();
> kMeansStatistics->SetAssessOption(true);
> kMeansStatistics->SetDefaultNumberOfClusters(1);
> //kMeansStatistics->SetMaxNumIterations(15);
> kMeansStatistics->Update();
>
> Thanks again.
>
> Regards,
> Polly
> ------------------------------
> *From:* Cory Quammen <cory.quammen at kitware.com>
> *Sent:* Friday, November 9, 2018 10:07 PM
> *To:* Polly Pui
> *Cc:* vtkusers
> *Subject:* Re: [vtkusers] Extract csv row and column into points
>
> vtkDelimitedTextReader -> vtkTableToPolyData is a pipeline that should
> make this much simpler.
>
> On Fri, Nov 9, 2018 at 1:14 AM Polly Pui <polly_sukting at hotmail.com>
> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://public.kitware.com/pipermail/vtkusers/attachments/20181119/7147ca38/attachment.html>


More information about the vtkusers mailing list