mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#5829 Add reader for ROFF files to extract category names and values from file
This commit is contained in:
committed by
Magne Sjaastad
parent
423b6c2887
commit
3f4778509d
@@ -51,6 +51,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.h
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.h
|
${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifEclipseInputPropertyLoader.h
|
${CMAKE_CURRENT_LIST_DIR}/RifEclipseInputPropertyLoader.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader.h
|
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RifRoffReader.h
|
||||||
|
|
||||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
||||||
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h
|
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h
|
||||||
@@ -106,7 +107,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.cpp
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderEnsembleStatisticsRft.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifReaderEnsembleStatisticsRft.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifEclipseInputPropertyLoader.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifEclipseInputPropertyLoader.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RifRoffReader.cpp
|
||||||
|
|
||||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
||||||
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp
|
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp
|
||||||
|
|||||||
141
ApplicationCode/FileInterface/RifRoffReader.cpp
Normal file
141
ApplicationCode/FileInterface/RifRoffReader.cpp
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor 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 <http://www.gnu.org/licenses/gpl.html>
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "RifRoffReader.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
const QString codeValuesString = QString( "array int codeValues" );
|
||||||
|
const QString codeNamesString = QString( "array char codeNames" );
|
||||||
|
const QString headerString = QString( "roff-asc" );
|
||||||
|
|
||||||
|
bool RifRoffReader::isCodeValuesDefinition( const QString& line )
|
||||||
|
{
|
||||||
|
return line.startsWith( codeValuesString );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RifRoffReader::isCodeNamesDefinition( const QString& line )
|
||||||
|
{
|
||||||
|
return line.startsWith( codeNamesString );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RifRoffReader::isCorrectHeader( const QString& line )
|
||||||
|
{
|
||||||
|
return line.startsWith( headerString );
|
||||||
|
}
|
||||||
|
|
||||||
|
int RifRoffReader::extractNumberAfterString( const QString& line, const QString& prefix )
|
||||||
|
{
|
||||||
|
QString copiedLine( line );
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
int num = copiedLine.remove( prefix ).toInt( &ok );
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
throw RifRoffReaderException( "Unexpected value: not an integer." );
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RifRoffReader::extractCodeValuesCount( const QString& line )
|
||||||
|
{
|
||||||
|
return extractNumberAfterString( line, codeValuesString );
|
||||||
|
}
|
||||||
|
|
||||||
|
int RifRoffReader::extractCodeNamesCount( const QString& line )
|
||||||
|
{
|
||||||
|
return extractNumberAfterString( line, codeNamesString );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RifRoffReader::readCodeNames( const QString& filename, std::map<int, QString>& codeNames )
|
||||||
|
{
|
||||||
|
QFile file( filename );
|
||||||
|
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||||
|
{
|
||||||
|
throw RifRoffReaderException( "Unable to open roff file." );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFirstLine = true;
|
||||||
|
int numCodeValues = -1;
|
||||||
|
int numCodeNames = -1;
|
||||||
|
|
||||||
|
std::vector<int> readCodeValues;
|
||||||
|
std::vector<QString> readCodeNames;
|
||||||
|
|
||||||
|
QTextStream in( &file );
|
||||||
|
while ( !in.atEnd() )
|
||||||
|
{
|
||||||
|
QString line = in.readLine();
|
||||||
|
|
||||||
|
// Check that the first line has the roff-asc header
|
||||||
|
if ( isFirstLine )
|
||||||
|
{
|
||||||
|
if ( !isCorrectHeader( line ) )
|
||||||
|
{
|
||||||
|
throw RifRoffReaderException( "Unexpected file type: roff-asc header missing." );
|
||||||
|
}
|
||||||
|
isFirstLine = false;
|
||||||
|
}
|
||||||
|
else if ( isCodeValuesDefinition( line ) )
|
||||||
|
{
|
||||||
|
// Expected line:
|
||||||
|
// array int codeValues 99
|
||||||
|
numCodeValues = extractCodeValuesCount( line );
|
||||||
|
for ( int i = 0; i < numCodeValues; i++ )
|
||||||
|
{
|
||||||
|
// The code values comes next, can be multiple per line.
|
||||||
|
int codeValue;
|
||||||
|
in >> codeValue;
|
||||||
|
readCodeValues.push_back( codeValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( isCodeNamesDefinition( line ) )
|
||||||
|
{
|
||||||
|
// Expected line:
|
||||||
|
// array char codeNames 99
|
||||||
|
numCodeNames = extractCodeNamesCount( line );
|
||||||
|
for ( int i = 0; i < numCodeNames; i++ )
|
||||||
|
{
|
||||||
|
// Read code names. Assumes one name per line.
|
||||||
|
QString codeName = in.readLine();
|
||||||
|
readCodeNames.push_back( codeName.trimmed().remove( "\"" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( numCodeValues == -1 )
|
||||||
|
{
|
||||||
|
throw RifRoffReaderException( "Code values not found." );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( numCodeNames == -1 )
|
||||||
|
{
|
||||||
|
throw RifRoffReaderException( "Code names not found." );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( numCodeNames != numCodeValues )
|
||||||
|
{
|
||||||
|
throw RifRoffReaderException( "Inconsistent code names and values: must be equal length." );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < numCodeNames; i++ )
|
||||||
|
{
|
||||||
|
codeNames[readCodeValues[i]] = readCodeNames[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
58
ApplicationCode/FileInterface/RifRoffReader.h
Normal file
58
ApplicationCode/FileInterface/RifRoffReader.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor 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 <http://www.gnu.org/licenses/gpl.html>
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
///
|
||||||
|
//==================================================================================================
|
||||||
|
class RifRoffReaderException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RifRoffReaderException( const std::string& message )
|
||||||
|
: message( message )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string message;
|
||||||
|
};
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
///
|
||||||
|
//==================================================================================================
|
||||||
|
class RifRoffReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Throws RifRoffReaderException on error
|
||||||
|
static void readCodeNames( const QString& filename, std::map<int, QString>& codeNames );
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool isCorrectHeader( const QString& line );
|
||||||
|
static bool isCodeNamesDefinition( const QString& line );
|
||||||
|
static bool isCodeValuesDefinition( const QString& line );
|
||||||
|
|
||||||
|
static int extractNumberAfterString( const QString& line, const QString& prefix );
|
||||||
|
static int extractCodeNamesCount( const QString& line );
|
||||||
|
static int extractCodeValuesCount( const QString& line );
|
||||||
|
};
|
||||||
@@ -66,6 +66,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifWellMeasurementReader-Test.cpp
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RiaDateStringParser-Test.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RiaDateStringParser-Test.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RigHexGradientTools-Test.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RigHexGradientTools-Test.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader-Test.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader-Test.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RifRoffReader-Test.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (RESINSIGHT_ENABLE_GRPC)
|
if (RESINSIGHT_ENABLE_GRPC)
|
||||||
|
|||||||
87
ApplicationCode/UnitTests/RifRoffReader-Test.cpp
Normal file
87
ApplicationCode/UnitTests/RifRoffReader-Test.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "RifRoffReader.h"
|
||||||
|
|
||||||
|
#include "RiaTestDataDirectory.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
TEST( RifRoffReader, ReadValidFile )
|
||||||
|
{
|
||||||
|
QDir baseFolder( TEST_DATA_DIR );
|
||||||
|
|
||||||
|
QString filename( "RifRoffReader/facies_info.roff" );
|
||||||
|
QString filePath = baseFolder.absoluteFilePath( filename );
|
||||||
|
EXPECT_TRUE( QFile::exists( filePath ) );
|
||||||
|
|
||||||
|
std::map<int, QString> codeNames;
|
||||||
|
RifRoffReader::readCodeNames( filePath, codeNames );
|
||||||
|
|
||||||
|
ASSERT_EQ( 6u, codeNames.size() );
|
||||||
|
for ( int i = 0; i < 6; i++ )
|
||||||
|
{
|
||||||
|
ASSERT_TRUE( codeNames.find( i ) != codeNames.end() );
|
||||||
|
ASSERT_EQ( codeNames.find( i )->second.toStdString(), QString( "code name %1" ).arg( i + 1 ).toStdString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string readIncorrectFile( const QString filename )
|
||||||
|
{
|
||||||
|
QDir baseFolder( TEST_DATA_DIR );
|
||||||
|
|
||||||
|
QString filePath = baseFolder.absoluteFilePath( filename );
|
||||||
|
|
||||||
|
std::map<int, QString> codeNames;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RifRoffReader::readCodeNames( filePath, codeNames );
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
catch ( RifRoffReaderException& ex )
|
||||||
|
{
|
||||||
|
return ex.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST( RifRoffReader, ReadWrongFileType )
|
||||||
|
{
|
||||||
|
// Read a surface file: no expected to work
|
||||||
|
QString filename( "RifSurfaceReader/test.ptl" );
|
||||||
|
ASSERT_EQ( readIncorrectFile( filename ), std::string( "Unexpected file type: roff-asc header missing." ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST( RifRoffReader, ReadNonExistingFileType )
|
||||||
|
{
|
||||||
|
// Read a non-existing file
|
||||||
|
QString filename( "RifRoffReader/this_file_does_not_exist.roff" );
|
||||||
|
ASSERT_EQ( readIncorrectFile( filename ), std::string( "Unable to open roff file." ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST( RifRoffReader, ReadFileWithIncorrectInteger )
|
||||||
|
{
|
||||||
|
// Read a file with incorrect integer for code values
|
||||||
|
QString filename( "RifRoffReader/code_values_integer_wrong.roff" );
|
||||||
|
ASSERT_EQ( readIncorrectFile( filename ), std::string( "Unexpected value: not an integer." ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST( RifRoffReader, ReadFileCodeNamesMissing )
|
||||||
|
{
|
||||||
|
// Read a file without code names
|
||||||
|
QString filename( "RifRoffReader/code_names_missing.roff" );
|
||||||
|
ASSERT_EQ( readIncorrectFile( filename ), std::string( "Code names not found." ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST( RifRoffReader, ReadFileCodeValuesMissing )
|
||||||
|
{
|
||||||
|
// Read a file without code values
|
||||||
|
QString filename( "RifRoffReader/code_values_missing.roff" );
|
||||||
|
ASSERT_EQ( readIncorrectFile( filename ), std::string( "Code values not found." ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST( RifRoffReader, ReadFileCodeNamesAndValuesMismatch )
|
||||||
|
{
|
||||||
|
// Read a file without code values
|
||||||
|
QString filename( "RifRoffReader/code_names_and_values_mismatch.roff" );
|
||||||
|
ASSERT_EQ( readIncorrectFile( filename ), std::string( "Inconsistent code names and values: must be equal length." ) );
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
roff-asc
|
||||||
|
#ROFF file#
|
||||||
|
#Creator: RMS - Reservoir Modeling System, version 11.1.0#
|
||||||
|
tag filedata
|
||||||
|
int byteswaptest 1
|
||||||
|
char filetype "parameter"
|
||||||
|
char creationDate "06/03/2020 14:25:36"
|
||||||
|
endtag
|
||||||
|
tag version
|
||||||
|
int major 2
|
||||||
|
int minor 0
|
||||||
|
endtag
|
||||||
|
tag dimensions
|
||||||
|
int nX 46
|
||||||
|
int nY 112
|
||||||
|
int nZ 242
|
||||||
|
endtag
|
||||||
|
tag parameter
|
||||||
|
char name "composite"
|
||||||
|
array char codeNames 4
|
||||||
|
"only"
|
||||||
|
"four"
|
||||||
|
"code"
|
||||||
|
"names"
|
||||||
|
array int codeValues 6
|
||||||
|
0 1 2 3 4 5
|
||||||
|
array int data 4
|
||||||
|
-999 -999 -999 -999
|
||||||
|
endtag
|
||||||
|
tag eof
|
||||||
|
endtag
|
||||||
26
ApplicationCode/UnitTests/TestData/RifRoffReader/code_names_missing.roff
Executable file
26
ApplicationCode/UnitTests/TestData/RifRoffReader/code_names_missing.roff
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
roff-asc
|
||||||
|
#ROFF file#
|
||||||
|
#Creator: RMS - Reservoir Modeling System, version 11.1.0#
|
||||||
|
tag filedata
|
||||||
|
int byteswaptest 1
|
||||||
|
char filetype "parameter"
|
||||||
|
char creationDate "06/03/2020 14:25:36"
|
||||||
|
endtag
|
||||||
|
tag version
|
||||||
|
int major 2
|
||||||
|
int minor 0
|
||||||
|
endtag
|
||||||
|
tag dimensions
|
||||||
|
int nX 46
|
||||||
|
int nY 112
|
||||||
|
int nZ 242
|
||||||
|
endtag
|
||||||
|
tag parameter
|
||||||
|
char name "composite"
|
||||||
|
array int codeValues 6
|
||||||
|
0 1 2 3 4 5
|
||||||
|
array int data 4
|
||||||
|
-999 -999 -999 -999
|
||||||
|
endtag
|
||||||
|
tag eof
|
||||||
|
endtag
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
roff-asc
|
||||||
|
#ROFF file#
|
||||||
|
#Creator: RMS - Reservoir Modeling System, version 11.1.0#
|
||||||
|
tag filedata
|
||||||
|
int byteswaptest 1
|
||||||
|
char filetype "parameter"
|
||||||
|
char creationDate "06/03/2020 14:25:36"
|
||||||
|
endtag
|
||||||
|
tag version
|
||||||
|
int major 2
|
||||||
|
int minor 0
|
||||||
|
endtag
|
||||||
|
tag dimensions
|
||||||
|
int nX 46
|
||||||
|
int nY 112
|
||||||
|
int nZ 242
|
||||||
|
endtag
|
||||||
|
tag parameter
|
||||||
|
char name "composite"
|
||||||
|
array char codeNames 2
|
||||||
|
"cn1"
|
||||||
|
"cn2"
|
||||||
|
array int codeValues this_is_not_a_number
|
||||||
|
0 1 2 3 4 5
|
||||||
|
array int data 4
|
||||||
|
-999 -999 -999 -999
|
||||||
|
endtag
|
||||||
|
tag eof
|
||||||
|
endtag
|
||||||
26
ApplicationCode/UnitTests/TestData/RifRoffReader/code_values_missing.roff
Executable file
26
ApplicationCode/UnitTests/TestData/RifRoffReader/code_values_missing.roff
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
roff-asc
|
||||||
|
#ROFF file#
|
||||||
|
#Creator: RMS - Reservoir Modeling System, version 11.1.0#
|
||||||
|
tag filedata
|
||||||
|
int byteswaptest 1
|
||||||
|
char filetype "parameter"
|
||||||
|
char creationDate "06/03/2020 14:25:36"
|
||||||
|
endtag
|
||||||
|
tag version
|
||||||
|
int major 2
|
||||||
|
int minor 0
|
||||||
|
endtag
|
||||||
|
tag dimensions
|
||||||
|
int nX 46
|
||||||
|
int nY 112
|
||||||
|
int nZ 242
|
||||||
|
endtag
|
||||||
|
tag parameter
|
||||||
|
char name "composite"
|
||||||
|
array char codeNames 1
|
||||||
|
"a name"
|
||||||
|
array int data 4
|
||||||
|
-999 -999 -999 -999
|
||||||
|
endtag
|
||||||
|
tag eof
|
||||||
|
endtag
|
||||||
33
ApplicationCode/UnitTests/TestData/RifRoffReader/facies_info.roff
Executable file
33
ApplicationCode/UnitTests/TestData/RifRoffReader/facies_info.roff
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
roff-asc
|
||||||
|
#ROFF file#
|
||||||
|
#Creator: RMS - Reservoir Modeling System, version 11.1.0#
|
||||||
|
tag filedata
|
||||||
|
int byteswaptest 1
|
||||||
|
char filetype "parameter"
|
||||||
|
char creationDate "06/03/2020 14:25:36"
|
||||||
|
endtag
|
||||||
|
tag version
|
||||||
|
int major 2
|
||||||
|
int minor 0
|
||||||
|
endtag
|
||||||
|
tag dimensions
|
||||||
|
int nX 46
|
||||||
|
int nY 112
|
||||||
|
int nZ 242
|
||||||
|
endtag
|
||||||
|
tag parameter
|
||||||
|
char name "composite"
|
||||||
|
array char codeNames 6
|
||||||
|
"code name 1"
|
||||||
|
"code name 2"
|
||||||
|
"code name 3"
|
||||||
|
"code name 4"
|
||||||
|
"code name 5"
|
||||||
|
"code name 6"
|
||||||
|
array int codeValues 6
|
||||||
|
0 1 2 3 4 5
|
||||||
|
array int data 4
|
||||||
|
-999 -999 -999 -999
|
||||||
|
endtag
|
||||||
|
tag eof
|
||||||
|
endtag
|
||||||
Reference in New Issue
Block a user