Source code for res2df.faults

#!/usr/bin/env python
"""
Extract the contents of the FAULTS keyword into
a DataFrame

"""

import argparse
import contextlib
import logging
from typing import Union

import pandas as pd

from .common import parse_opmio_deckrecord, write_dframe_stdout_file
from .res2csvlogger import getLogger_res2csv
from .resdatafiles import ResdataFiles

with contextlib.suppress(ImportError):
    # Needed for mypy

    # pylint: disable=unused-import
    import opm.io


logger = logging.getLogger(__name__)

RECORD_COLUMNS = ["NAME", "IX1", "IX2", "IY1", "IY2", "IZ1", "IZ2", "FACE"]
COLUMNS = ["NAME", "I", "J", "K", "FACE"]
ALLOWED_FACES = ["X", "Y", "Z", "I", "J", "K", "X-", "Y-", "Z-", "I-", "J-", "K-"]


[docs]def df(deck: Union[ResdataFiles, "opm.libopmcommon_python.Deck"]) -> pd.DataFrame: """Produce a dataframe of fault data from a :term:`deck` All data for the keyword FAULTS will be returned. Args: deck: A :term:`deck` """ if isinstance(deck, ResdataFiles): deck = deck.get_deck() # In[91]: list(deck['FAULTS'][0]) # Out[91]: [[u'F1'], [36], [36], [41], [42], [1], [14], [u'I']] data = [] # It is allowed in Eclipse to use the keyword FAULTS # as many times as needed. Thus we need to loop in some way: for keyword in deck: if keyword.name == "FAULTS": for rec in keyword: # Each record now has a range potentially in three # dimensions for the fault, unroll this: frec_dict = parse_opmio_deckrecord(rec, "FAULTS") faultname = frec_dict["NAME"] faultface = frec_dict["FACE"] for i_idx in range(frec_dict["IX1"], frec_dict["IX2"] + 1): for j_idx in range(frec_dict["IY1"], frec_dict["IY2"] + 1): for k_idx in range(frec_dict["IZ1"], frec_dict["IZ2"] + 1): data.append([faultname, i_idx, j_idx, k_idx, faultface]) dframe = pd.DataFrame(columns=COLUMNS, data=data) logger.info("Extracted %i faults", len(dframe["NAME"].unique())) return dframe
[docs]def fill_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: """Set up sys.argv parsers. Arguments: parser: argparse.ArgumentParser or argparse.subparser """ parser.add_argument( "DATAFILE", help="Name of the .DATA input file for the reservoir simulator" ) parser.add_argument( "-o", "--output", type=str, help="Name of output csv file.", default="faults.csv", ) parser.add_argument("-v", "--verbose", action="store_true", help="Be verbose") return parser
[docs]def faults_main(args) -> None: """Read from disk and write CSV back to disk""" logger = getLogger_res2csv( # pylint: disable=redefined-outer-name __name__, vars(args) ) resdatafiles = ResdataFiles(args.DATAFILE) if resdatafiles: deck = resdatafiles.get_deck() faults_df = df(deck) write_dframe_stdout_file( faults_df, args.output, index=False, caller_logger=logger, logstr=f"Wrote to {args.output}", )