Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot set colorscale in template for some trace types #3100

Closed
jonmmease opened this issue Oct 12, 2018 · 6 comments
Closed

Cannot set colorscale in template for some trace types #3100

jonmmease opened this issue Oct 12, 2018 · 6 comments

Comments

@jonmmease
Copy link
Contributor

In working on developing templates for plotly.py I've found that I'm not able to set the colorscale and colorbar properties in the template for some trace types.

This works as I expect for the heatmap trace type. The defualt colorscale of Viridis and the colorbar tick properties are both applied.
Pen: https://codepen.io/jonmmease/pen/mzMeMW

var trace1 = {
  type: 'heatmap',
  z: [[1, 2, 3], [4, 5, 6]],
};

var data = [ trace1 ];

var layout = {
  template: {
    data: {
      heatmap: [{
        colorscale: 'Viridis',
        colorbar: {
          ticks: 'inside',
          ticklen: 10,
          tickcolor: 'white'
        }
      }],
    }
  }
};

Plotly.newPlot('myDiv', data, layout);

newplot-1

But it does not work for the scatter.marker colorscale and colorbar.
Pen: https://codepen.io/jonmmease/pen/LgjpQG

var trace1 = {
  type: 'scatter',
  y: [1, 2, 3],
  marker: {
    size: 20,
    color: [1, 2, 3],
    showscale: true
  },
  mode: 'markers'
};

var data = [ trace1 ];

var layout = {
  template: {
    data: {
      scatter: [{
        marker: {
          symbol: 'square',
          colorscale: 'Viridis',
          colorbar: {
            ticks: 'inside',
            ticklen: 10,
            tickcolor: 'white'
          } 
        }
      }],
    }
  }
};

Plotly.newPlot('myDiv', data, layout);

Note that scatter.marker.symbol is being picked up from the template, so I'm pretty sure the template specification is correct, but let me know if I'm missing something.

I've noticed this same behavior for other colorscales and colorbars, and I can work through an exhaustive list later today if that's helpful. Thanks!

@etpinard
Copy link
Contributor

Thanks for the report @jonmmease !

The colorscale part can be "fixed" by adding marker.autocolorscale: false to the template as in https://codepen.io/etpinard/pen/XxaRyB, I'm not sure if this is the desired behavior though. Perhaps we could improve the logic here:

var autoColorscaleDflt;
if(sclIn !== undefined) autoColorscaleDflt = !isValidScale(sclIn);
coerce(prefix + 'autocolorscale', autoColorscaleDflt);
var sclOut = coerce(prefix + 'colorscale');

where autocolorscale would default to false if a valid colorscale template is set.

As for the colorbar part, the problem comes from the colorbar defaults call:

if(showScale) colorbarDefaults(containerIn, containerOut, layout);

where containerOut is fullData[i] for heatmap, but is fullData[i].marker for scatter and other marker colorscales. Colorbar templates propagate correctly (using Template.newContainer) from fullData[i], but not from marker containers. Adding

image

should be enough to fix this, but we should look for other situations where supply-defaults subroutines are called with trace sub-containers.

@jonmmease
Copy link
Contributor Author

Oh awesome, yeah setting marker.autocolorscale: false in the template takes care of the colorscale problem, which is fine with me for the time being.

@jonmmease
Copy link
Contributor Author

One more issue here. Setting marker.autocolorscale: false in the template causes the colorscale to be displayed properly if the template is already in place when the scatter trace is created. But if the template is applied with relayout after the scatter trace is added, the template's colorscale is not applied.

@etpinard
Copy link
Contributor

etpinard commented Oct 26, 2018

Thanks for pointing out the relayout issue @jonmmease (-> in https://codepen.io/etpinard/pen/gBqqgo)

I'm afraid that it points to a bigger problem though. At the moment, colorscales are mutating in the input traces and thus rely on an 'implied edit' (listed here) during Plotly.relayout. This 'implied edit' clears the colorscale value out of the input trace before calling Plots.supplyDefaults making calls like relayout(gd, 'marker.colorscale', 'Viridis') work as expected.

Now there are many more attributes (e.g. cmin/cmax, contours.* to name a few) with 'implied edits' which currently won't work with relayout(gd, 'template', {/* */}).

I'm not sure what the best way forward is. To stop mutating in things in input traces would solve the issue, or do something similar to the new histogram autobin logic, but those are fairly big projects. There might be an easier solution.

In the meantime, using relayout to update templates might not be the best idea.

@jonmmease
Copy link
Contributor Author

Thanks for the background @etpinard,

Would react handle this case better, or would the same issues arise? It would be a bit of a project, but I think plotly.py's FigureWidget could eventually move to using react instead of restyle/relayout/update.

But in the meantime, a lot of the template information does come through well when switching templates using relayout and I think it's a pretty useful way to explore themes. So I'd like to leave it in place for plotly.py 3.4 and just have the caveat that some template updates require the figure to be re-rendered.

@etpinard
Copy link
Contributor

Would react handle this case better, or would the same issues arise? I

No unfortunately. Only newPlot will behave correctly on layout.template edits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants