From 84ed027a4bb8598d51934b0fb133fa74ddefdc57 Mon Sep 17 00:00:00 2001 From: Meghan Jones Date: Thu, 20 May 2021 11:01:20 -0400 Subject: [PATCH 1/6] Refactor blockm to use virtualfile_from_data and improve i/o --- pygmt/src/blockm.py | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/pygmt/src/blockm.py b/pygmt/src/blockm.py index a9cf45f4616..0e4e511128e 100644 --- a/pygmt/src/blockm.py +++ b/pygmt/src/blockm.py @@ -3,12 +3,9 @@ """ import pandas as pd from pygmt.clib import Session -from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import ( GMTTempFile, build_arg_string, - data_kind, - dummy_context, fmt_docstring, kwargs_to_strings, use_alias, @@ -41,21 +38,12 @@ def _blockm(block_method, table, outfile, **kwargs): set by ``outfile``) """ - kind = data_kind(table) with GMTTempFile(suffix=".csv") as tmpfile: with Session() as lib: - if kind == "matrix": - if not hasattr(table, "values"): - raise GMTInvalidInput(f"Unrecognized data type: {type(table)}") - file_context = lib.virtualfile_from_matrix(table.values) - elif kind == "file": - if outfile is None: - raise GMTInvalidInput("Please pass in a str to 'outfile'") - file_context = dummy_context(table) - else: - raise GMTInvalidInput(f"Unrecognized data type: {type(table)}") - - with file_context as infile: + # Choose how data will be passed into the module + table_context = lib.virtualfile_from_data(check_kind="vector", data=table) + # Run blockm* on data table + with table_context as infile: if outfile is None: outfile = tmpfile.name arg_str = " ".join([infile, build_arg_string(kwargs), "->" + outfile]) @@ -63,7 +51,11 @@ def _blockm(block_method, table, outfile, **kwargs): # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame - result = pd.read_csv(tmpfile.name, sep="\t", names=table.columns) + try: + column_names = table.columns.to_list() + result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) + except AttributeError: # 'str' object has no attribute 'columns' + result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">") elif outfile != tmpfile.name: # return None if outfile set, output in outfile result = None @@ -110,8 +102,7 @@ def blockmean(table, outfile=None, **kwargs): Specify the region of interest. outfile : str - Required if ``table`` is a file. The file name for the output ASCII - file. + The file name for the output ASCII file. {V} {a} @@ -171,8 +162,7 @@ def blockmedian(table, outfile=None, **kwargs): Specify the region of interest. outfile : str - Required if ``table`` is a file. The file name for the output ASCII - file. + The file name for the output ASCII file. {V} {a} From 1410568d3675d9ab2f8b94bfa09d3e2684d7fea7 Mon Sep 17 00:00:00 2001 From: Meghan Jones Date: Thu, 20 May 2021 11:02:09 -0400 Subject: [PATCH 2/6] Update tests from blockm refactoring --- pygmt/tests/test_blockmean.py | 21 ++++++++++++++------- pygmt/tests/test_blockmedian.py | 19 +++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/pygmt/tests/test_blockmean.py b/pygmt/tests/test_blockmean.py index 76adb922f6b..d2ca96f61f7 100644 --- a/pygmt/tests/test_blockmean.py +++ b/pygmt/tests/test_blockmean.py @@ -26,16 +26,19 @@ def test_blockmean_input_dataframe(): return output -def test_blockmean_wrong_kind_of_input_table_matrix(): +def test_blockmean_input_table_matrix(): """ Run blockmean using table input that is not a pandas.DataFrame but still a matrix. """ dataframe = load_sample_bathymetry() - invalid_table = dataframe.values - assert data_kind(invalid_table) == "matrix" - with pytest.raises(GMTInvalidInput): - blockmean(table=invalid_table, spacing="5m", region=[245, 255, 20, 30]) + table = dataframe.values + output = blockmean(table=table, spacing="5m", region=[245, 255, 20, 30]) + assert isinstance(output, pd.DataFrame) + assert output.shape == (5849, 3) + npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) + + return output def test_blockmean_wrong_kind_of_input_table_grid(): @@ -74,5 +77,9 @@ def test_blockmean_without_outfile_setting(): """ Run blockmean by not passing in outfile parameter setting. """ - with pytest.raises(GMTInvalidInput): - blockmean(table="@tut_ship.xyz", spacing="5m", region=[245, 255, 20, 30]) + output = blockmean(table="@tut_ship.xyz", spacing="5m", region=[245, 255, 20, 30]) + assert isinstance(output, pd.DataFrame) + assert output.shape == (5849, 3) + npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) + + return output diff --git a/pygmt/tests/test_blockmedian.py b/pygmt/tests/test_blockmedian.py index ff0dd1cf059..7e7c9582b0d 100644 --- a/pygmt/tests/test_blockmedian.py +++ b/pygmt/tests/test_blockmedian.py @@ -32,10 +32,13 @@ def test_blockmedian_wrong_kind_of_input_table_matrix(): a matrix. """ dataframe = load_sample_bathymetry() - invalid_table = dataframe.values - assert data_kind(invalid_table) == "matrix" - with pytest.raises(GMTInvalidInput): - blockmedian(table=invalid_table, spacing="5m", region=[245, 255, 20, 30]) + table = dataframe.values + output = blockmedian(table=table, spacing="5m", region=[245, 255, 20, 30]) + assert isinstance(output, pd.DataFrame) + assert output.shape == (5849, 3) + npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) + + return output def test_blockmedian_wrong_kind_of_input_table_grid(): @@ -74,5 +77,9 @@ def test_blockmedian_without_outfile_setting(): """ Run blockmedian by not passing in outfile parameter setting. """ - with pytest.raises(GMTInvalidInput): - blockmedian(table="@tut_ship.xyz", spacing="5m", region=[245, 255, 20, 30]) + output = blockmedian(table="@tut_ship.xyz", spacing="5m", region=[245, 255, 20, 30]) + assert isinstance(output, pd.DataFrame) + assert output.shape == (5849, 3) + npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) + + return output From 55d88a4568897c1d899dcf5979480e8dca8e2228 Mon Sep 17 00:00:00 2001 From: Meghan Jones Date: Thu, 20 May 2021 11:07:39 -0400 Subject: [PATCH 3/6] Format code --- pygmt/tests/test_blockmedian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/tests/test_blockmedian.py b/pygmt/tests/test_blockmedian.py index 7e7c9582b0d..4d4dcb3005d 100644 --- a/pygmt/tests/test_blockmedian.py +++ b/pygmt/tests/test_blockmedian.py @@ -37,7 +37,7 @@ def test_blockmedian_wrong_kind_of_input_table_matrix(): assert isinstance(output, pd.DataFrame) assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) - + return output From fb0d9a0d9bdc3e1e4e4a13f36cffa74a84eaf58b Mon Sep 17 00:00:00 2001 From: Meghan Jones Date: Fri, 21 May 2021 10:19:26 -0400 Subject: [PATCH 4/6] Remove return statements from blockm tests --- pygmt/tests/test_blockmean.py | 8 -------- pygmt/tests/test_blockmedian.py | 8 -------- 2 files changed, 16 deletions(-) diff --git a/pygmt/tests/test_blockmean.py b/pygmt/tests/test_blockmean.py index d2ca96f61f7..f427d7a18cd 100644 --- a/pygmt/tests/test_blockmean.py +++ b/pygmt/tests/test_blockmean.py @@ -23,8 +23,6 @@ def test_blockmean_input_dataframe(): assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) - return output - def test_blockmean_input_table_matrix(): """ @@ -38,8 +36,6 @@ def test_blockmean_input_table_matrix(): assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) - return output - def test_blockmean_wrong_kind_of_input_table_grid(): """ @@ -70,8 +66,6 @@ def test_blockmean_input_filename(): assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) - return output - def test_blockmean_without_outfile_setting(): """ @@ -81,5 +75,3 @@ def test_blockmean_without_outfile_setting(): assert isinstance(output, pd.DataFrame) assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) - - return output diff --git a/pygmt/tests/test_blockmedian.py b/pygmt/tests/test_blockmedian.py index 4d4dcb3005d..54e7a5cf045 100644 --- a/pygmt/tests/test_blockmedian.py +++ b/pygmt/tests/test_blockmedian.py @@ -23,8 +23,6 @@ def test_blockmedian_input_dataframe(): assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) - return output - def test_blockmedian_wrong_kind_of_input_table_matrix(): """ @@ -38,8 +36,6 @@ def test_blockmedian_wrong_kind_of_input_table_matrix(): assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) - return output - def test_blockmedian_wrong_kind_of_input_table_grid(): """ @@ -70,8 +66,6 @@ def test_blockmedian_input_filename(): assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) - return output - def test_blockmedian_without_outfile_setting(): """ @@ -81,5 +75,3 @@ def test_blockmedian_without_outfile_setting(): assert isinstance(output, pd.DataFrame) assert output.shape == (5849, 3) npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) - - return output From cf7383741156a4a3664ed687b81daf1e86700a64 Mon Sep 17 00:00:00 2001 From: Meghan Jones Date: Fri, 21 May 2021 18:40:01 -0400 Subject: [PATCH 5/6] Update blockm tests to use pytest.fixture --- pygmt/tests/test_blockmean.py | 17 +++++++++++------ pygmt/tests/test_blockmedian.py | 17 +++++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/pygmt/tests/test_blockmean.py b/pygmt/tests/test_blockmean.py index f427d7a18cd..b787fda0ffc 100644 --- a/pygmt/tests/test_blockmean.py +++ b/pygmt/tests/test_blockmean.py @@ -12,11 +12,18 @@ from pygmt.helpers import GMTTempFile, data_kind -def test_blockmean_input_dataframe(): +@pytest.fixture(scope="module", name="dataframe") +def fixture_dataframe(): + """ + Load the grid data from the sample earth_relief file. + """ + return load_sample_bathymetry() + + +def test_blockmean_input_dataframe(dataframe): """ Run blockmean by passing in a pandas.DataFrame as input. """ - dataframe = load_sample_bathymetry() output = blockmean(table=dataframe, spacing="5m", region=[245, 255, 20, 30]) assert isinstance(output, pd.DataFrame) assert all(dataframe.columns == output.columns) @@ -24,12 +31,11 @@ def test_blockmean_input_dataframe(): npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) -def test_blockmean_input_table_matrix(): +def test_blockmean_input_table_matrix(dataframe): """ Run blockmean using table input that is not a pandas.DataFrame but still a matrix. """ - dataframe = load_sample_bathymetry() table = dataframe.values output = blockmean(table=table, spacing="5m", region=[245, 255, 20, 30]) assert isinstance(output, pd.DataFrame) @@ -37,12 +43,11 @@ def test_blockmean_input_table_matrix(): npt.assert_allclose(output.iloc[0], [245.888877, 29.978707, -384.0]) -def test_blockmean_wrong_kind_of_input_table_grid(): +def test_blockmean_wrong_kind_of_input_table_grid(dataframe): """ Run blockmean using table input that is not a pandas.DataFrame or file but a grid. """ - dataframe = load_sample_bathymetry() invalid_table = dataframe.bathymetry.to_xarray() assert data_kind(invalid_table) == "grid" with pytest.raises(GMTInvalidInput): diff --git a/pygmt/tests/test_blockmedian.py b/pygmt/tests/test_blockmedian.py index 54e7a5cf045..cde1ce8d644 100644 --- a/pygmt/tests/test_blockmedian.py +++ b/pygmt/tests/test_blockmedian.py @@ -12,11 +12,18 @@ from pygmt.helpers import GMTTempFile, data_kind -def test_blockmedian_input_dataframe(): +@pytest.fixture(scope="module", name="dataframe") +def fixture_dataframe(): + """ + Load the grid data from the sample earth_relief file. + """ + return load_sample_bathymetry() + + +def test_blockmedian_input_dataframe(dataframe): """ Run blockmedian by passing in a pandas.DataFrame as input. """ - dataframe = load_sample_bathymetry() output = blockmedian(table=dataframe, spacing="5m", region=[245, 255, 20, 30]) assert isinstance(output, pd.DataFrame) assert all(dataframe.columns == output.columns) @@ -24,12 +31,11 @@ def test_blockmedian_input_dataframe(): npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) -def test_blockmedian_wrong_kind_of_input_table_matrix(): +def test_blockmedian_wrong_kind_of_input_table_matrix(dataframe): """ Run blockmedian using table input that is not a pandas.DataFrame but still a matrix. """ - dataframe = load_sample_bathymetry() table = dataframe.values output = blockmedian(table=table, spacing="5m", region=[245, 255, 20, 30]) assert isinstance(output, pd.DataFrame) @@ -37,12 +43,11 @@ def test_blockmedian_wrong_kind_of_input_table_matrix(): npt.assert_allclose(output.iloc[0], [245.88819, 29.97895, -385.0]) -def test_blockmedian_wrong_kind_of_input_table_grid(): +def test_blockmedian_wrong_kind_of_input_table_grid(dataframe): """ Run blockmedian using table input that is not a pandas.DataFrame or file but a grid. """ - dataframe = load_sample_bathymetry() invalid_table = dataframe.bathymetry.to_xarray() assert data_kind(invalid_table) == "grid" with pytest.raises(GMTInvalidInput): From 148ba6dd4ba41f10e224710615664ee17bf54730 Mon Sep 17 00:00:00 2001 From: Meghan Jones Date: Sat, 22 May 2021 17:00:47 -0400 Subject: [PATCH 6/6] Use table-like in blockm docstrings --- pygmt/src/blockm.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pygmt/src/blockm.py b/pygmt/src/blockm.py index 0e4e511128e..d2951b7be69 100644 --- a/pygmt/src/blockm.py +++ b/pygmt/src/blockm.py @@ -87,10 +87,10 @@ def blockmean(table, outfile=None, **kwargs): Parameters ---------- - table : pandas.DataFrame or str - Either a pandas dataframe with (x, y, z) or (longitude, latitude, - elevation) values in the first three columns, or a file name to an - ASCII data table. + table : str or {table-like} + Pass in (x, y, z) or (longitude, latitude, elevation) values by + providing a file name to an ASCII data table, a 2D + {table-classes}. spacing : str *xinc*\[\ *unit*\][**+e**\|\ **n**] @@ -147,10 +147,10 @@ def blockmedian(table, outfile=None, **kwargs): Parameters ---------- - table : pandas.DataFrame or str - Either a pandas dataframe with (x, y, z) or (longitude, latitude, - elevation) values in the first three columns, or a file name to an - ASCII data table. + table : str or {table-like} + Pass in (x, y, z) or (longitude, latitude, elevation) values by + providing a file name to an ASCII data table, a 2D + {table-classes}. spacing : str *xinc*\[\ *unit*\][**+e**\|\ **n**]