def test_wo_fromtable_multiindex(): """Test that we accept multiindex dataframes, (but a warning will be issued)""" # Test an example dataframe that easily gets sent in from ecl2df.satfunc: df1 = pd.DataFrame( columns=["KEYWORD", "SATNUM", "SW", "KRW", "KROW", "PC"], data=[ ["SWOF", 1, 0, 0, 1, 2], ["SWOF", 1, 0.5, 0.5, 0.5, 1], ["SWOF", 1, 1, 1, 0, 0], ], ).set_index(["KEYWORD", "SATNUM"]) # Check that we have a MultiIndex: assert len(df1.index.names) == 2 wateroil = WaterOil(h=0.1) wateroil.add_fromtable(df1, swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PC") assert "krw" in wateroil.table.columns assert "krow" in wateroil.table.columns assert "pc" in wateroil.table.columns check_table(wateroil.table)
def test_linear_input(h, sw_mid): """Linear input creates difficulties with sorw, which is used in add_fromtable(). The intention of the test is to avoid crashes when add_fromtable(). estimate_sorw() is unreliable on linear input, and returns 0 or 1 on the given test dataset. Correctness of sorw should not be needed for add_fromtable(). This tests fails in pyscal v0.7.7""" dframe = pd.DataFrame( columns=["SW", "KRW", "KROW", "PC"], data=[[sw, sw, 1 - sw, 1 - sw] for sw in [0, sw_mid, 1.0]], ) wateroil = WaterOil(h=h, swl=0) wateroil.add_fromtable(dframe) assert wateroil.selfcheck() # GasOil did not fail in v0.7.7, but test anyway: gasoil = GasOil(h=h, swl=0) gasoil.add_fromtable(dframe, sgcolname="SW", krgcolname="KRW", krogcolname="KROW", pccolname="PCOW") assert gasoil.selfcheck()
def test_wo_fromtable_simple(): """Test loading a simple curve from a table""" df1 = pd.DataFrame(columns=["SW", "KRW", "KROW", "PC"], data=[[0, 0, 1, 2], [1, 1, 0, 0]]) wateroil = WaterOil(h=0.1) # With wrong names: with pytest.raises(ValueError): # Here we also get a deprecation warning wateroil.add_oilwater_fromtable(df1) # Set names: wateroil.add_fromtable(df1, swcolname="SW") # This didn't do anything, because we did not provide any relperm names assert "krw" not in wateroil.table.columns assert "krow" not in wateroil.table.columns assert "pc" not in wateroil.table.columns # Try again: wateroil.add_fromtable(df1, swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PC") assert "krw" in wateroil.table.columns assert "krow" in wateroil.table.columns assert "pc" in wateroil.table.columns check_table(wateroil.table)
def test_ow_fromtable_h(h): df1 = pd.DataFrame( columns=["Sw", "krw", "krow", "pcow"], data=[[0.15, 0, 1, 3], [0.89, 1, 0, 0.1], [1, 1, 0, 0]], ) wo = WaterOil(h=h, swl=0.15, sorw=1 - 0.89) wo.add_fromtable(df1) check_wo_table(wo.table)
def test_wo_fromtable_h(h): """Test making curves from tabular data with random stepsize h""" df1 = pd.DataFrame( columns=["Sw", "krw", "krow", "pcow"], data=[[0.15, 0, 1, 3], [0.89, 1, 0, 0.1], [1, 1, 0, 0]], ) wateroil = WaterOil(h=h, swl=0.15, sorw=1 - 0.89) wateroil.add_fromtable(df1) check_table(wateroil.table)
def test_fromtable_types(): """Test loading from a table with incorrect types""" # This frame is valid, but the type was wrong. This # can happen if data is via CSV files, and some other rows # ruin the numerical interpretation of a column. df1 = pd.DataFrame( columns=["SW", "KRW", "KROW", "PC"], data=[["0", "0", "1", "2"], ["1", "1", "0", "0"]], ) wateroil = WaterOil(h=0.1) wateroil.add_fromtable(df1, swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PC") assert "krw" in wateroil.table.columns assert "krow" in wateroil.table.columns assert "pc" in wateroil.table.columns check_table(wateroil.table) gasoil = GasOil(h=0.1) gasoil.add_fromtable(df1, sgcolname="SW", krgcolname="KRW", krogcolname="KROW", pccolname="PC") assert "krg" in gasoil.table.columns assert "krog" in gasoil.table.columns assert "pc" in gasoil.table.columns check_table(gasoil.table) # But this should not make sense. df2 = pd.DataFrame( columns=["SW", "KRW", "KROW", "PC"], data=[["0", dict(foo="bar"), "1", "2"], ["1", "1", "0", "0"]], ) wateroil = WaterOil(h=0.1) with pytest.raises((ValueError, TypeError)): wateroil.add_fromtable(df2, swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PC") gasoil = GasOil(h=0.1) with pytest.raises((ValueError, TypeError)): gasoil.add_fromtable(df2, sgcolname="SW", krgcolname="KRW", krogcolname="KROW", pccolname="PC")
def test_wo_fromtable_simple(): """Test loading a simple curve from a table""" df1 = pd.DataFrame(columns=["SW", "KRW", "KROW", "PC"], data=[[0, 0, 1, 2], [1, 1, 0, 0]]) wateroil = WaterOil(h=0.1) # With wrong names: with pytest.raises(ValueError): wateroil.add_fromtable(df1, swcolname="sw") # Set names: wateroil.add_fromtable(df1, swcolname="SW", pccolname="PC") assert "KRW" in wateroil.table.columns assert "KROW" in wateroil.table.columns assert "PC" in wateroil.table.columns assert sum(wateroil.table["KRW"]) > 0 assert sum(wateroil.table["KROW"]) > 0 assert np.isclose(sum(wateroil.table["PC"]), 11) # Linearly increasing PC check_table(wateroil.table)
def test_interpolations_wo_fromtable(): """Analog test as test_interpolations_go_fromtable(). Pyscal 0.6.1 and earlier fails this test sorw. """ base = pd.DataFrame( columns=["Sw", "krw", "krow"], data=[ [0.0, 0.0, 1.0], [0.1, 0.0, 1.0], [0.2, 0.0, 1.0], # swcr [0.3, 0.1, 0.9], [0.8, 0.8, 0.0], # sorw [0.9, 0.9, 0.0], [1.0, 1.0, 0.0], ], ) opt = pd.DataFrame( columns=["Sw", "krw", "krow"], data=[ [0.0, 0.0, 1.0], [0.1, 0.0, 1.0], [0.3, 0.0, 1.0], [0.4, 0.1, 0.2], # swcr [0.9, 0.9, 0.0], # sorw [0.95, 0.95, 0.0], [1.0, 1.0, 0.0], ], ) wo_base = WaterOil(h=0.01) wo_base.add_fromtable(base) assert np.isclose(wo_base.estimate_swcr(), 0.2) assert np.isclose(wo_base.estimate_sorw(), 0.2) wo_opt = WaterOil(h=0.01) wo_opt.add_fromtable(opt) assert np.isclose(wo_opt.estimate_swcr(), 0.3) assert np.isclose(wo_opt.estimate_sorw(), 0.1) wo_ip = interpolate_wo(wo_base, wo_opt, 0.5, h=0.01) assert np.isclose(wo_ip.estimate_swcr(), 0.25) assert np.isclose(wo_ip.estimate_sorw(), 0.15)
def test_wo_fromtable_problems(): """Test wateroil from tables with problematic data""" # Implicit swl and sorw in the input, how do we handle that? df1 = pd.DataFrame( columns=["Sw", "krw", "krow", "pcow"], data=[[0.15, 0, 1, 3], [0.89, 1, 0, 0.1], [1, 1, 0, 0]], ) # With default object: wateroil = WaterOil(h=0.1) with pytest.raises(ValueError): wateroil.add_fromtable(df1) # This results in krw and krow overshooting 0 and 1 # Fix left endpoint: wateroil = WaterOil(h=0.1, swl=df1["Sw"].min()) wateroil.add_fromtable(df1) # The table is now valid, but we did not preserve the 0.89 point check_table(wateroil.table) # If we also tell the WaterOil object about sorw, we are guaranteed # to have it expclitly included: wateroil = WaterOil(h=0.1, swl=df1["Sw"].min(), sorw=1 - 0.89) wateroil.add_fromtable(df1) check_table(wateroil.table) # For low enough h, this will however NOT matter. df2 = pd.DataFrame(columns=["Sw", "KRW", "KROW", "PCOW"], data=[[0, -0.01, 1, 0], [1, 1, 0, 0]]) wateroil = WaterOil(h=0.1) with pytest.raises(ValueError): # Should say krw is negative wateroil.add_fromtable(df2, krwcolname="KRW") df3 = pd.DataFrame( columns=["Sw", "KRW", "KROW", "PCOW"], data=[[0, 0, 1, 0], [1, 1.000000001, 0, 0]], ) wateroil = WaterOil(h=0.1) with pytest.raises(ValueError): # Should say krw is above 1.0 wateroil.add_fromtable(df3, krwcolname="KRW")
def test_ow_fromtable_problems(): # Implicit swl and sorw in the input, how do we handle that? df1 = pd.DataFrame( columns=["Sw", "krw", "krow", "pcow"], data=[[0.15, 0, 1, 3], [0.89, 1, 0, 0.1], [1, 1, 0, 0]], ) # With default object: wo = WaterOil(h=0.1) with pytest.raises(ValueError): wo.add_fromtable(df1) # This results in krw and krow overshooting 0 and 1 # Fix left endpoint: wo = WaterOil(h=0.1, swl=df1["Sw"].min()) wo.add_fromtable(df1) # The table is now valid, but we did not preserve the 0.89 point check_wo_table(wo.table) # If we also tell the WaterOil object about sorw, we are guaranteed # to have it expclitly included: wo = WaterOil(h=0.1, swl=df1["Sw"].min(), sorw=1 - 0.89) wo.add_fromtable(df1) check_wo_table(wo.table)
def test_wo_fromtable_problems(): """Test wateroil from tables with problematic data""" # With default object: df1 = pd.DataFrame( columns=["SW", "KRW", "KROW", "PCOW"], data=[[0.15, 0, 1, 3], [0.89, 1, 0, 0.1], [1, 1, 0, 0]], ) # With default object: wateroil = WaterOil(h=0.1) with pytest.raises(ValueError): wateroil.add_fromtable(df1) # This results in krw and krow overshooting 0 and 1 # Fix left endpoint: wateroil = WaterOil(h=0.1, swl=df1["SW"].min()) wateroil.add_fromtable(df1) # The table is now valid, but we did not preserve the 0.89 point check_table(wateroil.table) # If we also tell the WaterOil object about sorw, we are guaranteed # to have it expclitly included: wateroil = WaterOil(h=0.1, swl=df1["SW"].min(), sorw=1 - 0.89) wateroil.add_fromtable(df1) check_table(wateroil.table)
def test_wo_invalidcurves(): """Test what happens when we give in invalid data""" # Sw data not ordered: krw1 = pd.DataFrame(columns=["Sw", "krw"], data=[[0.15, 0], [0.1, 1], [1, 1]]) wateroil = WaterOil(swl=krw1["Sw"].min(), h=0.1) with pytest.raises(ValueError): # pchip-interpolator raises this error; # x coordinates are not in increasing order wateroil.add_fromtable(krw1, krwcolname="krw") krw2 = pd.DataFrame(columns=["Sw", "krw"], data=[[0.15, 0], [0.4, 0.6], [0.6, 0.4], [1, 1]]) wateroil = WaterOil(swl=krw2["Sw"].min(), h=0.1) with pytest.raises(ValueError): # Should get notified that krw is not monotonous wateroil.add_fromtable(krw2, krwcolname="krw") krow2 = pd.DataFrame(columns=["Sw", "krow"], data=[[0.15, 1], [0.4, 0.4], [0.6, 0.6], [1, 0]]) wateroil = WaterOil(swl=krow2["Sw"].min(), h=0.1) with pytest.raises(ValueError): # Should get notified that krow is not monotonous wateroil.add_fromtable(krow2, krowcolname="krow") pc2 = pd.DataFrame(columns=["Sw", "pc"], data=[[0.15, 1], [0.4, 0.4], [0.6, 0.6], [1, 0]]) wateroil = WaterOil(swl=pc2["Sw"].min(), h=0.1) with pytest.raises(ValueError): # Should get notified that pc is not monotonous wateroil.add_fromtable(pc2, pccolname="pc") pc3 = pd.DataFrame( columns=["Sw", "pc"], data=[[0, np.inf], [0.1, 1], [0.4, 0.4], [0.6, 0.2], [1, 0]], ) wateroil = WaterOil(swl=pc3["Sw"].min(), h=0.1) # Will get warning that infinite numbers are ignored. # In this case the extrapolation is quite bad. wateroil.add_fromtable(pc3, pccolname="pc") # But when we later set swl larger, then we should # not bother about the infinity: wateroil = WaterOil(swl=0.1, h=0.1) wateroil.add_fromtable(pc3, pccolname="pc") assert np.isclose(wateroil.table["pc"].max(), pc3.iloc[1:]["pc"].max()) # Choosing endpoint slightly to the left of 0.1 incurs # extrapolation. A warning will be given wateroil = WaterOil(swl=0.05, h=0.1) wateroil.add_fromtable(pc3, pccolname="pc") # Inequality due to extrapolation: assert wateroil.table["pc"].max() > pc3.iloc[1:]["pc"].max()
def test_wo_singlecolumns(): """Test that we can load single columns from individual dataframes""" krw = pd.DataFrame(columns=["Sw", "krw"], data=[[0.15, 0], [0.89, 1], [1, 1]]) krow = pd.DataFrame(columns=["Sw", "krow"], data=[[0.15, 1], [0.89, 0], [1, 0]]) pc1 = pd.DataFrame(columns=["Sw", "pcow"], data=[[0.15, 3], [0.89, 0.1], [1, 0]]) wateroil = WaterOil(h=0.1, swl=0.15, sorw=1 - 0.89) wateroil.add_fromtable(krw) assert "krw" in wateroil.table assert "krow" not in wateroil.table wateroil.add_fromtable(krow) assert "krow" in wateroil.table wateroil.add_fromtable(pc1) assert "pc" in wateroil.table # We want to allow a pc dataframe where sw starts from zero: # then should not preserve pc(sw=0) pc2 = pd.DataFrame(columns=["Sw", "pcow"], data=[[0, 3], [0.5, 0.1], [1, 0]]) wateroil.add_fromtable(pc2) assert "pc" in wateroil.table assert wateroil.table["sw"].min() == 0.15 assert wateroil.table["pc"].max() < 3 # But we should refuse a pc dataframe not covering our sw range: wateroil = WaterOil(h=0.1, swl=0) with pytest.raises(ValueError): pc3 = pd.DataFrame(columns=["Sw", "pcow"], data=[[0.1, 3], [0.5, 0.1], [1, 0]]) wateroil.add_fromtable(pc3) with pytest.raises(ValueError): pc3 = pd.DataFrame(columns=["Sw", "pcow"], data=[[0, 3], [0.5, 0.1]]) wateroil.add_fromtable(pc3) # Disallow non-monotonous capillary pressure: pc4 = pd.DataFrame(columns=["Sw", "pcow"], data=[[0.15, 3], [0.89, 0.1], [1, 0.1]]) with pytest.raises(ValueError): wateroil.add_fromtable(pc4) # But if capillary pressure is all zero, accept it: pc5 = pd.DataFrame(columns=["Sw", "pcow"], data=[[0, 0], [1, 0]]) wateroil = WaterOil(h=0.1) wateroil.add_fromtable(pc5) assert wateroil.table["pc"].sum() == 0
def test_wo_from_table_exceptions(dframe, swl, exception, message): wateroil = WaterOil(h=0.1, swl=swl) with pytest.raises(exception, match=message): wateroil.add_fromtable(dframe)