mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-31 09:14:11 -05:00
Add path pattern helper functions and tests
This commit is contained in:
1 parent
5126face72
commit
f708ac96f2
4 files changed
+289
No files matched your search
@@ -20,12 +20,16 @@
|
||||
|
||||
#include "RiaGuiApplication.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaStdStringTools.h"
|
||||
#include "Summary/RiaSummaryTools.h"
|
||||
|
||||
#include "RifSummaryCaseRestartSelector.h"
|
||||
|
||||
#include "RimSummaryCaseMainCollection.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace RiaEnsembleImportTools
|
||||
{
|
||||
|
||||
@@ -78,4 +82,213 @@ std::pair<bool, std::vector<RimSummaryCase*>> createSummaryCasesFromFiles( const
|
||||
return std::make_pair( true, newCases );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<QString, QString> findPathPattern( const QStringList& filePaths, const QString& placeholderString )
|
||||
{
|
||||
if ( filePaths.isEmpty() ) return {};
|
||||
|
||||
std::vector<std::vector<int>> tableOfNumbers;
|
||||
|
||||
QRegularExpression numberRegex( "\\d+" );
|
||||
|
||||
for ( const auto& f : filePaths )
|
||||
{
|
||||
std::vector<int> valuesInString;
|
||||
auto matchIterator = numberRegex.globalMatch( f );
|
||||
while ( matchIterator.hasNext() )
|
||||
{
|
||||
auto match = matchIterator.next();
|
||||
QString number = match.captured( 0 );
|
||||
|
||||
valuesInString.push_back( number.toInt() );
|
||||
}
|
||||
tableOfNumbers.push_back( valuesInString );
|
||||
}
|
||||
|
||||
if ( tableOfNumbers.empty() ) return {};
|
||||
|
||||
const auto valuesFirstRow = tableOfNumbers[0];
|
||||
if ( valuesFirstRow.empty() ) return {};
|
||||
|
||||
std::vector<size_t> valueCountEachIndex;
|
||||
valueCountEachIndex.resize( valuesFirstRow.size(), 1 );
|
||||
|
||||
for ( size_t rowIndex = 1; rowIndex < tableOfNumbers.size(); ++rowIndex )
|
||||
{
|
||||
const auto& values = tableOfNumbers[rowIndex];
|
||||
for ( size_t j = 0; j < std::min( valuesFirstRow.size(), values.size() ); ++j )
|
||||
{
|
||||
if ( values[j] != valuesFirstRow[j] )
|
||||
{
|
||||
valueCountEachIndex[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString firstPath = filePaths[0];
|
||||
QList<QPair<int, int>> numberPositions; // start pos, length
|
||||
|
||||
auto i = numberRegex.globalMatch( firstPath );
|
||||
while ( i.hasNext() )
|
||||
{
|
||||
auto match = i.next();
|
||||
numberPositions.append( qMakePair( match.capturedStart(), match.capturedLength() ) );
|
||||
}
|
||||
|
||||
if ( numberPositions.isEmpty() ) return {};
|
||||
|
||||
// For each number position, check if there are unique values for all rows
|
||||
QList<QPair<int, int>> varyingNumberPositions;
|
||||
|
||||
for ( size_t i = 0; i < static_cast<size_t>( numberPositions.size() ); i++ )
|
||||
{
|
||||
const auto& varyPos = numberPositions[i];
|
||||
if ( i < valueCountEachIndex.size() && valueCountEachIndex[i] == tableOfNumbers.size() )
|
||||
{
|
||||
varyingNumberPositions.push_back( varyPos );
|
||||
}
|
||||
}
|
||||
|
||||
if ( varyingNumberPositions.empty() ) return {};
|
||||
|
||||
// Extract the varying numbers
|
||||
std::vector<int> numbers;
|
||||
|
||||
// Find the first varying position
|
||||
int varyingPosition = -1;
|
||||
for ( size_t i = 0; i < valueCountEachIndex.size(); i++ )
|
||||
{
|
||||
if ( valueCountEachIndex[i] == tableOfNumbers.size() )
|
||||
{
|
||||
varyingPosition = static_cast<int>( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract numbers from the varying position
|
||||
if ( varyingPosition >= 0 )
|
||||
{
|
||||
for ( const auto& values : tableOfNumbers )
|
||||
{
|
||||
if ( varyingPosition < static_cast<int>( values.size() ) )
|
||||
{
|
||||
numbers.push_back( values[varyingPosition] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( numbers.size() != static_cast<size_t>( filePaths.size() ) ) return {};
|
||||
|
||||
auto pattern = filePaths.front();
|
||||
|
||||
// Loop over varying number positions in reverse order to avoid messing up the positions when replacing the varying part with a
|
||||
// placeholder
|
||||
for ( int i = varyingNumberPositions.size() - 1; i >= 0; --i )
|
||||
{
|
||||
const auto& [start, length] = varyingNumberPositions[i];
|
||||
|
||||
pattern.replace( start, length, placeholderString );
|
||||
}
|
||||
|
||||
auto rangeString = QString::fromStdString( RiaStdStringTools::formatRangeSelection( numbers ) );
|
||||
|
||||
return { pattern, rangeString };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QStringList createPathsFromPattern( const QString& basePath, const QString& numberRange, const QString& placeholderString )
|
||||
{
|
||||
QStringList paths;
|
||||
|
||||
auto numbers = RiaStdStringTools::valuesFromRangeSelection( numberRange.toStdString() );
|
||||
for ( const auto& number : numbers )
|
||||
{
|
||||
QString path = basePath;
|
||||
path.replace( placeholderString, QString::number( number ) );
|
||||
paths.push_back( path );
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Find all files matching the path pattern in the file system
|
||||
//
|
||||
// Example:
|
||||
// pathPattern = "/myfolder/drogon-varying-grid-geometry/realization-*/iter-0/eclipse/model/DROGON-*.EGRID"
|
||||
//
|
||||
// basePath will be "/myfolder/drogon-varying-grid-geometry/"
|
||||
//
|
||||
// The '*' in the pathPattern is replaced with a regex pattern to capture numbers
|
||||
// regexPattern will be "/myfolder/drogon-varying-grid-geometry/realization-(\\d+)/iter-0/eclipse/model/DROGON-(\\d+).EGRID"
|
||||
//
|
||||
// The basePath will be traversed recursively to find all files matching the regex pattern
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QStringList createPathsBySearchingFileSystem( const QString& pathPattern, const QString& placeholderString )
|
||||
{
|
||||
auto basePath = pathPattern;
|
||||
|
||||
// Find based path up to "/realization"
|
||||
auto realizationPos = basePath.indexOf( "/realization" );
|
||||
if ( realizationPos != -1 )
|
||||
{
|
||||
basePath = basePath.left( realizationPos );
|
||||
}
|
||||
|
||||
QStringList matchingFiles;
|
||||
|
||||
// Replace placeholder string with a regex pattern to capture numbers
|
||||
QString regexPattern = pathPattern;
|
||||
regexPattern.replace( placeholderString, "(\\d+)" );
|
||||
|
||||
QRegularExpression regex( regexPattern );
|
||||
|
||||
// Use QDirIterator to traverse the directory recursively
|
||||
QDirIterator it( basePath, QDir::Files, QDirIterator::Subdirectories );
|
||||
while ( it.hasNext() )
|
||||
{
|
||||
QString filePath = it.next();
|
||||
|
||||
QRegularExpressionMatch match = regex.match( filePath );
|
||||
if ( match.hasMatch() )
|
||||
{
|
||||
QString index1 = match.captured( 1 );
|
||||
QString index2 = match.captured( 2 );
|
||||
|
||||
if ( index1 == index2 )
|
||||
{
|
||||
matchingFiles << filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort files by realization number
|
||||
std::sort( matchingFiles.begin(),
|
||||
matchingFiles.end(),
|
||||
[]( const QString& a, const QString& b )
|
||||
{
|
||||
QRegularExpression regex( "realization-(\\d+)" );
|
||||
|
||||
auto matchA = regex.match( a );
|
||||
auto matchB = regex.match( b );
|
||||
|
||||
if ( matchA.hasMatch() && matchB.hasMatch() )
|
||||
{
|
||||
int numA = matchA.captured( 1 ).toInt();
|
||||
int numB = matchB.captured( 1 ).toInt();
|
||||
return numA < numB;
|
||||
}
|
||||
|
||||
// Fallback to alphabetical if regex doesn't match
|
||||
return a < b;
|
||||
} );
|
||||
|
||||
return matchingFiles;
|
||||
}
|
||||
|
||||
} // namespace RiaEnsembleImportTools
|
||||
@@ -34,4 +34,7 @@ struct CreateConfig
|
||||
};
|
||||
std::pair<bool, std::vector<RimSummaryCase*>> createSummaryCasesFromFiles( const QStringList& fileNames, CreateConfig createConfig );
|
||||
|
||||
std::pair<QString, QString> findPathPattern( const QStringList& filePaths, const QString& placeholderString );
|
||||
QStringList createPathsFromPattern( const QString& basePath, const QString& numberRange, const QString& placeholderString );
|
||||
QStringList createPathsBySearchingFileSystem( const QString& pathPattern, const QString& placeholderString );
|
||||
} // namespace RiaEnsembleImportTools
|
||||
Reference in new issue
Block a user