diff --git a/README.md b/README.md
index f8657898..e4bd6d3d 100644
--- a/README.md
+++ b/README.md
@@ -7,29 +7,33 @@
-
-
-
+
@@ -69,6 +73,18 @@ isns.imgplot(data, dx=0.01, units="um", cbar_label="Height (nm)")
+### Plot image with a histogram
+
+```python
+import seaborn_image as isns
+
+isns.imghist(data, dx=150, units="nm", cbar_label="Height (nm)", cmap="ice")
+```
+
+
+
+
+
### Set context like seaborn
```python
@@ -92,4 +108,5 @@ isns.filterplot(data, filter="gaussian", sigma=5, cbar_label="Height (nm)")
## Documentation
+
Check out the docs [here](https://seaborn-image.readthedocs.io/)
diff --git a/examples/image_5.png b/examples/image_5.png
new file mode 100644
index 00000000..a7c6b1a9
Binary files /dev/null and b/examples/image_5.png differ
diff --git a/pyproject.toml b/pyproject.toml
index aed29acf..74abf6cc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -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 "]
license = "MIT"
diff --git a/src/seaborn_image/_context.py b/src/seaborn_image/_context.py
index fb129054..0d535742 100644
--- a/src/seaborn_image/_context.py
+++ b/src/seaborn_image/_context.py
@@ -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)
diff --git a/src/seaborn_image/_core.py b/src/seaborn_image/_core.py
index 0b6dfb74..621895a5 100644
--- a/src/seaborn_image/_core.py
+++ b/src/seaborn_image/_core.py
@@ -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
diff --git a/src/seaborn_image/_general.py b/src/seaborn_image/_general.py
index 188a358a..ba3bfd27 100644
--- a/src/seaborn_image/_general.py
+++ b/src/seaborn_image/_general.py
@@ -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
@@ -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
@@ -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
diff --git a/tests/test_core.py b/tests/test_core.py
index e4f8d1cb..e81c94d8 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -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"])
@@ -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
diff --git a/tests/test_general.py b/tests/test_general.py
index fe94022f..4de63726 100644
--- a/tests/test_general.py
+++ b/tests/test_general.py
@@ -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(
@@ -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,
+ )