Skip to content

Commit

Permalink
Merge pull request #4 from SarthakJariwala/v0.3.x
Browse files Browse the repository at this point in the history
Add `imghist` function to view distribution along side the image
  • Loading branch information
SarthakJariwala authored Jul 28, 2020
2 parents 764b304 + bdd78af commit 949aa0b
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 27 deletions.
47 changes: 32 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,33 @@

<div class="row">

<a>
<img src="./examples/image_0.png" height="180" width="200">
</a>
<a>
<img src="./examples/image_0.png" height="180" width="200">
</a>

<a>
<img src="./examples/image_1.png" height="180" width="200">
</a>
<a>
<img src="./examples/image_1.png" height="180" width="200">
</a>

<a>
<img src="./examples/image_3.png" height="165" width="400">
</a>
<a>
<img src="./examples/image_3.png" height="165" width="400">
</a>

</div>

<div class="row">

<a>
<img src="./examples/image_5.png" height="250" width="375">
</a>

<a>
<img src="./examples/image_4.png" height="400" width="400">
</a>
</div>

<a>
<img src="./examples/image_2.png" height="400" width="400">
</a>
<div class="row">

<a>
<img src="./examples/image_4.png" height="600" width="600">
</a>

</div>

Expand Down Expand Up @@ -69,6 +73,18 @@ isns.imgplot(data, dx=0.01, units="um", cbar_label="Height (nm)")
<img src="./examples/image_0.png" height="275" width="300">
</a>

### Plot image with a histogram

```python
import seaborn_image as isns

isns.imghist(data, dx=150, units="nm", cbar_label="Height (nm)", cmap="ice")
```

<a>
<img src="./examples/image_5.png" height="300" width="450">
</a>

### Set context like seaborn

```python
Expand All @@ -92,4 +108,5 @@ isns.filterplot(data, filter="gaussian", sigma=5, cbar_label="Height (nm)")
</a>

## Documentation

Check out the docs [here](https://seaborn-image.readthedocs.io/)
Binary file added examples/image_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "seaborn-image"
version = "0.2.0"
version = "0.3.0"
description = "seaborn-image: image data visualization and processing like seaborrn using matplotlib, scipy and scikit-image"
authors = ["Sarthak Jariwala <[email protected]>"]
license = "MIT"
Expand Down
3 changes: 3 additions & 0 deletions src/seaborn_image/_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,21 @@ def set_context(mode="talk", fontfamily="arial", fontweight="bold", rc=None):
plt.rc("axes", linewidth=1.5)
plt.rc("axes", titlesize=15, titleweight=fontweight)
plt.rc("axes", labelsize=15, labelweight=fontweight)
mpl.rcParams.update({"figure.constrained_layout.wspace": 0.2})
font = {"family": fontfamily, "weight": fontweight, "size": 10}

if mode == "notebook" or mode == "presentation" or mode == "talk":
plt.rc("axes", linewidth=2.5)
plt.rc("axes", titlesize=20, titleweight=fontweight)
plt.rc("axes", labelsize=20, labelweight=fontweight)
mpl.rcParams.update({"figure.constrained_layout.wspace": 0.3})
font = {"family": fontfamily, "weight": fontweight, "size": 15}

if mode == "poster":
plt.rc("axes", linewidth=3.5)
plt.rc("axes", titlesize=25, titleweight=fontweight)
plt.rc("axes", labelsize=25, labelweight=fontweight)
mpl.rcParams.update({"figure.constrained_layout.wspace": 0.4})
font = {"family": fontfamily, "weight": fontweight, "size": 20}

plt.rc("font", **font)
Expand Down
5 changes: 4 additions & 1 deletion src/seaborn_image/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,13 @@ def plot(self):
if self.cbar_label is not None:
cb.set_label(self.cbar_label, fontdict=self.cbar_fontdict)

else:
cax = None

if not self.showticks:
ax.get_yaxis().set_visible(False)
ax.get_xaxis().set_visible(False)

f.tight_layout()

return f, ax
return f, ax, cax
128 changes: 126 additions & 2 deletions src/seaborn_image/_general.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec
from matplotlib.axes import Axes
from matplotlib.colors import Colormap

from ._colormap import _CMAP_QUAL
from ._core import _SetupImage


Expand Down Expand Up @@ -63,6 +67,7 @@ def imgplot(
(tuple): tuple containing:
(`matplotlib.figure.Figure`): Matplotlib figure.
(`matplotlib.axes.Axes`): Matplotlib axes where the image is drawn.
(`matplotlib.axes.Axes`): Colorbar axes
Example:
>>> import seaborn_image as isns
Expand Down Expand Up @@ -114,6 +119,125 @@ def imgplot(
fontdict=title_fontdict,
)

f, ax = img_plotter.plot()
f, ax, cax = img_plotter.plot()

return f, ax, data
return f, ax, cax


def imghist(
data,
cmap=None,
bins=500,
vmin=None,
vmax=None,
dx=None,
units=None,
cbar=True,
cbar_label=None,
cbar_fontdict=None,
cbar_ticks=None,
showticks=False,
title=None,
title_fontdict=None,
):
"""Plot data as a 2-D image with histogram showing the distribution of
the data. Options to add scalebar, colorbar, title.
Args:
data: Image data (array-like). Supported array shapes are all
`matplotlib.pyplot.imshow` array shapes
cmap (str or `matplotlib.colors.Colormap`, optional): Colormap for image.
Can be a seaborn-image colormap or default matplotlib colormaps or
any other colormap converted to a matplotlib colormap. Defaults to None.
bins (int, optional): Number of histogram bins. Defaults to 500.
vmin (float, optional): Minimum data value that colormap covers. Defaults to None.
vmax (float, optional): Maximum data value that colormap covers. Defaults to None.
dx (float, optional): Size per pixel of the image data. If scalebar
is required, `dx` and `units` must be sepcified. Defaults to None.
units (str, optional): Units of `dx`. Defaults to None.
cbar (bool, optional): Specify if a colorbar is required or not.
Defaults to True.
cbar_label (str, optional): Colorbar label. Defaults to None.
cbar_fontdict (dict, optional): Font specifications for colorbar label - `cbar_label`.
Defaults to None.
cbar_ticks (list, optional): List of colorbar ticks. If None, min and max of
the data are used. If `vmin` and `vmax` are specified, `vmin` and `vmax` values
are used for colorbar ticks. Defaults to None.
showticks (bool, optional): Show image x-y axis ticks. Defaults to False.
title (str, optional): Image title. Defaults to None.
title_fontdict (dict, optional): [Font specifications for `title`. Defaults to None.
Raises:
TypeError: if `bins` is not int
Returns:
(tuple): tuple containing:
(`matplotlib.figure.Figure`): Matplotlib figure.
(tuple): tuple containing:
(`matplotlib.axes.Axes`): Matplotlib axes where the image is drawn.
(`matplotlib.axes.Axes`): Matplotlib axes where the histogram is drawn.
(`matplotlib.axes.Axes`): Colorbar axes
Example:
>>> import seaborn_image as isns
>>> isns.imghist(data)
>>> isns.imghist(data, bins=300) # specify the number of histogram bins
>>> isns.imghist(data, dx=2, units="nm") # add a scalebar
>>> isns.imghist(data, cmap="deep") # specify a colormap
"""

if not isinstance(bins, int):
raise TypeError("'bins' must be a positive integer")
if not bins > 0:
raise ValueError("'bins' must be a positive integer")

f = plt.figure(figsize=(10, 6)) # TODO make figsize user defined
gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1], figure=f)

ax1 = f.add_subplot(gs[0])

f, ax1, cax = imgplot(
data,
ax=ax1,
cmap=cmap,
vmin=vmin,
vmax=vmax,
dx=dx,
units=units,
cbar=cbar,
cbar_label=cbar_label,
cbar_fontdict=cbar_fontdict,
cbar_ticks=cbar_ticks,
showticks=showticks,
title=title,
title_fontdict=title_fontdict,
)

ax2 = f.add_subplot(gs[1], sharey=cax)

n, bins, patches = ax2.hist(
data.ravel(), bins=bins, density=True, orientation="horizontal"
)

ax2.get_xaxis().set_visible(False)
ax2.get_yaxis().set_visible(False)
ax2.set_frame_on(False)

if cmap is None:
cm = _CMAP_QUAL.get("deep").mpl_colormap
else:
if cmap in _CMAP_QUAL.keys():
cm = _CMAP_QUAL.get(cmap).mpl_colormap
else:
cm = plt.cm.get_cmap(cmap)

bin_centers = bins[:-1] + bins[1:]

# scale values to interval [0,1]
col = bin_centers - np.min(bin_centers)
col /= np.max(col)

for c, p in zip(col, patches):
plt.setp(p, "facecolor", cm(c))

return f, (ax1, ax2), cax
8 changes: 6 additions & 2 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_plot_check_cbar_dict():
img_setup = isns._core._SetupImage(
data, cbar=True, cbar_fontdict=[{"fontsize": 20}]
)
f, ax = img_setup.plot()
f, ax, cax = img_setup.plot()


@pytest.mark.parametrize("cmap", [None, "acton"])
Expand Down Expand Up @@ -82,7 +82,11 @@ def test_plot_w_all_inputs(
cbar_ticks=cbar_ticks,
showticks=showticks,
)
f, ax = img_setup.plot()
f, ax, cax = img_setup.plot()

assert isinstance(f, Figure)
assert isinstance(ax, Axes)
if cbar is True:
assert isinstance(cax, Axes)
else:
assert cax is None
57 changes: 51 additions & 6 deletions tests/test_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,21 @@ def test_title_fontdict_type():


def test_imgplot_return():
f, ax, d = isns.imgplot(data)
f, ax, cax = isns.imgplot(data)

assert isinstance(f, Figure)
assert isinstance(ax, Axes)
assert d.all() == data.all()
assert isinstance(cax, Axes)


@pytest.mark.parametrize("cmap", ["acton"])
@pytest.mark.parametrize("cmap", [None, "acton", "inferno"])
@pytest.mark.parametrize("cbar", [True, False])
@pytest.mark.parametrize("cbar_label", ["My title", None])
@pytest.mark.parametrize("cbar_fontdict", [{"fontsize": 20}])
@pytest.mark.parametrize("cbar_fontdict", [{"fontsize": 20}, None])
@pytest.mark.parametrize("showticks", [True, False])
@pytest.mark.parametrize("title", ["My title", None])
@pytest.mark.parametrize("title_fontdict", [{"fontsize": 20}])
def test_all_valid_inputs(
@pytest.mark.parametrize("title_fontdict", [{"fontsize": 20}, None])
def test_imgplot_w_all_valid_inputs(
cmap, cbar, cbar_label, cbar_fontdict, showticks, title, title_fontdict
):
isns.imgplot(
Expand All @@ -79,3 +79,48 @@ def test_all_valid_inputs(
title=title,
title_fontdict=title_fontdict,
)


@pytest.mark.parametrize("bins", [None, 200.0, -400.13])
def test_imghist_bins_type(bins):
with pytest.raises(TypeError):
isns.imghist(data, bins=bins)


@pytest.mark.parametrize("bins", [-100, 0])
def test_imghist_bins_value(bins):
with pytest.raises(ValueError):
isns.imghist(data, bins=bins)


def test_imghist_return():
f, axes, cax = isns.imghist(data)

assert isinstance(f, Figure)
assert isinstance(axes[0], Axes)
assert isinstance(axes[1], Axes)
assert isinstance(cax, Axes)


@pytest.mark.parametrize("cmap", [None, "acton", "inferno"])
@pytest.mark.parametrize("bins", [500, 10])
@pytest.mark.parametrize("cbar", [True, False])
@pytest.mark.parametrize("cbar_label", ["My title", None])
@pytest.mark.parametrize("cbar_fontdict", [{"fontsize": 20}, None])
@pytest.mark.parametrize("showticks", [True, False])
@pytest.mark.parametrize("title", ["My title", None])
@pytest.mark.parametrize("title_fontdict", [{"fontsize": 20}, None])
def test_imghist_w_all_valid_inputs(
cmap, bins, cbar, cbar_label, cbar_fontdict, showticks, title, title_fontdict
):
isns.imghist(
data,
cmap=cmap,
bins=bins,
cbar=cbar,
cbar_label=cbar_label,
cbar_fontdict=cbar_fontdict,
showticks=showticks,
title=title,
title_fontdict=title_fontdict,
)

0 comments on commit 949aa0b

Please sign in to comment.