Plotting template¶
Usage¶
Plot objects that inherit from the template plot classes have the following properties.
Fast plotting by use of
matplotlib.canvas.blit
.Redrawing past iterations of the figure by storing all changes in history.
Keyboard navigation for iteration selection.
Plot object information by picking.
When the focus is on the figure, indicated by a green circle in the bottom right corner, the user can navigate through the history of the figure by the commands below.
key |
function |
---|---|
h |
show help |
i |
show all iterations |
enter or right |
go to next iteration, enter iteration number |
backspace or left |
go to previous iteration |
n |
go to newest iteration |
0-9 |
input iteration number |
If the focus is lost, it can be regained by calling template.focus
on the plot object.
Default values for plot properties such as colors and linewidths are saved in a plot.ini file. Any plot property can be overwritten by supplying the override value as a keyword argument during object initialization or a custom plot.ini file in the working directory.
Development¶
-
class
qsurface.plot.
PlotParams
(blocking_wait=- 1, blocking_pick_radius=10, scale_figure_length=10, scale_figure_height=10, scale_font_primary=12, scale_font_secondary=10, scale_3d_layer=8, color_background=1, 1, 1, 0, color_edge=0.8, 0.8, 0.8, 1, color_qubit_edge=0.7, 0.7, 0.7, 1, color_qubit_face=0.95, 0.95, 0.95, 1, color_x_primary=0.9, 0.3, 0.3, 1, color_z_primary=0.5, 0.5, 0.9, 1, color_y_primary=0.9, 0.9, 0.5, 1, color_x_secondary=0.9, 0.7, 0.3, 1, color_z_secondary=0.3, 0.9, 0.3, 1, color_y_secondary=0.9, 0.9, 0.5, 1, color_x_tertiary=0.5, 0.1, 0.1, 1, color_z_tertiary=0.1, 0.1, 0.5, 1, color_y_tertiary=0.9, 0.9, 0.5, 1, alpha_primary=0.35, alpha_secondary=0.5, line_width_primary=1.5, line_width_secondary=3, line_style_primary='solid', line_style_secondary='dashed', line_style_tertiary='dotted', patch_circle_2d=0.1, patch_rectangle_2d=0.1, patch_circle_3d=30, patch_rectangle_3d=30, axis_main=0.075, 0.1, 0.7, 0.85, axis_main_non_interact=0.0, 0.05, 0.8, 0.9, axis_block=0.96, 0.01, 0.03, 0.03, axis_nextbutton=0.85, 0.05, 0.125, 0.05, axis_prevbutton=0.85, 0.12, 0.125, 0.05, axis_legend=0.85, 0.5, 0.125, 0.3, axis_text=0.05, 0.025, 0.7, 0.05, axis_radio=0.85, 0.19, 0.125, 0.125, font_default_size=12, font_title_size=16, font_button_size=12, axis3d_pane_color=1, 1, 1, 0, axis3d_line_color=0, 0, 0, 0.1, axis3d_grid_line_style='dotted', axis3d_grid_line_alpha=0.2)¶ Parameters for the plotting template classes.
Contains all parameters used in inherited objects of
Template2D
andTemplate3D
. The dataclass is initialized with many default values for an optimal plotting experience. But if any parameters should be changed, the user can call the class to create its own instance of plotting paramters, where the altered paramters are supplied as keyword arguments. The instance can be supplied to the plotting class via theplot_params
keyword argument.Examples
See the below example where the background color of the figure is changed to black. Note that we have to inherit from the
Template2D
class.>>> class Plotting(Template2D): ... pass >>> custom_params = PlotParams(color_background = (0,0,0,1)) >>> plot_with_custom_params = Plotting(plot_params=custom_params)
-
load_params
(param_dict)¶ Loads extra plotting parameters.
Additional parameters can be loaded to the dataclass via this method. The additional parameters must be a dictionary where values are stored to the dataclass with the key as attribute name. If the value is a string that equals to any already defined dataclass attribute, the value at the existing attribute is used for the new parameter. See examples.
- Parameters
params_dict – Dictionary or dictionary of dictionaries of additional parameters.
Examples
New parameters can be added to the dataclass. Values of dataclass attributes are used if present.
>>> params = PlotParams() >>> params.alpha_primary 0.35 >>> params.load_params({ ... "new_attr" : "some_value", ... "use_existing" : "alpha_primary", ... }) >>> params.new_attr some_value >>> params.use_existing 0.35
Nested dictionaries will also load existing attribute values.
>>> params.load_params({ ... "category": { ... "new_attr" : "some_value", ... "use_existing" : "alpha_primary", ... } ... }) >>> params.category {"new_attr" : "some_value", "use_existing" : 0.35}
-
-
class
qsurface.plot.
BlockingKeyInput
(*args, **kwargs)¶ Blocking class to receive key presses.
See also
None
Inherited blocking class.
-
class
qsurface.plot.
Template2D
(plot_params=None, projection=None, **kwargs)¶ Template 2D plot object with history navigation.
This template plot object which can either be an interactive figure using the Tkinter backend, or shows each plotting iteration as a separate figure for the IPython
inline
backend. The interactive figure has the following features.Fast plotting by use of “blitting”.
Redrawing past iterations of the figure by storing all changes in history.
Keyboard navigation for iteration selection.
Plot object information by picking.
To instance this class, one must inherit the current class. The existing objects can then be altered by updating their plot properties by
new_properties()
, where the changed properties must be a dictionary with keywords and values corresponding tho the respective matplotlib object. Every change in plot property is stored inself.history_dict
. This allows to undo or redo changes by simply applying the saved changed properties in the dictionary. Fast plotting is enabled by not drawing the figure after every queued change. Instead, each object is draw in the canvas individually after a property change and a series of changes is drawn to the figure when a new plot iteration is requested vianew_iter()
. This is performed by blitting the canvas.Keyboard navigation and picking is enabled by blocking the code via a custom
BlockingKeyInput
class. While the code is blocked, inputs are caught by the blocking class and processed for history navigation or picking navigation. Moving the iteration past the available history allows for the code to continue. The keyboard input is parsed byfocus()
.Default values for plot properties such as colors and linewidths loaded from
PlotParams
. A custom parameter dataclass can be supplied via theplot_params
keyword argument.- Parameters
plot_params (
Optional
[PlotParams
]) – Plotting parameters dataclass containing colors, styles and others.
-
figure
¶ Main figure.
-
main_ax
¶ Main axis of the figure.
- Type
-
history_dict
¶ For each iteration, for every plot object with changed properties, the properties are stored as a nested dictionary. See the example below.
>>> history_dict = { 0: { "<Line2D object>": { "color": "k", }, "<Circle object>": { "linestyle": "-", } } 1: { "<Line2D object>": { "color": "r", }, "<Circle object>": { "linestyle": ":", } } }
-
history_iter_names
¶ List of length
history_iters
containing a title for each iteration.- Type
list of str
-
future_dict
¶ Same as
history_dict
but for changes for future iterations.
-
temporary_changes
¶ Temporary changes for plot properties, requested by
temporary_properties()
, which are immediately drawn to the figure. These properties can be overwritten or undone before a new iteration is requested vianew_iter()
. When a new iteration is requested, we need to find the difference in properties of the queued changes with the current iteration and save all differences toself.history_dict
.
-
temporary_saved
¶ Temporary changes are saved to the current iteration
iter
. Thus when a new iterationiter + 1
is requested, we need to recalculate the differences of the properties initer-1
and the current iteration with the temporary changes. The previous property values when temporary changes are requested bytemporary_properties()
are saved toself.temporary_saved
and used as the property changes foriter-1
.
-
interact_axes
¶ All iteractive elements should have their own axis saved in
self.interact_axes
. Theaxis.active
attribute must be added to define when the axis is shown. If the focus on the figure is lost, all axes inself.interact_axes
are hidden by settingaxis.active=False
.- Type
dict of
matplotlib.axes.Axes
-
interact_bodies
¶ All interactive elements such as buttons, radiobuttons, sliders, should be saved to this dictionary with the same key as their axes in
self.interact_axes
.- Type
Notes
Note all backends support blitting. It does not work with the OSX backend (but does work with other GUI backends on mac).
Examples
A
matplotlib.lines.Line2D
object is initiated withcolor="k"
andls="-"
. We request that the color of the object is red in a new plot iteration.>>> import matplotlib.pyplot as plt ... class Example(Template2D): ... def __init__(self, *args, **kwargs): ... super().__init__(*args, **kwargs) ... self.line = plt.plot(0, 0, color="k", ls="-")[0] # Line located at [0] after plot >>> fig = Example() >>> fig.new_properties(fig.line, {"color": "r}) >>> fig.new_iter() >>> fig.history_dict { 0: {"<Line2D>": {"color": "k"}}, 1: {"<Line2D>": {"color": "r"}}, }
The attribute
self.history_dict
thus only contain changes to plot properties. If we request another iteration but change the linestyle to “:”, the initial linestyle will be saved to iteration 1.>>> fig.new_properties(fig.line, {"ls": ":"}) >>> fig.new_iter() >>> fig.history_dict { 0: {"<Line2D>": {"color": "k"}}, 1: {"<Line2D>": {"color": "r", "ls: "-"}}, 2: {"<Line2D>": {ls: ":"}}, }
We temporarily alter the linewidth to 2, and then to 1.5. After we are satisfied with the temporary changes. we request a new iteration with the final change of color to green.
>>> fig.temporary_properties(fig.line, {"lw": 2}) >>> fig.temporary_properties(fig.line, {"lw": 1.5}) >>> fig.temporary_changes {"<Line2D>": {"lw": 1.5}} >>> fig.temporary_saved {"<Line2D>": {"lw": 1}} # default value >>> fig.new_properties(fig.line, {"color": "g"}) >>> fig.new_iter() >>> fig.history_dict { 0: {"<Line2D>": {"color": "k"}}, 1: {"<Line2D>": {"color": "r", "ls: "-", "lw": 1}}, 2: {"<Line2D>": {"lw": 1.5, color": "r"}, 3: {"<Line2D>": {"color": "g"}}, }
Properties in
self.temporary_saved
are saved toself.history_dict
in the previous iteration, properties inself.temporary_changes
are saved to the current iteration, and new properties are saved to the new iteration.The
history_dict
for a plot with a Line2D object and a Circle object. In the second iteration, the color of the Line2D object is updated from black to red, and the linestyle of the Circle object is changed from “-” to “:”.-
load_interactive_backend
()¶ Configures the plotting backend.
If the Tkinter backend is enabled or can be enabled, the function returns True. For other backends False is returned.
- Return type
-
close
()¶ Closes the figure.
-
focus
()¶ Enables the blocking object, catches input for history navigation.
The BlockingKeyInput object is called which blocks the execution of the code. During this block, the user input is received by the blocking object and return to the current method. From here, we can manipulate the plot or move through the plot history and call
focus()
again when all changes in the history have been drawn and blit.key
function
h
show help
i
show all iterations
d
redraw current iteration
enter or right
go to next iteration, enter iteration number
backspace or left
go to previous iteration
n
go to newest iteration
0-9
input iteration number
When the method is active, the focus is on the figure. This will be indicated by a green circle in the bottom right of the figure. When the focus is lost, the code execution is continued and the icon is red. The change is icon color is performed by
_set_figure_state()
, which also hides the interactive elements when the focus is lost.
-
draw_figure
(new_iter_name=None, output=True, carriage_return=False, **kwargs)¶ Draws the canvas and blocks code execution.
Draws the queued plot changes onto the canvas and calls for
focus()
which blocks the code execution and catches user input for history navigation.If a new iteration is called by supplying a
new_iter_name
, we additionally check for future property changes in theself.future_dict
, and add these changes to the queue. Finally, all queued property changes for the next iteration are applied bychange_properties
.- Parameters
See also
-
new_artist
(artist, axis=None)¶ Adds a new artist to the
axis
.Newly added artists must be hidden in the previous iteration. To make sure the history is properly logged, the visibility of the
artist
is set toFalse
, and a new property of shown visibility is added to the queue of the next iteration.
-
static
change_properties
(artist, prop_dict)¶ Changes the plot properties and draw the plot object or artist.
-
new_properties
(artist, properties, saved_properties={}, **kwargs)¶ Parses a dictionary of property changes of a matplotlib artist.
New properties are supplied via
properties
. If any of the new properties is different from its current value, this is seen as a property change. The old property value is stored inself.history_dict[self.history_iteration]
, and the new property value is stored atself.history_dict[self.history_iteration+1]
. These new properties are queued for the next interation. The queue is emptied by applying all changes whendraw_figure
is called. If the same property changes 2+ times within the same iteration, the previous property change is removed withnext_prop.pop(key, None)
.The
saved_properties
parameter is used when temporary property changes have been applied bytemporary_changes
, in which the original properties are saved toself.temporary_saved
as the saved properties. Before a new iteration is drawn, the temporary changes, which can be overwritten, are compared with the saved changes and the differences in properties are saved to[self.history_dict[self.history_iter-1]]
andself.history_dict[self.history_iteration]
.Some color values from different matplotlib objects are nested, some are list or tuple, and others may be a
numpy.ndarray
. The nested methodsget_nested()
andget_nested_property()
make sure that the return type is always a list.
-
temporary_properties
(artist, properties, **kwargs)¶ Applies temporary property changes to a matplotlib artist.
Only available on the newest iteration, as we cannot change what is already in the past. All values in
properties
are immediately applied toartist
. Since temporary changes can be overwritten within the same iteration, the first time a temporary property change is requested, the previous value is saved toself.temporary_saved
. When the iteration changes, the property differences of the previous and current iteration are recomputed and saved toself.history_dict
in_draw_from_history()
.
-
class
qsurface.plot.
Template3D
(*args, **kwargs)¶ Template 3D plot object with history navigation.