Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
afb5c4d
use init_figure from main px core
emmanuelle Sep 3, 2020
8be8ca0
WIP: add facet_col arg to imshow
emmanuelle Sep 3, 2020
d236bc2
animations work for grayscale images, with or without binary string
emmanuelle Sep 4, 2020
c8e852e
animations now work + tests
emmanuelle Sep 5, 2020
12cec34
docs on facets and animations + add subplots titles
emmanuelle Sep 6, 2020
ab427ae
Merge branch 'master' into imshow-animation
emmanuelle Sep 7, 2020
7a3a9f4
solved old unnoticed conflict
emmanuelle Sep 7, 2020
b689a2f
attempt to use imshow with binary strings and xarrays
emmanuelle Sep 7, 2020
fbb3f65
added test
emmanuelle Sep 7, 2020
882810f
animation work for xarrays, still need to fix slider label
emmanuelle Sep 7, 2020
ba65990
added test with xarray and animations
emmanuelle Sep 7, 2020
cf644e5
added doc
emmanuelle Sep 7, 2020
72674b7
added pooch to doc requirements
emmanuelle Sep 7, 2020
bd42385
Update packages/python/plotly/plotly/express/_imshow.py
emmanuelle Sep 8, 2020
fc2375b
Update doc/python/imshow.md
emmanuelle Sep 8, 2020
a431fad
remove commented-out code
emmanuelle Sep 9, 2020
b652039
animation + facet kinda working now, but it broke labels
emmanuelle Sep 17, 2020
59c6622
added test
emmanuelle Sep 17, 2020
c7285a3
simplified code
emmanuelle Sep 17, 2020
91c066e
simplified code
emmanuelle Sep 17, 2020
ac5aa1f
polished code and added doc example
emmanuelle Sep 17, 2020
36b9f98
Merge branch 'imshow-animation' of https://github.com/plotly/plotly.p…
emmanuelle Sep 17, 2020
8cdc6af
updated doc
emmanuelle Nov 17, 2020
cf1c2b9
Merge branch 'master' into imshow-animation
emmanuelle Nov 18, 2020
5d1d8d8
add facet_col_spacing and facet_row_spacing
emmanuelle Nov 24, 2020
c27f88a
modify error message + animation_frame label
emmanuelle Nov 24, 2020
502fdfd
improve code readibility
emmanuelle Nov 24, 2020
135b01b
added example with sequence of images
emmanuelle Nov 24, 2020
6ac3e36
typoe
emmanuelle Nov 24, 2020
a5a2252
label names
emmanuelle Nov 27, 2020
77cb5cd
label name
emmanuelle Nov 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
animations work for grayscale images, with or without binary string
  • Loading branch information
emmanuelle committed Sep 4, 2020
commit d236bc227c1ef058fcd646b6df0d872396b8f44f
44 changes: 30 additions & 14 deletions packages/python/plotly/plotly/express/_imshow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import plotly.graph_objs as go
from _plotly_utils.basevalidators import ColorscaleValidator
from ._core import apply_default_cascade, init_figure
from ._core import apply_default_cascade, init_figure, configure_animation_controls
from io import BytesIO
import base64
from .imshow_utils import rescale_intensity, _integer_ranges, _integer_types
Expand Down Expand Up @@ -133,7 +133,7 @@ def imshow(
labels={},
x=None,
y=None,
animation_frame=False,
animation_frame=None,
facet_col=None,
facet_col_wrap=None,
color_continuous_scale=None,
Expand Down Expand Up @@ -353,13 +353,21 @@ def imshow(

# --------------- Starting from here img is always a numpy array --------
img = np.asanyarray(img)
slice_through = False
if facet_col is not None:
img = np.moveaxis(img, facet_col, 0)
facet_col = True

slice_through = True
if animation_frame is not None:
img = np.moveaxis(img, animation_frame, 0)
animation_frame = True
args["animation_frame"] = "plane"
slice_through = True

print("slice_through", slice_through)
# Default behaviour of binary_string: True for RGB images, False for 2D
if binary_string is None:
if facet_col:
if slice_through:
binary_string = img.ndim >= 4 and not is_dataframe
else:
binary_string = img.ndim >= 3 and not is_dataframe
Expand Down Expand Up @@ -391,7 +399,7 @@ def imshow(
zmin = 0

# For 2d data, use Heatmap trace, unless binary_string is True
if (img.ndim == 2 or (img.ndim == 3 and facet_col)) and not binary_string:
if (img.ndim == 2 or (img.ndim == 3 and slice_through)) and not binary_string:
if y is not None and img.shape[0] != len(y):
raise ValueError(
"The length of the y vector must match the length of the first "
Expand All @@ -402,10 +410,10 @@ def imshow(
"The length of the x vector must match the length of the second "
+ "dimension of the img matrix."
)
if facet_col:
if slice_through:
traces = [
go.Heatmap(x=x, y=y, z=img_slice, coloraxis="coloraxis1")
for img_slice in img
go.Heatmap(x=x, y=y, z=img_slice, coloraxis="coloraxis1", name=str(i))
for i, img_slice in enumerate(img)
]
else:
traces = [go.Heatmap(x=x, y=y, z=img, coloraxis="coloraxis1")]
Expand All @@ -429,7 +437,7 @@ def imshow(
# For 2D+RGB data, use Image trace
elif (
img.ndim == 3
and (img.shape[-1] in [3, 4] or (facet_col and binary_string))
and (img.shape[-1] in [3, 4] or (slice_through and binary_string))
or (img.ndim == 2 and binary_string)
):
rescale_image = True # to check whether image has been modified
Expand All @@ -442,7 +450,7 @@ def imshow(
if zmin is None and zmax is None: # no rescaling, faster
img_rescaled = img
rescale_image = False
elif img.ndim == 2 or (img.ndim == 3 and facet_col):
elif img.ndim == 2 or (img.ndim == 3 and slice_through):
img_rescaled = rescale_intensity(
img, in_range=(zmin[0], zmax[0]), out_range=np.uint8
)
Expand All @@ -457,7 +465,7 @@ def imshow(
for ch in range(img.shape[-1])
]
)
if facet_col:
if slice_through:
img_str = [
_array_to_b64str(
img_rescaled_slice,
Expand All @@ -477,7 +485,7 @@ def imshow(
ext=binary_format,
)
]
traces = [go.Image(source=img_str_slice) for img_str_slice in img_str]
traces = [go.Image(source=img_str_slice, name=str(i)) for i, img_str_slice in enumerate(img_str)]
else:
colormodel = "rgb" if img.shape[-1] == 3 else "rgba256"
traces = [go.Image(z=img, zmin=zmin, zmax=zmax, colormodel=colormodel)]
Expand All @@ -498,8 +506,15 @@ def imshow(
layout_patch["title_text"] = args["title"]
elif args["template"].layout.margin.t is None:
layout_patch["margin"] = {"t": 60}

frame_list = []
for index, trace in enumerate(traces):
fig.add_trace(trace, row=nrows - index // ncols, col=index % ncols + 1)
if facet_col or index == 0:
fig.add_trace(trace, row=nrows - index // ncols, col=index % ncols + 1)
if animation_frame:
frame_list.append(dict(data=trace, layout=layout, name=str(index)))
if animation_frame:
fig.frames = frame_list
fig.update_layout(layout)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a bit odd to have layout and layout_patch here... it was odd before I guess but might be worth looking at merging them together earlier?

fig.update_layout(layout_patch)
# Hover name, z or color
Expand Down Expand Up @@ -530,5 +545,6 @@ def imshow(
fig.update_xaxes(title_text=labels["x"])
if labels["y"]:
fig.update_yaxes(title_text=labels["y"])
fig.update_layout(template=args["template"], overwrite=True)
configure_animation_controls(args, go.Image, fig)
#fig.update_layout(template=args["template"], overwrite=True)
return fig