def test_error_messages_pr_satnum(caplog): """When errors are somewhere in a big dataframe, we should provide hints to the user for where to look""" # A string instead of a number in SATNUM 2 dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"], data=[[1, 1, 1], [2, "foo", 1]]) with pytest.raises(ValueError, match="SATNUM 2"): PyscalFactory.create_pyscal_list(dframe, h=0.2) dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"], data=[[1, 1, 1], [2, np.nan, 1]]) with pytest.raises(ValueError, match="SATNUM 2"): PyscalFactory.create_pyscal_list(dframe, h=0.2) # Mixed up order: dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"], data=[[2, np.nan, 1], [1, 1, 1]]) with pytest.raises(ValueError, match="SATNUM 2"): PyscalFactory.create_pyscal_list(dframe, h=0.2) # Gasoil list dframe = pd.DataFrame(columns=["SATNUM", "ng", "nog"], data=[[1, 1, 1], [2, np.nan, 1]]) with pytest.raises(ValueError, match="SATNUM 2"): PyscalFactory.create_pyscal_list(dframe, h=0.2) # Gaswater list: dframe = pd.DataFrame(columns=["SATNUM", "ng", "nw"], data=[[1, 1, 1], [2, np.nan, 1]]) with pytest.raises(ValueError, match="SATNUM 2"): PyscalFactory.create_pyscal_list(dframe, h=0.2) # Wateroilgas list: dframe = pd.DataFrame( columns=["SATNUM", "nw", "now", "ng", "nog"], data=[[1, 1, 1, 1, 1], [2, np.nan, 1, 2, 3]], ) with pytest.raises(ValueError, match="SATNUM 2"): PyscalFactory.create_pyscal_list(dframe, h=0.2) # SCAL rec list: dframe = pd.DataFrame( columns=["SATNUM", "CASE", "nw", "now", "ng", "nog"], data=[ [1, "low", 1, 1, 1, 1], [1, "base", 1, 1, 1, 1], [1, "high", 1, 1, 1, 1], [2, "low", np.nan, 1, 2, 3], [2, "base", 2, 1, 2, 3], [2, "high", 3, 1, 2, 3], ], ) # The error should hint both to SATNUM and to low/base/high with pytest.raises(ValueError, match="SATNUM 2"): PyscalFactory.create_scal_recommendation_list(dframe, h=0.2) with pytest.raises(ValueError, match="Problem with low"): PyscalFactory.create_scal_recommendation_list(dframe, h=0.2)
def test_case_aliasing(): """Test that we can use aliases for the CASE column in SCAL recommendations""" dframe = pd.DataFrame( columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"], data=[ [1, "pess", 2, 2, 1, 1], [1, "base", 3, 1, 1, 1], [1, "optIMIstiC", 3, 1, 1, 1], ], ) relperm_data = PyscalFactory.load_relperm_df(dframe) PyscalFactory.create_scal_recommendation_list(relperm_data, h=0.2).interpolate(-0.4) with pytest.raises(ValueError): PyscalFactory.load_relperm_df( pd.DataFrame( columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"], data=[ [1, "FOOBAR", 2, 2, 1, 1], [1, "base", 3, 1, 1, 1], [1, "optIMIstiC", 3, 1, 1, 1], ], ) ) # Ambigous data: with pytest.raises(ValueError): amb = PyscalFactory.load_relperm_df( pd.DataFrame( columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"], data=[ [1, "low", 2, 2, 1, 1], [1, "pess", 5, 5, 5, 5], [1, "base", 3, 1, 1, 1], [1, "optIMIstiC", 3, 1, 1, 1], ], ) ) PyscalFactory.create_scal_recommendation_list(amb) # Missing a case with pytest.raises(ValueError): PyscalFactory.load_relperm_df( pd.DataFrame( columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"], data=[[1, "base", 3, 1, 1, 1], [1, "optIMIstiC", 3, 1, 1, 1]], ) ) # Missing a case with pytest.raises(ValueError): PyscalFactory.load_relperm_df( pd.DataFrame( columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"], data=[[1, "base", 3, 1, 1, 1]], ) )
def test_load_scalrec_tags(): """Test tag handling for a SCAL recommendation with SATNUM range""" if "__file__" in globals(): # Easen up copying test code into interactive sessions testdir = os.path.dirname(os.path.abspath(__file__)) else: testdir = os.path.abspath(".") scalrec_data = PyscalFactory.load_relperm_df( testdir + "/data/scal-pc-input-example.xlsx") scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data) wog_list = scalrec_list.interpolate(-1) swof = wog_list.SWOF() assert swof.count("SCAL recommendation interpolation to -1") == 3 assert swof.count("SATNUM 1") == 1 assert swof.count("SATNUM") == 3 sof3 = wog_list.SOF3() assert sof3.count("SCAL recommendation interpolation to -1") == 3 assert sof3.count("SATNUM 1") == 1 assert sof3.count("SATNUM") == 3 assert (scalrec_list.interpolate(1).SWOF().count( "SCAL recommendation interpolation to 1\n") == 3) assert (scalrec_list.interpolate(0).SWOF().count( "SCAL recommendation interpolation to 0\n") == 3) assert (scalrec_list.interpolate(-0.444).SWOF().count( "SCAL recommendation interpolation to -0.444\n") == 3) # Give each row in the SCAL recommendation its own tag (low, base, high # explicitly in each tag, someone will do that) scalrec_data["TAG"] = [ "SAT1 low", "SAT1 base", "SAT1 high", "SAT2 pess", "SAT2 base", "SAT2 opt", "SAT3 pessimistic", "SAT3 base case", "SAT3 optimistic", ] scalrec_list2 = PyscalFactory.create_scal_recommendation_list(scalrec_data) swof = scalrec_list2.interpolate(-0.5, h=0.2).SWOF() assert swof.count("SCAL recommendation") == 3 for tag in scalrec_data["TAG"]: assert swof.count(tag) == 1
def test_load_scalrec(): """Load a SATNUM range from xlsx""" testdir = Path(__file__).absolute().parent scalrec_data = PyscalFactory.load_relperm_df( testdir / "data/scal-pc-input-example.xlsx") scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data) wog_list = scalrec_list.interpolate(-0.3) with pytest.raises((AssertionError, ValueError)): scalrec_list.interpolate(-1.1) assert wog_list.pyscaltype == WaterOilGas with pytest.raises(TypeError): scalrec_list.dump_family_1() with pytest.raises(TypeError): scalrec_list.dump_family_2() with pytest.raises(TypeError): scalrec_list.SWOF() scalrec_list.interpolate([-1, 1, 0]) with pytest.raises((AssertionError, ValueError)): scalrec_list.interpolate([-1, 0, 1.1]) # Not enough interpolation parameters with pytest.raises(ValueError): scalrec_list.interpolate([-1, 1]) with pytest.raises(ValueError): scalrec_list.interpolate([-1, 1, 0, 0]) scalrec_list.interpolate(-1, 1) scalrec_list.interpolate(-1, [0, -1, 1]) with pytest.raises(ValueError): scalrec_list.interpolate(1, [-1, 1, 0, 0])
def test_create_lists(): """Test the factory methods for making pyscal lists""" testdir = Path(__file__).absolute().parent scalfile_xls = testdir / "data/scal-pc-input-example.xlsx" scaldata = PyscalFactory.load_relperm_df(scalfile_xls) scalrec_list = PyscalFactory.create_scal_recommendation_list(scaldata) assert len(scalrec_list) == 3 assert scalrec_list.pyscaltype == SCALrecommendation basecasedata = scaldata[scaldata["CASE"] == "base"].reset_index() relpermlist = PyscalFactory.create_pyscal_list(basecasedata) assert len(relpermlist) == 3 assert relpermlist.pyscaltype == WaterOilGas wo_list = PyscalFactory.create_pyscal_list( basecasedata.drop(["Lg", "Eg", "Tg", "Log", "Eog", "Tog"], axis="columns") ) assert len(wo_list) == 3 assert wo_list.pyscaltype == WaterOil go_list = PyscalFactory.create_pyscal_list( basecasedata.drop(["Lw", "Ew", "Tw", "Low", "Eow", "Tow"], axis="columns") ) assert len(go_list) == 3 assert go_list.pyscaltype == GasOil
def __init__( self, distribution_values: pd.DataFrame, ti2ci: pd.DataFrame, satnum: pd.DataFrame, phases: List, fast_pyscal: bool = False, interpolation_values: Optional[pd.DataFrame] = None, ): self._ti2ci: pd.DataFrame = ti2ci self._random_variables: List[ProbabilityDistribution] = [ LogUniformDistribution(row["minimum"], row["maximum"]) if row["loguniform"] else UniformDistribution(row["minimum"], row["maximum"]) for _, row in distribution_values.iterrows() ] self._unique_satnums: List[int] = list(distribution_values["satnum"].unique()) self._parameters: List[Parameter] = list( distribution_values["parameter"].unique() ) self._satnum: pd.DataFrame = satnum self._phases = phases self._interpolation_values: Optional[pd.DataFrame] = None self._scal_for_interp: Optional[PyscalList] = None if isinstance(interpolation_values, pd.DataFrame): self._interpolation_values = interpolation_values # self._rec will be indexed by SATNUM region, starting at 1 self._scal_for_interp = PyscalFactory.create_scal_recommendation_list( interpolation_values ) self._swof, self._sgof = self._check_parameters() self._fast_pyscal: bool = fast_pyscal
def test_create_lists(): """Test the factory methods for making pyscal lists""" if "__file__" in globals(): # Easen up copying test code into interactive sessions testdir = os.path.dirname(os.path.abspath(__file__)) else: testdir = os.path.abspath(".") scalfile_xls = testdir + "/data/scal-pc-input-example.xlsx" scaldata = PyscalFactory.load_relperm_df(scalfile_xls) scalrec_list = PyscalFactory.create_scal_recommendation_list(scaldata) assert len(scalrec_list) == 3 assert scalrec_list.pyscaltype == SCALrecommendation basecasedata = scaldata[scaldata["CASE"] == "base"].reset_index() relpermlist = PyscalFactory.create_pyscal_list(basecasedata) assert len(relpermlist) == 3 assert relpermlist.pyscaltype == WaterOilGas wo_list = PyscalFactory.create_pyscal_list( basecasedata.drop(["Lg", "Eg", "Tg", "Log", "Eog", "Tog"], axis="columns") ) assert len(wo_list) == 3 assert wo_list.pyscaltype == WaterOil go_list = PyscalFactory.create_pyscal_list( basecasedata.drop(["Lw", "Ew", "Tw", "Low", "Eow", "Tow"], axis="columns") ) assert len(go_list) == 3 assert go_list.pyscaltype == GasOil
def test_gaswater_scal(): """Test list of gas-water objects in scal recommendation""" dframe = pd.DataFrame( columns=["SATNUM", "CASE", "NW", "NG", "TAG"], data=[ [1, "pess", 2, 2, "thetag"], [1, "base", 3, 3, "thetag"], [1, "opt", 4, 4, "thetag"], ], ) pyscal_list = PyscalFactory.create_scal_recommendation_list( PyscalFactory.load_relperm_df(dframe), h=0.1) assert pyscal_list.pyscaltype == SCALrecommendation
def test_load_scalrec(tmpdir): """Load a SATNUM range from xlsx""" testdir = Path(__file__).absolute().parent scalrec_data = PyscalFactory.load_relperm_df( testdir / "data/scal-pc-input-example.xlsx") # Also check that we can read the old excel format scalrec_data_legacy_xls = PyscalFactory.load_relperm_df( testdir / "data/scal-pc-input-example.xls") pd.testing.assert_frame_equal(scalrec_data, scalrec_data_legacy_xls) scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data) wog_list = scalrec_list.interpolate(-0.3) with pytest.raises((AssertionError, ValueError)): scalrec_list.interpolate(-1.1) assert wog_list.pyscaltype == WaterOilGas with pytest.raises(TypeError): scalrec_list.dump_family_1() with pytest.raises(TypeError): scalrec_list.dump_family_2() with pytest.raises(TypeError): scalrec_list.SWOF() scalrec_list.interpolate([-1, 1, 0]) with pytest.raises((AssertionError, ValueError)): scalrec_list.interpolate([-1, 0, 1.1]) # Not enough interpolation parameters with pytest.raises(ValueError): scalrec_list.interpolate([-1, 1]) with pytest.raises(ValueError): scalrec_list.interpolate([-1, 1, 0, 0]) scalrec_list.interpolate(-1, 1) scalrec_list.interpolate(-1, [0, -1, 1]) with pytest.raises(ValueError): scalrec_list.interpolate(1, [-1, 1, 0, 0]) # Test slicing the scalrec to base, this is relevant for # API usage. base_data = scalrec_data[scalrec_data["CASE"] == "base"].drop("CASE", axis=1) PyscalFactory.load_relperm_df(base_data) # Ensure no errors. pyscal_list = PyscalFactory.create_pyscal_list(base_data) assert "LET" in pyscal_list.dump_family_1()
def test_gaswater_scal(): """Test list of gas-water objects in scal recommendation""" dframe = pd.DataFrame( columns=["SATNUM", "CASE", "NW", "NG", "TAG"], data=[ [1, "pess", 2, 2, "sometag"], [1, "base", 3, 3, "sometag"], [1, "opt", 4, 4, "sometag"], ], ) rec_list = PyscalFactory.create_scal_recommendation_list( PyscalFactory.load_relperm_df(dframe), h=0.1) assert rec_list.pyscaltype == SCALrecommendation assert rec_list[1].type == GasWater low_list = rec_list.interpolate(-1) str_fam2 = low_list.dump_family_2() assert "SCAL recommendation interpolation to -1" in str_fam2 assert "SGFN" in str_fam2 assert "SWFN" in str_fam2
def test_load_scalrec(): """Load a SATNUM range from xlsx""" if "__file__" in globals(): # Easen up copying test code into interactive sessions testdir = os.path.dirname(os.path.abspath(__file__)) else: testdir = os.path.abspath(".") scalrec_data = PyscalFactory.load_relperm_df( testdir + "/data/scal-pc-input-example.xlsx" ) scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data) wog_list = scalrec_list.interpolate(-0.3) with pytest.raises((AssertionError, ValueError)): scalrec_list.interpolate(-1.1) assert wog_list.pyscaltype == WaterOilGas with pytest.raises(TypeError): scalrec_list.dump_family_1() with pytest.raises(TypeError): scalrec_list.dump_family_2() with pytest.raises(TypeError): scalrec_list.SWOF() scalrec_list.interpolate([-1, 1, 0]) with pytest.raises((AssertionError, ValueError)): scalrec_list.interpolate([-1, 0, 1.1]) # Not enough interpolation parameters with pytest.raises(ValueError): scalrec_list.interpolate([-1, 1]) with pytest.raises(ValueError): scalrec_list.interpolate([-1, 1, 0, 0]) scalrec_list.interpolate(-1, 1) scalrec_list.interpolate(-1, [0, -1, 1]) with pytest.raises(ValueError): scalrec_list.interpolate(1, [-1, 1, 0, 0])
def test_twophase(): """Test interpolation for a two-phase setup water-oil""" # Triggers bug in pyscal <= 0.5.0 dframe = pd.DataFrame( columns=["SATNUM", "CASE", "NW", "NOW", "TAG"], data=[ [1, "pess", 1, 1, "thetag"], [1, "base", 2, 2, "thetag"], [1, "opt", 3, 3, "thetag"], ], ) pyscal_list = PyscalFactory.create_scal_recommendation_list( PyscalFactory.load_relperm_df(dframe)) pyscal_list = pyscal_list.interpolate(-0.5) # This works, but provides an error message that Gas. # The correct usage would be to call .SWOF(), but the pyscal # client calls dump_family_1 on two-phase problems. swof = pyscal_list.dump_family_1() assert "thetag" in swof assert "SWOF" in swof assert "SGOF" not in swof
def test_df(): """Test dataframe dumps""" testdir = Path(__file__).absolute().parent scalrec_data = PyscalFactory.load_relperm_df( testdir / "data/scal-pc-input-example.xlsx") scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data) wog_list = scalrec_list.interpolate(-0.3) # Test dataframe dumps: dframe = scalrec_list.df() assert "SG" in dframe assert "KRG" in dframe assert "KROG" in dframe assert "PCOW" in dframe if "PCOG" in dframe: # Allow PCOG to be included later. assert dframe["PCOG"].sum() == 0 assert "KRW" in dframe assert "KROW" in dframe assert "SATNUM" in dframe assert dframe["SATNUM"].min() == 1 assert len(dframe["SATNUM"].unique()) == len(scalrec_list) assert set(dframe["CASE"]) == set(["pess", "base", "opt"]) assert dframe["SATNUM"].max() == len(scalrec_list) if HAVE_ECL2DF: # Test using ecl2df to do the include file printing. First we need to # massage the dataframe into what ecl2df can handle: base_df_swof = (dframe.set_index("CASE").loc["base"][[ "SW", "KRW", "KROW", "PCOW", "SATNUM" ]].assign(KEYWORD="SWOF").dropna().reset_index(drop=True)) ecl_inc = ecl2df.satfunc.df2ecl(base_df_swof) dframe_from_inc = ecl2df.satfunc.df(ecl_inc) pd.testing.assert_frame_equal(base_df_swof, dframe_from_inc) # Test also SGOF base_df_sgof = (dframe.set_index("CASE").loc["base"][[ "SG", "KRG", "KROG", "SATNUM" ]].assign(KEYWORD="SGOF", PCOG=0.0).dropna().reset_index(drop=True)) ecl_inc = ecl2df.satfunc.df2ecl(base_df_sgof) dframe_from_inc = ecl2df.satfunc.df(ecl_inc) pd.testing.assert_frame_equal(base_df_sgof, dframe_from_inc, check_like=True) # WaterOilGasList: dframe = wog_list.df() assert "SG" in dframe assert "KRG" in dframe assert "KROG" in dframe assert "PCOW" in dframe assert "PCOG" in dframe # This gets included through interpolation assert "KRW" in dframe assert "KROW" in dframe assert "SATNUM" in dframe assert dframe["SATNUM"].min() == 1 assert len(dframe["SATNUM"].unique()) == len(wog_list) assert "CASE" not in dframe assert dframe["SATNUM"].max() == len(wog_list) # WaterOil list input_dframe = pd.DataFrame(columns=["SATNUM", "Nw", "Now"], data=[[1, 2, 2]]) relperm_data = PyscalFactory.load_relperm_df(input_dframe) p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2) dframe = p_list.df() assert "SW" in dframe assert "KRW" in dframe assert "KROW" in dframe assert "PCOW" not in dframe # to be interpreted as zero assert "SATNUM" in dframe assert len(dframe.columns) == 4 assert not dframe.empty # GasOil list input_dframe = pd.DataFrame(columns=["SATNUM", "Ng", "Nog"], data=[[1, 2, 2]]) relperm_data = PyscalFactory.load_relperm_df(input_dframe) p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2) dframe = p_list.df() assert "SG" in dframe assert "KRG" in dframe assert "KROG" in dframe assert "PCOG" not in dframe # to be interpreted as zero assert "SATNUM" in dframe assert len(dframe.columns) == 4 assert not dframe.empty
def pyscal_main( parametertable, verbose=False, output="relperm.inc", delta_s=None, int_param_wo=None, int_param_go=None, sheet_name=None, slgof=False, family2=False, ): """A "main()" method not relying on argparse. This can be used for testing, and also by an ERT forward model, e.g. in semeio (github.com/equinor/semeio) Args: parametertable (string): Filename (CSV or XLSX) to load verbose (bool): verbose or not output (string): Output filename delta_s (float): Saturation step-length int_param_wo (list): Interpolation params for wateroil int_param_go (list): Interpolation params for gasoil sheet_name (string): Which sheet in XLSX file slgof (bool): Use SLGOF family2 (bool): Dump family 2 keywords """ if verbose: # Fixme: Logging level is not inherited in called modules. logger.setLevel(logging.INFO) if sheet_name: logger.info("Loading data from %s and sheetname %s", parametertable, sheet_name) else: logger.info("Loading data from %s", parametertable) scalinput_df = PyscalFactory.load_relperm_df(parametertable, sheet_name=sheet_name) logger.info("Input data:\n%s", scalinput_df.to_string(index=False)) if int_param_go is not None and int_param_wo is None: logger.error("Don't use int_param_go alone, only int_param_wo") raise ValueError if "SATNUM" not in scalinput_df: logger.error("There is no column called SATNUM in the input data") raise ValueError if "CASE" in scalinput_df: # Then we should do interpolation if int_param_wo is None: logger.error("No interpolation parameters provided") raise ValueError scalrec_list = PyscalFactory.create_scal_recommendation_list( scalinput_df, h=delta_s) logger.info( "Interpolating, wateroil=%s, gasoil=%s", str(int_param_wo), str(int_param_go), ) wog_list = scalrec_list.interpolate(int_param_wo, int_param_go, h=delta_s) else: wog_list = PyscalFactory.create_pyscal_list( scalinput_df, h=delta_s) # can be both water-oil, water-oil-gas, or gas-water if (int_param_wo is not None or int_param_go is not None) and "CASE" not in scalinput_df: logger.error( "Interpolation parameter provided but no CASE column in input data" ) raise ValueError if not family2: logger.info("Generating family 1 keywords.") if output == "-": print(wog_list.dump_family_1(slgof=slgof)) else: wog_list.dump_family_1(filename=output, slgof=slgof) print("Written to " + output) else: logger.info("Generating family 2 keywords") if output == "-": print(wog_list.dump_family_2()) else: wog_list.dump_family_2(filename=output) print("Written to " + output)
def test_fast(): """Test fast mode for SCALrecommendation""" testdir = Path(__file__).absolute().parent scalrec_data = PyscalFactory.load_relperm_df( testdir / "data/scal-pc-input-example.xlsx") scalrec_list_fast = PyscalFactory.create_scal_recommendation_list( scalrec_data, fast=True) for item in scalrec_list_fast: assert item.fast assert item.low.fast assert item.base.fast assert item.high.fast wog_list_fast = scalrec_list_fast.interpolate(-0.5) for item in wog_list_fast: assert item.fast # WaterOilGas list dframe = pd.DataFrame( columns=["SATNUM", "nw", "now", "ng", "nog"], data=[ [1, 2, 2, 2, 2], [2, 2, 2, 2, 2], [3, 2, 2, 2, 2], ], ) relperm_data = PyscalFactory.load_relperm_df(dframe) p_list_fast = PyscalFactory.create_pyscal_list(relperm_data, h=0.2, fast=True) for item in p_list_fast: assert item.fast # GasOil list input_dframe = dframe[["SATNUM", "ng", "nog"]].copy() relperm_data = PyscalFactory.load_relperm_df(input_dframe) p_list_fast = PyscalFactory.create_pyscal_list(relperm_data, h=0.2, fast=True) for item in p_list_fast: assert item.fast # WaterOil list input_dframe = dframe[["SATNUM", "nw", "now"]].copy() relperm_data = PyscalFactory.load_relperm_df(input_dframe) p_list_fast = PyscalFactory.create_pyscal_list(relperm_data, h=0.2, fast=True) for item in p_list_fast: assert item.fast # GasWater list input_dframe = dframe[["SATNUM", "nw", "ng"]].copy() relperm_data = PyscalFactory.load_relperm_df(input_dframe) p_list_fast = PyscalFactory.create_pyscal_list(relperm_data, h=0.2, fast=True) for item in p_list_fast: assert item.fast # Testing with "fast" column in dataframe # Currently the choice is to only implement fast mode # as a global option. This column should do nothing now. # One could imagine it implemented # for individual SATNUM regions at a later stage dframe = pd.DataFrame( columns=["SATNUM", "nw", "now", "ng", "nog", "fast"], data=[ [1, 2, 2, 2, 2, True], [2, 2, 2, 2, 2, False], [3, 2, 2, 2, 2, True], ], ) relperm_data = PyscalFactory.load_relperm_df(dframe) assert "fast" in relperm_data p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2) for item in p_list: assert not item.fast
def load_scal_recommendation( scalfile: Path, sheet_name: Optional[Union[str, int, list]] = None ) -> pd.DataFrame: return PyscalFactory.create_scal_recommendation_list( PyscalFactory.load_relperm_df(str(scalfile), sheet_name) ).df()