Skip to content

Commit

Permalink
Merge pull request #15 from earthlab/master
Browse files Browse the repository at this point in the history
Update jlpalomino fork from earthpy master
  • Loading branch information
Jenny Palomino committed May 14, 2019
2 parents 38686bc + e859c65 commit 23f2f49
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 36 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -5,7 +5,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [unreleased]

## [0.6.8]
* Add multi-panel plotting to plot_bands (@lwasser, #316)
* Fix bug in plot_rgb where multipanel plots are blank (@lwasser, #313)
* Add example vignette for calculating and classifying NDVI with EarthPy (@jlpalomino, #266)

Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Expand Up @@ -24,9 +24,9 @@
author = "Earth Lab"

# The short X.Y version
version = "0.6.7"
version = "0.6.8"
# The full version, including alpha/beta/rc tags
release = "0.6.7"
release = "0.6.8"


# -- General configuration ---------------------------------------------------
Expand Down
126 changes: 95 additions & 31 deletions earthpy/plot.py
Expand Up @@ -71,6 +71,61 @@ def colorbar(mapobj, size="3%", pad=0.09):
return fig.colorbar(mapobj, cax=cax)


def _plot_image(
arr_im,
cmap="Greys_r",
title=None,
extent=None,
cbar=True,
scale=True,
vmin=None,
vmax=None,
ax=None,
):

"""
Create a matplotlib figure with an image axis and associated extent.
Parameters
----------
arr_im : numpy array
An n-dimensional numpy array to plot.
cmap : str (default = "Greys_r")
Colormap name for plots.
title : str or list (optional)
Title of one band or list of titles with one title per band.
extent : tuple (optional)
Bounding box that the data will fill: (minx, miny, maxx, maxy).
cbar : Boolean (default = True)
Turn off colorbar if needed.
scale : Boolean (Default = True)
Turn off bytescale scaling if needed.
vmin : Int (Optional)
Specify the vmin to scale imshow() plots.
vmax : Int (Optional)
Specify the vmax to scale imshow() plots.
ax : Matplotlib axes object (Optional)
Matplotlib axis object to plot image.
Returns
----------
ax : axes object
The axes object(s) associated with the plot.
"""

if scale:
arr_im = es.bytescale(arr_im)

im = ax.imshow(arr_im, cmap=cmap, vmin=vmin, vmax=vmax, extent=extent)
if title:
ax.set(title=title)
if cbar:
colorbar(im)
ax.set(xticks=[], yticks=[])

return ax


def plot_bands(
arr,
cmap="Greys_r",
Expand All @@ -82,6 +137,7 @@ def plot_bands(
scale=True,
vmin=None,
vmax=None,
ax=None,
):
"""Plot each band in a numpy array in its own axis.
Expand Down Expand Up @@ -112,11 +168,8 @@ def plot_bands(
Returns
----------
tuple
fig : figure object
The figure of the plotted band(s).
ax or axs : axes object(s)
The axes object(s) associated with the plot.
ax or axs : matplotlib.axes._subplots.AxesSubplot object(s)
The axes object(s) associated with the plot.
Example
-------
Expand All @@ -133,7 +186,7 @@ def plot_bands(
... figsize=(8, 3))
array([<matplotlib.axes._subplots.AxesSubplot object at 0x...
"""

show = False
try:
arr.ndim
except AttributeError:
Expand Down Expand Up @@ -171,19 +224,23 @@ def plot_bands(
band = i + 1

arr_im = arr[i]
if scale:
arr_im = es.bytescale(arr_im)

im = ax.imshow(
arr_im, cmap=cmap, vmin=vmin, vmax=vmax, extent=extent
)
if title:
ax.set(title=title[i])
the_title = title[i]
else:
ax.set(title="Band %i" % band)
if cbar:
colorbar(im)
ax.set(xticks=[], yticks=[])
the_title = "Band {}".format(band)

_plot_image(
arr_im,
cmap=cmap,
cbar=cbar,
scale=scale,
vmin=vmin,
vmax=vmax,
extent=extent,
title=the_title,
ax=ax,
)
# This loop clears out the plots for axes which are empty
# A matplotlib axis grid is always uniform with x cols and x rows
# eg: an 8 band plot with 3 cols will always be 3 x 3
Expand All @@ -198,17 +255,26 @@ def plot_bands(
# If it's a 2 dimensional array with a 3rd dimension
arr = np.squeeze(arr)

fig, ax = plt.subplots(figsize=figsize)
if scale:
arr = es.bytescale(arr)
if ax is None:
fig, ax = plt.subplots(figsize=figsize)
show = True

im = ax.imshow(arr, cmap=cmap, vmin=vmin, vmax=vmax, extent=extent)
if title:
ax.set(title=title[0])
ax.set(xticks=[], yticks=[])
if cbar:
colorbar(im)
plt.show()
title = title[0]

_plot_image(
arr,
cmap=cmap,
scale=scale,
cbar=cbar,
vmin=vmin,
vmax=vmax,
extent=extent,
title=title,
ax=ax,
)
if show:
plt.show()
return ax


Expand Down Expand Up @@ -269,14 +335,12 @@ def plot_rgb(
The intended title of the plot.
stretch : Boolean (optional)
Application of a linear stretch. If set to True, a linear stretch will be applied.
Returns
----------
tuple
fig : figure object
The figure object associated with the 3 band image. If the
ax keyword is specified, the figure return will be None.
ax : axes object
The axes object associated with the 3 band image.
ax : axes object
The axes object associated with the 3 band image.
Example
-------
Expand Down
20 changes: 20 additions & 0 deletions earthpy/tests/test_io.py
Expand Up @@ -9,6 +9,16 @@
import earthpy.io as eio


RUNNING_ON_CI = False
if "CI" in os.environ:
if os.environ["CI"]:
RUNNING_ON_CI = True

skip_on_ci = pytest.mark.skipif(
RUNNING_ON_CI, reason="Test fails intermittently on CI systems."
)


@pytest.fixture
def eld(tmpdir):
return eio.Data(path=tmpdir)
Expand Down Expand Up @@ -87,6 +97,7 @@ def test_continental_divide_trail():
]


@skip_on_ci
@pytest.mark.vcr()
def test_urls_are_valid():
""" Test responses for each dataset to ensure valid URLs. """
Expand Down Expand Up @@ -125,13 +136,15 @@ def test_invalid_dataset_key(eld):
eld.get_data(key="some non-existent key")


@skip_on_ci
@pytest.mark.vcr()
def test_valid_download_file(eld):
""" Test that single files get downloaded. """
file = eld.get_data("little-text-file")
assert os.path.isfile(file)


@skip_on_ci
@pytest.mark.vcr()
def test_valid_download_zip(eld):
""" Test that zipped files get downloaded and extracted. """
Expand All @@ -140,6 +153,7 @@ def test_valid_download_zip(eld):
assert path_has_contents


@skip_on_ci
@pytest.mark.parametrize("replace_arg_value", [True, False])
@pytest.mark.vcr()
def test_replace_arg_controle_overwrite(eld, replace_arg_value):
Expand All @@ -154,6 +168,7 @@ def test_replace_arg_controle_overwrite(eld, replace_arg_value):
assert mtime1 == mtime2


@skip_on_ci
@pytest.mark.vcr()
def test_arbitrary_url_file_download(eld):
""" Verify that arbitrary URLs work for data file downloads. """
Expand All @@ -170,6 +185,7 @@ def test_invalid_data_type(eld):
eld.get_data("invalid-data-type")


@skip_on_ci
@pytest.mark.vcr()
def test_arbitrary_url_zip_download(eld):
""" Verify that aribitrary URLs work for zip file downloads. """
Expand All @@ -180,27 +196,31 @@ def test_arbitrary_url_zip_download(eld):
assert path_has_contents


@skip_on_ci
@pytest.mark.vcr()
def test_url_download_tar_file(eld):
""" Ensure that tar files are downloaded and extracted. """
path = eld.get_data(url="https://ndownloader.figshare.com/files/14615411")
assert "abc.txt" in os.listdir(path)


@skip_on_ci
@pytest.mark.vcr()
def test_url_download_tar_gz_file(eld):
""" Ensure that tar.gz files are downloaded and extracted. """
path = eld.get_data(url="https://ndownloader.figshare.com/files/14615414")
assert "abc.txt" in os.listdir(path)


@skip_on_ci
@pytest.mark.vcr()
def test_url_download_txt_file_with_content_disposition(eld):
""" Test arbitrary URL download with content-disposition. """
path = eld.get_data(url="https://ndownloader.figshare.com/files/14555681")
assert path.endswith("abc.txt") and os.path.isfile(path)


@skip_on_ci
@pytest.mark.parametrize("verbose_arg_value", [True, False])
@pytest.mark.vcr()
def test_verbose_arg_works(eld, verbose_arg_value, capsys):
Expand Down
17 changes: 17 additions & 0 deletions earthpy/tests/test_plot_bands.py
Expand Up @@ -224,3 +224,20 @@ def test_extent(one_band_3dims):
# Cbar should be scaled between the vmin and vmax vals
assert pl_extent == ext
plt.close()


def test_multi_panel_single_band(one_band_3dims):
"""Test that multi panel works with single band arr."""

title1 = "Title axis one"
title2 = "Title axis two"
f, (ax1, ax2) = plt.subplots(2, 1)
ep.plot_bands(one_band_3dims, title=title1, ax=ax1)
ep.plot_bands(one_band_3dims, title=title2, ax=ax2)

# get all axis subplot elements - note this returns subplots and axes
all_axes = f.axes

assert len(all_axes) == 4
assert all_axes[0].get_title() == title1
assert all_axes[1].get_title() == title2
2 changes: 1 addition & 1 deletion setup.cfg
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.6.7
current_version = 0.6.8
commit = True
tag = True

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -22,7 +22,7 @@
description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
long_description_content_type="text/markdown",
version="0.6.7",
version="0.6.8",
packages=["earthpy"],
install_requires=[
"geopandas",
Expand Down

0 comments on commit 23f2f49

Please sign in to comment.