Пример #1
0
def df(
    deck: Union[str, EclFiles, "opm.libopmcommon_python.Deck"],
    keywords: Optional[List[str]] = None,
    ntequl: Optional[int] = None,
) -> pd.DataFrame:
    """Extract EQUIL related keyword data, EQUIL, RSVD, RVVD
    PBVD and PDVD.

    How each data value in the EQUIL records are to be interpreted
    depends on the phase configuration in the deck, which means
    that we need more than the EQUIL section alone to determine the
    dataframe.

    If ntequl is not supplied and EQLDIMS is not in the deck, the
    equil data is not well defined in terms of OPM. This means
    that we have to infer the correct number of EQUIL lines from what
    gives us successful parsing from OPM. In those cases, the
    deck must be supplied as a string, if not, extra EQUIL lines
    are possibly already removed by the OPM parser in eclfiles.str2deck().

    Arguments:
        deck: Eclipse deck or string with deck. If
           not string, EQLDIMS must be present in the deck.
        keywords: Requested keywords for which to extract data.
        ntequl: If not None, should state the NTEQUL in EQLDIMS. If
            None and EQLDIMS is not present, it will be inferred.

    Return:
        pd.DataFrame, at least with columns KEYWORD and EQLNUM
    """
    if isinstance(deck, EclFiles):
        deck = deck.get_ecldeck()

    deck = inferdims.inject_xxxdims_ntxxx("EQLDIMS", "NTEQUL", deck, ntequl)
    ntequl = deck["EQLDIMS"][0][inferdims.DIMS_POS["NTEQUL"]].get_int(0)

    wanted_keywords = common.handle_wanted_keywords(keywords, deck,
                                                    SUPPORTED_KEYWORDS)

    frames = []
    for keyword in wanted_keywords:
        # Construct the associated function names
        function_name = keyword.lower() + "_fromdeck"
        function = globals()[function_name]
        dframe = function(deck, ntequl=ntequl)
        frames.append(dframe.assign(KEYWORD=keyword))
    nonempty_frames = [frame for frame in frames if not frame.empty]
    if nonempty_frames:
        dframe = pd.concat(nonempty_frames,
                           axis=0,
                           sort=False,
                           ignore_index=True)
        logger.info(
            "Extracted keywords %s for %g EQLNUMs",
            dframe["KEYWORD"].unique(),
            len(dframe["EQLNUM"].unique()),
        )
        return dframe
    logger.warning("No equil data found")
    return pd.DataFrame()
Пример #2
0
def equil_fromdeck(deck, ntequl=None):
    """Extract EQUIL data from a deck

    Args:
        deck (str or opm.common Deck)
        ntequl (int): Number of EQLNUM regions in deck. Will
            be inferred if not present in deck
    """
    if "EQLDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("EQLDIMS", "NTEQUL", deck,
                                              ntequl)

    phasecount = sum(["OIL" in deck, "GAS" in deck, "WATER" in deck])
    phases = phases_from_deck(deck)
    if not phases or phases not in RENAMERS:
        raise ValueError(
            "Could not determine phase configuration, got '{}'".format(phases))
    columnrenamer = RENAMERS[phases_from_deck(deck)]
    if phasecount == 1:
        columnrenamer = {"DATUM_DEPTH": "DATUM", "DATUM_PRESSURE": "PRESSURE"}
    if not columnrenamer:
        raise ValueError("Unsupported phase configuration")

    dataframe = common.ecl_keyworddata_to_df(deck,
                                             "EQUIL",
                                             renamer=columnrenamer,
                                             recordcountername="EQLNUM")

    # The column handling can be made prettier..
    for col in dataframe.columns:
        if "IGNORE" in col:
            del dataframe[col]

    return dataframe
Пример #3
0
def equil_fromdeck(deck: Union[str, "opm.libopmcommon_python.Deck"],
                   ntequl: Optional[int] = None) -> pd.DataFrame:
    """Extract EQUIL data from a deck

    If the deck is supplied as a string object, the number
    of EQLNUM regions will be inferred if needed.

    Args:
        deck
        ntequl: Number of EQLNUM regions in deck.
    """
    if "EQLDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("EQLDIMS", "NTEQUL", deck,
                                              ntequl)

    phases = phases_from_deck(deck)
    if not phases or phases not in RENAMERS:
        raise ValueError(
            f"Could not determine phase configuration, got '{phases}'")
    columnrenamer = RENAMERS[phases_from_deck(deck)]

    dataframe = common.ecl_keyworddata_to_df(deck,
                                             "EQUIL",
                                             renamer=columnrenamer,
                                             recordcountername="EQLNUM")

    # The column handling can be made prettier..
    for col in dataframe.columns:
        if "IGNORE" in col:
            del dataframe[col]

    return dataframe
Пример #4
0
def df(deck, keywords=None, ntsfun=None):
    """Extract the data in the saturation function keywords as a Pandas
    DataFrames.

    Data for all saturation functions are merged into one dataframe.
    The two first columns in the dataframe are 'KEYWORD' (which can be
    SWOF, SGOF, etc.), and then SATNUM which is an index counter from 1 and
    onwards. Then follows the data for each individual keyword that
    is found in the deck.

    SATNUM data can only be parsed correctly if TABDIMS is present
    and stating how many saturation functions there should be.
    If you have a string with TABDIMS missing, you must supply
    this as a string to this function, and not a parsed deck, as
    the default parser in EclFiles is very permissive (and only
    returning the first function by default).

    Arguments:
        deck (opm.io deck or str): Incoming data deck. Always
            supply as a string if you don't know TABDIMS-NTSFUN.
        keywords (list of str): Requested keywords for which to
            to extract data.
        ntsfun (int): Number of SATNUMs defined in the deck, only
            needed if TABDIMS with NTSFUN is not found in the deck.
            If not supplied (or None) and NTSFUN is not defined,
            it will be attempted inferred.

    Return:
        pd.DataFrame, columns 'KEYWORD', 'SW', 'KRW', 'KROW', 'PC', ..
    """
    if isinstance(deck, EclFiles):
        # NB: If this is done on include files and not on DATA files
        # we can loose data for SATNUM > 1
        deck = deck.get_ecldeck()
    deck = inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTSFUN", deck, ntsfun)
    assert "TABDIMS" in deck
    ntsfun = deck["TABDIMS"][0][inferdims.DIMS_POS["NTSFUN"]].get_int(0)

    keywords = common.handle_wanted_keywords(keywords, deck, SUPPORTED_KEYWORDS)

    frames = []
    for keyword in keywords:
        # Construct the associated function names
        function_name = keyword.lower() + "_fromdeck"
        function = globals()[function_name]
        dframe = function(deck, ntsfun=ntsfun)
        frames.append(dframe.assign(KEYWORD=keyword))
    nonempty_frames = [frame for frame in frames if not frame.empty]
    if nonempty_frames:
        dframe = pd.concat(nonempty_frames, axis=0, sort=False, ignore_index=True)
        # We want to sort the keywords by the order they appear in
        # SUPPORTED_KEYWORDS (mainly to get WaterOil before GasOil)
        # We do that by converting to a Categorical series:
        dframe["KEYWORD"] = pd.Categorical(dframe["KEYWORD"], SUPPORTED_KEYWORDS)
        dframe.sort_values(["SATNUM", "KEYWORD"], inplace=True)
        dframe["KEYWORD"] = dframe["KEYWORD"].astype(str)
        return dframe
    return pd.DataFrame()
Пример #5
0
def rock_fromdeck(deck, ntpvt=None):
    """Extract ROCK from a deck

    Args:
        deck (str or opm.common Deck)
        ntpvt (int): Number of PVT regions in deck. Will
            be inferred if not present in deck.
    """
    if "TABDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTPVT", deck, ntpvt)
    return common.ecl_keyworddata_to_df(
        deck, "ROCK", renamer=RENAMERS["ROCK"], recordcountername="PVTNUM"
    )
Пример #6
0
def pdvd_fromdeck(deck, ntequl=None):
    """Extract PDVD data from a deck

    Args:
        deck (str or opm.common Deck)
        ntequl (int): Number of EQLNUM regions in deck. Will
            be inferred if not present in deck
    """
    if "EQLDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("EQLDIMS", "NTEQUL", deck, ntequl)
    return common.ecl_keyworddata_to_df(
        deck, "PDVD", renamer=RENAMERS["PDVD"], recordcountername="EQLNUM"
    )
Пример #7
0
def slgof_fromdeck(deck, ntsfun=None):
    """Extract SLGOF data from a deck

    Args:
        deck (str or opm.common Deck)
        ntsfun (int): Number of SATNUM regions in deck. Will
            be inferred if not present in deck
    """
    if "TABDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTSFUN", deck, ntsfun)
    return common.ecl_keyworddata_to_df(
        deck, "SLGOF", renamer=RENAMERS["SLGOF"], recordcountername="SATNUM"
    )
Пример #8
0
def density_fromdeck(deck: Union[str, "opm.libopmcommon_python.Deck"],
                     ntpvt: Optional[int] = None) -> pd.DataFrame:
    """Extract DENSITY from a deck

    Args:
        deck
        ntpvt: Number of PVT regions in deck. Will
            be inferred if not present in deck.
    """
    if "TABDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTPVT", deck, ntpvt)
    return common.ecl_keyworddata_to_df(deck,
                                        "DENSITY",
                                        renamer=RENAMERS["DENSITY"],
                                        recordcountername="PVTNUM")
Пример #9
0
def df(
    deck: Union[str, "opm.libopmcommon_python.Deck"],
    keywords: Optional[List[str]] = None,
    ntpvt: Optional[int] = None,
) -> pd.DataFrame:
    """Extract all (most) PVT data from a deck.

    If you want to call this function on Eclipse include files,
    read them in to strings as in this example:

    > pvt_df = pvt.df(open("pvt.inc").read())

    Arguments:
        deck: Incoming data deck. Always
            supply as a string if you don't know TABDIMS-NTSFUN.
        keywords: List of keywords for which data is
            wanted. All data will be merged into one dataframe.
        pvtnumcount: Number of PVTNUMs defined in the deck, only
            needed if TABDIMS with NTPVT is not found in the deck.
            If not supplied (or None) and NTPVT is not defined,
            it will be attempted inferred.

    Return:
        pd.DataFrame
    """
    if isinstance(deck, EclFiles):
        deck = deck.get_ecldeck()

    deck = inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTPVT", deck, ntpvt)
    ntpvt = deck["TABDIMS"][0][inferdims.DIMS_POS["NTPVT"]].get_int(0)

    wanted_keywords = common.handle_wanted_keywords(keywords, deck,
                                                    SUPPORTED_KEYWORDS)

    frames = []
    for keyword in wanted_keywords:
        # Construct the associated function names
        function_name = keyword.lower() + "_fromdeck"
        function = globals()[function_name]
        dframe = function(deck, ntpvt=ntpvt)
        frames.append(dframe.assign(KEYWORD=keyword))
    nonempty_frames = [frame for frame in frames if not frame.empty]
    if nonempty_frames:
        return pd.concat(nonempty_frames,
                         axis=0,
                         sort=False,
                         ignore_index=True)
    return pd.DataFrame()
Пример #10
0
def slgof_fromdeck(deck: Union[str, "opm.libopmcommon_python.Deck"],
                   ntsfun: Optional[int] = None) -> pd.DataFrame:
    """Extract SLGOF data from a deck

    Args:
        deck
        ntsfun: Number of SATNUM regions in deck. Will
            be inferred if not present in deck
    """
    if "TABDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTSFUN", deck,
                                              ntsfun)
    return common.ecl_keyworddata_to_df(deck,
                                        "SLGOF",
                                        renamer=RENAMERS["SLGOF"],
                                        recordcountername="SATNUM")
Пример #11
0
def pdvd_fromdeck(deck: Union[str, "opm.libopmcommon_python.Deck"],
                  ntequl: Optional[int] = None) -> pd.DataFrame:
    """Extract PDVD data from a deck

    Args:
        deck
        ntequl: Number of EQLNUM regions in deck. Will
            be inferred if not present in deck
    """
    if "EQLDIMS" not in deck:
        deck = inferdims.inject_xxxdims_ntxxx("EQLDIMS", "NTEQUL", deck,
                                              ntequl)
    return common.ecl_keyworddata_to_df(deck,
                                        "PDVD",
                                        renamer=RENAMERS["PDVD"],
                                        recordcountername="EQLNUM")
Пример #12
0
def test_inject_xxxdims_ntxxx():
    """Test the wrapper of inject_dimcount()"""

    with pytest.raises(AssertionError):
        inferdims.inject_xxxdims_ntxxx("WELLDIMS", "NTSFUN", "SWOF\n0/\n0/\n")
    with pytest.raises(AssertionError):
        inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTFUN", "SWOF\n0/\n0/\n")

    # Repeated calls should be ok:
    deck_with_injection = inferdims.inject_xxxdims_ntxxx(
        "TABDIMS", "NTSFUN", "SWOF\n0/\n0/\n")
    assert deck_with_injection == inferdims.inject_xxxdims_ntxxx(
        "TABDIMS", "NTSFUN", deck_with_injection)
Пример #13
0
def test_inject_xxxdims_ntxxx():
    """Test the wrapper of inject_dimcount()"""

    with pytest.raises(AssertionError):
        inferdims.inject_xxxdims_ntxxx("WELLDIMS", "NTSFUN", "SWOF\n0/\n0/\n")
    with pytest.raises(AssertionError):
        inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTFUN", "SWOF\n0/\n0/\n")

    # Repeated calls should be ok:
    deck_with_injection = inferdims.inject_xxxdims_ntxxx(
        "TABDIMS", "NTSFUN", "SWOF\n0/\n0/\n", 1
    )
    assert "TABDIMS\n   1 /" in str(
        inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTSFUN", deck_with_injection, 10)
    )
    # If no number is supplied, return the deck untouched:
    assert "TABDIMS\n   1 /" in str(
        inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTSFUN", deck_with_injection, None)
    )
Пример #14
0
def df(
    deck: Union[str, "opm.libopmcommon_python.Deck"],
    keywords: Optional[List[str]] = None,
    ntsfun: Optional[int] = None,
) -> pd.DataFrame:
    """Extract the data in the saturation function keywords as a Pandas
    DataFrames.

    Data for all saturation functions are merged into one dataframe.
    The two first columns in the dataframe are 'KEYWORD' (which can be
    SWOF, SGOF, etc.), and then SATNUM which is an index counter from 1 and
    onwards. Then follows the data for each individual keyword that
    is found in the deck.

    SATNUM data can only be parsed correctly if TABDIMS is present
    and stating how many saturation functions there should be.
    If you have a string with TABDIMS missing, you must supply
    this as a string to this function, and not a parsed deck, as
    the default parser in EclFiles is very permissive (and only
    returning the first function by default).

    Arguments:
        deck: Incoming data deck. Always
            supply as a string if you don't know TABDIMS-NTSFUN.
        keywords: Requested keywords for which to
            to extract data.
        ntsfun: Number of SATNUMs defined in the deck, only
            needed if TABDIMS with NTSFUN is not found in the deck.
            If not supplied (or None) and NTSFUN is not defined,
            it will be attempted inferred.

    Return:
        pd.DataFrame, columns 'KEYWORD', 'SW', 'KRW', 'KROW', 'PC', ..
    """
    if isinstance(deck, EclFiles):
        # NB: If this is done on include files and not on DATA files
        # we can loose data for SATNUM > 1
        deck = deck.get_ecldeck()
    deck = inferdims.inject_xxxdims_ntxxx("TABDIMS", "NTSFUN", deck, ntsfun)
    assert "TABDIMS" in deck

    wanted_keywords = common.handle_wanted_keywords(keywords, deck,
                                                    SUPPORTED_KEYWORDS)

    frames = []
    for keyword in wanted_keywords:
        frames.append(
            interpolate_defaults(
                common.ecl_keyworddata_to_df(
                    deck,
                    keyword,
                    renamer=RENAMERS[keyword],
                    recordcountername="SATNUM").assign(KEYWORD=keyword)))
    nonempty_frames = [frame for frame in frames if not frame.empty]
    if nonempty_frames:
        dframe = pd.concat(nonempty_frames,
                           axis=0,
                           sort=False,
                           ignore_index=True)
        # We want to sort the keywords by the order they appear in
        # SUPPORTED_KEYWORDS (mainly to get WaterOil before GasOil)
        # We do that by converting to a Categorical series:
        dframe["KEYWORD"] = pd.Categorical(dframe["KEYWORD"],
                                           SUPPORTED_KEYWORDS)
        dframe.sort_values(["SATNUM", "KEYWORD"], inplace=True)
        dframe["KEYWORD"] = dframe["KEYWORD"].astype(str)
        logger.info(
            "Extracted keywords %s for %i SATNUMs",
            dframe["KEYWORD"].unique(),
            len(dframe["SATNUM"].unique()),
        )
        return dframe
    return pd.DataFrame()