Skip to content

Line animations fail in some frames for some lines. #2794

Closed
@iandanforth

Description

@iandanforth

OS: OSX 10.13.2
Browsers: Chrome/Firefox/Safari latest

plotly-bug

As you can see in this gif, most of the frames animate properly. Some however have the lines "jumping" to their final values rather than being smoothly transitioned.

This animated scatter is being created from the Python API, but I suspect this is more appropriate for the js side to investigate. (Correct me if I'm wrong).

Here is the script to recreate the above chart.

Notes

  • The issue seems to be largely independent of how many lines are being drawn. (You can change line_count below to see that).
  • The issue goes away if the values remain constant within each line. Comment out line 43 to see that.
import numpy as np
import colorlover as cl
from plotly.offline import plot

sim_duration = 20.0
time_inc = 0.1
line_count = 120
times = np.arange(0.0, sim_duration, time_inc)

# Setting colors for plot.
potvin_scheme = [
    'rgb(115, 0, 0)',
    'rgb(252, 33, 23)',
    'rgb(230, 185, 43)',
    'rgb(107, 211, 100)',
    'rgb(52, 211, 240)',
    'rgb(36, 81, 252)',
    'rgb(0, 6, 130)'
]
# It's hacky but also sorta cool.
c = cl.to_rgb(cl.interp(potvin_scheme, line_count))
c = [val.replace('rgb', 'rgba') for val in c]
c = [val.replace(')', ',{})') for val in c]


def get_color(trace_index: int) -> str:
    # The first and every 20th trace should be full opacity
    alpha = 0.2
    if trace_index == 0 or ((trace_index + 1) % 20 == 0):
        alpha = 1.0
    color = c[trace_index].format(alpha)
    return color

# Per Motor Unit Force

start = np.ones((line_count, len(times)))
inds = np.reshape(np.arange(1.0, 41.0, 40 / len(times)), (1, len(times)))
vals = (-np.log(inds) + 4) / 0.18
vals = np.repeat(vals, line_count, axis=0)


all_array = np.ones((line_count, len(times))) * np.reshape(np.arange(0.0, 35.0, 35 / line_count), (line_count, 1))
all_array += vals  # <---- COMMENT OUT TO REMOVE CURVE
data = []
annotations = []
anno_offsets = {
    0: 20,
    19: 30,
    39: 40,
    59: 45,
    79: 17,
    99: 56,
    119: 170
}

max_y = np.amax(all_array)
for i, t in enumerate(all_array):
    trace = dict(
        x=times[:1],
        y=t[:1],
        name=i + 1,
        marker=dict(
            color=get_color(i)
        ),
        mode='lines'
    )
    data.append(trace)

frames = []
for i in range(1, len(times), int(1 / time_inc)):
    frame_data = []
    for j, t in enumerate(all_array):
        trace = dict(
            x=times[:i],
            y=t[:i],
            name=j + 1,
            marker=dict(
                color=get_color(j)
            ),
            mode='lines'
        )
        frame_data.append(trace)

    frame = dict(
        data=frame_data
    )
    frames.append(frame)

layout = dict(
    title='Motor Unit Forces by Time',
    yaxis=dict(
        title='Motor unit force (relative to MU1 tetanus)',
        range=[0, max_y],
        autorange=False
    ),
    xaxis=dict(
        title='Time (s)',
        range=[0, sim_duration],
        autorange=False
    ),
    updatemenus=[{
        'type': 'buttons',
        'buttons': [{
            'args': [
                None,
                {'frame': {'duration': 300, 'redraw': False},
                 'fromcurrent': True,
                 'transition': {'duration': 200, 'easing': 'linear'}
                 }
            ],
            'label': 'Play',
            'method': 'animate'
        }]
    }]
)
layout['annotations'] = annotations

fig = dict(
    data=data,
    layout=layout,
    frames=frames
)

plot(fig, filename='bug.html', validate=False)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugsomething broken

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions