From 55147e5b70c3ad6bf9fa526ea4969d8851580916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Jensen?= Date: Tue, 9 Jan 2018 11:33:02 +0100 Subject: [PATCH] #2350. Implement ElementPropertyTable file reader for single file --- .../FileInterface/CMakeLists_files.cmake | 2 + .../RifElementPropertyTableReader.cpp | 196 ++++++++++++++++++ .../RifElementPropertyTableReader.h | 79 +++++++ 3 files changed, 277 insertions(+) create mode 100644 ApplicationCode/FileInterface/RifElementPropertyTableReader.cpp create mode 100644 ApplicationCode/FileInterface/RifElementPropertyTableReader.h diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index e437ee7c5b..96f3ba89cd 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -40,6 +40,7 @@ ${CEE_CURRENT_LIST_DIR}RifCsvUserData.h ${CEE_CURRENT_LIST_DIR}RifCsvUserDataParser.h ${CEE_CURRENT_LIST_DIR}RifWellPathFormationReader.h ${CEE_CURRENT_LIST_DIR}RifWellPathFormationsImporter.h +${CEE_CURRENT_LIST_DIR}RifElementPropertyTableReader.h # HDF5 file reader is directly included in ResInsight main CmakeList.txt #${CEE_CURRENT_LIST_DIR}RifHdf5Reader.h ) @@ -84,6 +85,7 @@ ${CEE_CURRENT_LIST_DIR}RifCsvUserData.cpp ${CEE_CURRENT_LIST_DIR}RifCsvUserDataParser.cpp ${CEE_CURRENT_LIST_DIR}RifWellPathFormationReader.cpp ${CEE_CURRENT_LIST_DIR}RifWellPathFormationsImporter.cpp +${CEE_CURRENT_LIST_DIR}RifElementPropertyTableReader.cpp # HDF5 file reader is directly included in ResInsight main CmakeList.txt #${CEE_CURRENT_LIST_DIR}RifHdf5Reader.cpp diff --git a/ApplicationCode/FileInterface/RifElementPropertyTableReader.cpp b/ApplicationCode/FileInterface/RifElementPropertyTableReader.cpp new file mode 100644 index 0000000000..68a5a99291 --- /dev/null +++ b/ApplicationCode/FileInterface/RifElementPropertyTableReader.cpp @@ -0,0 +1,196 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifElementPropertyTableReader.h" + +#include "RiaLogging.h" +#include "RiuMainWindow.h" + +#include +#include +#include +#include + +#include +#include +#include + + +//-------------------------------------------------------------------------------------------------- +/// Internal functions +//-------------------------------------------------------------------------------------------------- +static QFile* openFile(const QString &fileName); +static void closeFile(QFile *file); +static QStringList splitLineAndTrim(const QString& line, const QString& separator); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ElementPropertyMetadata RifElementPropertyTableReader::readMetadata(const QString& fileName) +{ + ElementPropertyMetadata metadata; + QFile* file = openFile(fileName); + + if (file) + { + QTextStream stream(file); + bool metadataBlockFound = false; + int maxLinesToRead = 50; + int lineNo = 0; + + while (lineNo < maxLinesToRead) + { + QString line = stream.readLine(); + lineNo++; + + if (line.toUpper().startsWith("*DISTRIBUTION TABLE")) + { + metadataBlockFound = true; + continue; + } + + if (!metadataBlockFound) continue; + + QStringList cols = splitLineAndTrim(line, ","); + + metadata.fileName = fileName; + for (QString s : cols) + { + metadata.dataColumns.push_back(s); + } + break; + } + + closeFile(file); + } + + return metadata; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifElementPropertyTableReader::readData(const ElementPropertyMetadata *metadata, ElementPropertyTable *table) +{ + CVF_ASSERT(metadata && table); + + QFile* file = openFile(metadata->fileName); + int expectedColumnCount = (int)metadata->dataColumns.size() + 1; + + if (file && expectedColumnCount > 0) + { + QTextStream stream(file); + bool dataBlockFound = false; + int lineNo = 0; + + // Init data vectors + table->elementIds.clear(); + table->data = std::vector>(metadata->dataColumns.size()); + + while (!stream.atEnd()) + { + QString line = stream.readLine(); + QStringList cols = splitLineAndTrim(line, ","); + lineNo++; + + if (!dataBlockFound) + { + if (!line.startsWith("*") && cols.size() == expectedColumnCount) dataBlockFound = true; + else continue; + } + + if (cols.size() != expectedColumnCount) + { + throw FileParseException(QString("Number of columns mismatch at %1:%2").arg(metadata->fileName).arg(lineNo)); + } + + for (int c = 0; c < expectedColumnCount; c++) + { + bool parseOk; + + if (c == 0) + { + // Remove elementId column prefix + QStringList parts = cols[0].split("."); + + int elementId = parts.last().toInt(&parseOk); + if (!parseOk) + { + throw FileParseException(QString("Parse failed at %1:%2").arg(metadata->fileName).arg(lineNo)); + } + table->elementIds.push_back(elementId); + } + else + { + float value = cols[c].toFloat(&parseOk); + if (!parseOk) + { + throw FileParseException(QString("Parse failed at %1:%2").arg(metadata->fileName).arg(lineNo)); + } + table->data[c - 1].push_back(value); + } + } + } + + table->hasData = true; + } + + closeFile(file); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QFile* openFile(const QString &fileName) +{ + QFile *file; + file = new QFile(fileName); + if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) + { + RiaLogging::error(QString("Failed to open %1").arg(fileName)); + + delete file; + return nullptr; + } + return file; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void closeFile(QFile *file) +{ + if (file) + { + file->close(); + delete file; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList splitLineAndTrim(const QString& line, const QString& separator) +{ + QStringList cols = line.split(separator); + for (QString& col : cols) + { + col = col.trimmed(); + } + return cols; +} diff --git a/ApplicationCode/FileInterface/RifElementPropertyTableReader.h b/ApplicationCode/FileInterface/RifElementPropertyTableReader.h new file mode 100644 index 0000000000..fc58e53a6b --- /dev/null +++ b/ApplicationCode/FileInterface/RifElementPropertyTableReader.h @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigWellPathFormations.h" + +#include +#include +#include + +#include "cvfBase.h" +#include "cvfObject.h" + +#include + +class ElementPropertyTable; +class ElementPropertyMetadata; + +//================================================================================================== +/// +//================================================================================================== +class RifElementPropertyTableReader : cvf::Object +{ +public: + static ElementPropertyMetadata readMetadata(const QString& filePath); + static void readData(const ElementPropertyMetadata *metadata, ElementPropertyTable *table); +}; + +//================================================================================================== +/// +//================================================================================================== +class FileParseException +{ +public: + FileParseException(const QString &message) : message(message) {} + QString message; +}; + +//================================================================================================== +/// +//================================================================================================== +class ElementPropertyMetadata +{ +public: + QString fileName; + std::vector dataColumns; +}; + + +//================================================================================================== +/// +//================================================================================================== +class ElementPropertyTable +{ +public: + ElementPropertyTable() : hasData(false) {} + + ElementPropertyMetadata metadata; + bool hasData; + std::vector elementIds; + std::vector> data; +}; +