std::unique_ptr<DataObject> MatricesToVtk::readRawFile(const QString & fileName)
{
    InputVector inputVectors;
    auto && result = TextFileReader(fileName).read(inputVectors);

    if (!result.testFlag(TextFileReader::successful))
    {
        return nullptr;
    }

    int numColumns = (int)inputVectors.size();
    if (numColumns == 0)
    {
        return nullptr;
    }
    int numRows = (int)inputVectors.at(0).size();
    if (numRows == 0)
    {
        return nullptr;
    }

    bool switchRowsColumns = numColumns > numRows;
    if (switchRowsColumns)
    {
        std::swap(numColumns, numRows);
    }

    auto dataArray = vtkSmartPointer<vtkFloatArray>::New();
    dataArray->SetNumberOfComponents(numColumns);
    dataArray->SetNumberOfTuples(numRows);

    if (!switchRowsColumns)
    {
        for (vtkIdType component = 0; component < numColumns; ++component)
        {
            for (vtkIdType cellId = 0; cellId < numRows; ++cellId)
            {
                dataArray->SetValue(cellId * numColumns + component,
                    static_cast<float>(inputVectors.at(component).at(cellId)));
            }
        }
    }
    else
    {
        for (vtkIdType component = 0; component < numColumns; ++component)
        {
            for (vtkIdType cellId = 0; cellId < numRows; ++cellId)
            {
                dataArray->SetValue(cellId * numColumns + component,
                    static_cast<float>(inputVectors.at(cellId).at(component)));
            }
        }
    }

    QFileInfo fInfo(fileName);

    return std::make_unique<RawVectorData>(fInfo.baseName(), *dataArray);
}
vtkSmartPointer<vtkPolyData> MatricesToVtk::parsePoints(
    const InputVector & inputData, size_t firstColumn,
    int vtk_dataType /*= VTK_FLOAT*/)
{
    assert(inputData.size() > firstColumn);

    auto points = vtkSmartPointer<vtkPoints>::New();
    points->SetDataType(vtk_dataType);

    size_t nbRows = inputData.at(firstColumn).size();
    std::vector<vtkIdType> pointIds(nbRows);

    // copy triangle vertexes to VTK point list
    for (size_t row = 0; row < nbRows; ++row)
    {
        pointIds.at(row) = points->InsertNextPoint(inputData[firstColumn][row], inputData[firstColumn + 1][row], inputData[firstColumn + 2][row]);
    }

    // Create the topology of the point (a vertex)
    auto vertices = vtkSmartPointer<vtkCellArray>::New();
    vertices->InsertNextCell(nbRows, pointIds.data());

    auto resultPolyData = vtkSmartPointer<vtkPolyData>::New();
    resultPolyData->SetPoints(points);
    resultPolyData->SetVerts(vertices);

    return resultPolyData;
}
vtkSmartPointer<vtkDataArray> MatricesToVtk::parseFloatVector(
    const InputVector & inputData, const QString & arrayName, size_t firstColumn, size_t lastColumn,
    int vtk_dataType /*= VTK_FLOAT*/)
{
    assert(firstColumn <= lastColumn);
    assert(inputData.size() > lastColumn);
    int numComponents = static_cast<int>(lastColumn - firstColumn + 1);
    vtkIdType numTuples = inputData.at(lastColumn).size();

    DEBUG_ONLY(for (auto && ax : inputData)
    {
        assert(ax.size() == size_t(numTuples));
    })