-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Templates (themes) integration #1224
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
e.g. `layout.template.layout.annotationdefaults`
Supports registering/unregistering templates and setting default template layout.template can now be specified as the name of a template, and if layout.template is not specified, then a registered default is applied during figure construction.
This inputs a figure and outputs a new figure where all eligible properties have been moved into the new figure's template definition By default properties named 'text' and 'title' are note moved into the template, but this can be customized using the `skip` argument.
fig.layout.template = 'template1+template2'
and logic to lazily load theme from file on first use
going to be pretty large
decimate bmw colorscale in plotly templates to save space and reduce plotting latency.
colorscale is used across trace types. Also crop bwm colorscale slightly so that it has better contrast on both light and dark themes. No it doesn't go quite as close to black or as close to white.
of text and lines/markers for several trace types.
There is still some non-determinism with raster image formats, and eps is enough to execute the full orca pipeline
in the plotly_* templates
that can be added to turn it off if desired.
- Slightly lighten background grid in plotly template - Slightly darken grid lines in plotly_dark template - Don't explicitly enable xgrid/ygrid in plotly* templates, let plotly.js decide.
This way fig.layout.template won't be None after Figure is constructed
…* templates This makes zero lines less distracting when not helpful, while still making it fairly easy to focus on them when desired.
Alright, time to merge this! We'll review the built-in templates once more after building this against plotly.js 1.42.0 as there are a few template fixes in that version. Here are final versions of each template at the time of the merge None (still the default):'ggplot2':'seaborn':'plotly':'plotly_white':'plotly_dark':'plotly+presentation':'plotly_white+presentation+xgridoff': |
Closed
1 task
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
This PR introduces figure templates (themes) to plotly.py
Background
Earlier this year the plotly.js team discussed (plotly/plotly.js#2469) and then implemented (plotly/plotly.js#2761) a powerful templating approach that allows plotly.js users to specify default values for all trace and layout properties that make up a figure. This makes it possible to create custom figure themes that can be applied repeatedly to new figures.
In addition to default property values, themes can also include default object array elements like annotations, shapes, and images. This way, templates can be used to create figures that include default labels (e.g. "CONFIDENTIAL") and/or default images (e.g. a company/project logo).
Plotly.js Template Representation
Templates in Plotly.js are specified as a part of the declarative structure of the figure itself. A template is a specification object located at the
layout.template
path in the figure specification.After a figure has been created, its template can be updated using the same
Plotly.relayout
operation that can be used to update the rest of the figure's layout properties.plotly.py integration
This section describes the high-level changes made in this PR to support templates in plotly.py
Code generation / validation
The specification of the
layout.template
object can't be fully captured in the schema, so a bunch of code generation work was needed in order to provide the same level of validation that plotly.py users have come to expect from the rest of the figure property hierarchy.In addition to the
layout.template
object itself, templates also introduce a*defaults
property that corresponds to each object array property (e.g.layout.annotationsdefaults
corresponds tolayout.annotations
). These are now included in the code generation / validation process.These changes are implemented in approximately commits 106426e through f84c8a5
plotly.io.templates configuration object for registering named templates
Next, this PR adds a new
plotly.io.templates
configuration object for registering templates. A user can create a template object (an instance ofgo.layout.Template
), configure it to their liking, then register it by name withplotly.io.templates
for use in the future.If a string is assigned to the
fig.layout.template
property, plotly.py checks theplotly.io.templates
registry to see if there is a template registered with this name. If there is, then this template is applied to the figure.Default template
The
plotly.io.templates
configuration object can also be used to specify a global default template. The global default template will be applied automatically when a figure is constructed (unless an explicit template was provided to the figure constructor).Merging templates
A string assigned to the
fig.layout.template
property, or registered as the default template, may contain multiple registered template names joined on'+'
characters (borrowing the flaglist syntax). In this case the templates are merged together (applied to the figure from left to right).Extracting a template from a figure
A new
plotly.io.to_templated
function is introduced that inputs a figure and then returns a copy of the figure where all of the "styling" properties have been moved from the figure'sdata
/layout
specification into the figure'slayout.template
object.The
layout.template
property of the resulting figure can then be applied to another figure, or it can be registered as a named template.Custom Theme API example
Imports
Construct a figure with large courier text
Convert to a figure with a template. Note how the 'font' properties have been moved into the template property.
Next create a new figure with this template
The default font in fig2 will now be size 20 Courier.
Next, register as a named template...
and specify this template by name when constructing a figure.
Finally, set this as the default template to be applied to all new figures
New built-in named templates
A new
templategen
module is introduced that includes some helper function for us to use in generating templates to bundle with plotly.py. Thetemplategen
module was purposely not added to setup.py because it should not be distributed with plotly.py, it's only for development (just like the existingcodegen
module).Built-in templates are generated by running
templategen/__init__.py
and they are output to the newplotly/package_data/templates
directory. This directory has been added as apackage_data
directory to setup.py as it needs to be distributed along with plotly.pyAt this point this PR includes templates for 2 common themes, 3 original themes, and 2 "add-on" templates.
Common themes
This PR includes pre-registered templates that imitate (in the most flattering way possible 🙂) the default ggplot2 and seaborn themes.
Current default
First, here is the sample figure with no theme applied
ggplot
seaborn
Original themes
This PR currently includes three original themes, including one dark theme that's well suited for use alongside JupyterLab's dark theme.
plotly
plotly_white
plotly_dark
Here's a screeshot of the
plotly_dark
, viewed in JupyterLab with JupyterLab dark themeAdd-on templates
In addition to these theme templates, I've added a couple of "add-on" templates. These are templates that can be used either on their own, or merged with one of the themes above.
presentation
The
presentation
template increases the font size, marker size, and line width by about 1.5x The idea is that this is a templates that can be selectively activated during a presentation, along with JupyterLab's "View->Presentation Mode" option, to make figure more readable from a distance.Here is an example of
'plotly+presentation'
xgridoff
The "xgridoff" template simply disables x-grid axis lines by default. It can be
Here's an example of
'plotly_dark+presentation+xgridoff'
Interactive theme switching
Thanks to the design of templates in Plotly.js and the design of the ipywidgets plotly.py it's possible to interactively apply different templates to a figure after it has already been created and displayed. Here's what that looks like...
cc @jackparmer @chriddyp @nicolaskruchten @sglyon