From ff08afe6d031ef594fe834cdedbc138f0f7f73c5 Mon Sep 17 00:00:00 2001 From: Thomas Guillod Date: Tue, 6 Jun 2023 18:15:51 -0400 Subject: [PATCH] add theme for the plots --- examples/config/plotter.json | 224 ++++++++++++------- examples/config/viewer.json | 42 ++-- examples/generate_plot.py | 29 ++- pypeec/lib_check/check_data_visualization.py | 47 +++- pypeec/lib_visualization/manage_pyvista.py | 47 ++-- 5 files changed, 265 insertions(+), 124 deletions(-) diff --git a/examples/config/plotter.json b/examples/config/plotter.json index a14e0513..41ced5b0 100644 --- a/examples/config/plotter.json +++ b/examples/config/plotter.json @@ -18,6 +18,7 @@ ] }, "data_plot": { + "plot_title": "Material", "plot_type": "material", "data_options": { "color_electric": "darkorange", @@ -31,12 +32,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Material", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -74,6 +78,7 @@ ] }, "data_plot": { + "plot_title": "El. Potential", "plot_type": "scalar_voxel", "data_options": { "var": "V_c_abs", @@ -90,12 +95,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "El. Potential", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -133,6 +141,7 @@ ] }, "data_plot": { + "plot_title": "Mag. Potential", "plot_type": "scalar_voxel", "data_options": { "var": "V_m_abs", @@ -149,12 +158,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Mag. Potential", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -192,6 +204,7 @@ ] }, "data_plot": { + "plot_title": "El. Source", "plot_type": "scalar_voxel", "data_options": { "var": "S_c_abs", @@ -208,12 +221,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "El. Source", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -251,6 +267,7 @@ ] }, "data_plot": { + "plot_title": "Mag. Source", "plot_type": "scalar_voxel", "data_options": { "var": "Q_m_abs", @@ -267,12 +284,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Mag. Source", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -310,6 +330,7 @@ ] }, "data_plot": { + "plot_title": "El. Losses", "plot_type": "scalar_voxel", "data_options": { "var": "P_c_abs", @@ -326,12 +347,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "El. Losses", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -369,6 +393,7 @@ ] }, "data_plot": { + "plot_title": "Mag. Losses", "plot_type": "scalar_voxel", "data_options": { "var": "P_m_abs", @@ -385,12 +410,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Mag. Losses", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -428,6 +456,7 @@ ] }, "data_plot": { + "plot_title": "Current", "plot_type": "scalar_voxel", "data_options": { "var": "J_c_norm_abs", @@ -444,12 +473,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Current", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -487,6 +519,7 @@ ] }, "data_plot": { + "plot_title": "Re. Current", "plot_type": "arrow_voxel", "data_options": { "var_scalar": "J_c_norm_re", @@ -505,12 +538,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Re. Current", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -548,6 +584,7 @@ ] }, "data_plot": { + "plot_title": "Im. Current", "plot_type": "arrow_voxel", "data_options": { "var_scalar": "J_c_norm_im", @@ -566,12 +603,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Im. Current", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -609,6 +649,7 @@ ] }, "data_plot": { + "plot_title": "Flux Density", "plot_type": "scalar_voxel", "data_options": { "var": "B_m_norm_abs", @@ -625,12 +666,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Flux Density", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -668,6 +712,7 @@ ] }, "data_plot": { + "plot_title": "Re. Flux Density", "plot_type": "arrow_voxel", "data_options": { "var_scalar": "B_m_norm_re", @@ -686,12 +731,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Re. Flux Density", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -729,6 +777,7 @@ ] }, "data_plot": { + "plot_title": "Im. Flux Density", "plot_type": "arrow_voxel", "data_options": { "var_scalar": "B_m_norm_im", @@ -747,12 +796,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Im. Flux Density", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -790,6 +842,7 @@ ] }, "data_plot": { + "plot_title": "Mag. Field Norm", "plot_type": "scalar_point", "data_options": { "var": "H_norm_abs", @@ -806,12 +859,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Mag. Field Norm", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -849,6 +905,7 @@ ] }, "data_plot": { + "plot_title": "Re. Mag. Field", "plot_type": "arrow_point", "data_options": { "var_scalar": "H_norm_re", @@ -867,12 +924,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Re. Mag. Field", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -910,6 +970,7 @@ ] }, "data_plot": { + "plot_title": "Im. Mag. Field", "plot_type": "arrow_point", "data_options": { "var_scalar": "H_norm_im", @@ -928,12 +989,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Im. Mag. Field", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", diff --git a/examples/config/viewer.json b/examples/config/viewer.json index dcb48761..72ff5dd3 100644 --- a/examples/config/viewer.json +++ b/examples/config/viewer.json @@ -18,6 +18,7 @@ ] }, "data_plot": { + "plot_title": "Domain", "plot_type": "domain", "data_options": { "colormap": "Accent", @@ -29,12 +30,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Domain", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -72,6 +76,7 @@ ] }, "data_plot": { + "plot_title": "Connection", "plot_type": "connection", "data_options": { "colormap": "Accent", @@ -83,12 +88,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Connection", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", @@ -126,6 +134,7 @@ ] }, "data_plot": { + "plot_title": "Voxelization", "plot_type": "voxelization", "data_options": { "color_voxel": "red", @@ -139,12 +148,15 @@ "clip_axis": "z", "clip_value": 0.0 }, - "plot_options": { - "title_text": "Voxelization", - "title_color": "black", - "title_font": 10.0, + "plot_theme": { + "text_color": "black", + "title_font": 10, + "colorbar_font": 15, + "colorbar_size": 5, "background_color": "gray", - "axis_size": 2.0, + "axis_size": 2 + }, + "plot_options": { "grid_plot": true, "grid_thickness": 1.0, "grid_color": "black", diff --git a/examples/generate_plot.py b/examples/generate_plot.py index 1945d812..f6f56d75 100644 --- a/examples/generate_plot.py +++ b/examples/generate_plot.py @@ -16,18 +16,13 @@ FOLDER_CONFIG = examples_config.FOLDER_CONFIG -def _get_plot_options(name): +def _get_plot_options(): """ The plot options are controlling the 3D wireframe rendering. This structure is used by the viewer and the plotter. """ plot_options = { - "title_text": name, # name displayed on the window corner - "title_color": "black", # color of the text displayed on the window corner - "title_font": 10.0, # font size of the text displayed on the window corner - "background_color": "gray", # background color of the plot - "axis_size": 2.0, # size of the axis marker "grid_plot": True, # plot (or not) the complete voxel geometry as wireframe "grid_thickness": 1.0, # line thickness for the complete voxel geometry "grid_color": "black", # line opacity for the complete voxel geometry @@ -48,6 +43,24 @@ def _get_plot_options(name): return plot_options +def _get_plot_theme(): + """ + The plot theme are is controlling the 3D plot color and size. + This structure is used by the viewer and the plotter. + """ + + plot_theme = { + "text_color": "black", # color of the text + "title_font": 10, # font size of the text displayed on the window corner + "colorbar_font": 15, # font size of the color bar + "colorbar_size": 5, # number of division for the colorbar + "background_color": "gray", # background color of the plot + "axis_size": 2, # size of the axis marker + } + + return plot_theme + + def _get_clip_options(): """ Define the 3D display (with/without clipping plane). @@ -245,10 +258,12 @@ def _get_data_pyvista(plot_type, data_options, name): "plot_framework": "pyvista", "data_window": _get_data_window(name), "data_plot": { + "plot_title": name, "plot_type": plot_type, "data_options": data_options, "clip_options": _get_clip_options(), - "plot_options": _get_plot_options(name), + "plot_theme": _get_plot_theme(), + "plot_options": _get_plot_options(), }, } diff --git a/pypeec/lib_check/check_data_visualization.py b/pypeec/lib_check/check_data_visualization.py index ccefa9ac..167163f1 100644 --- a/pypeec/lib_check/check_data_visualization.py +++ b/pypeec/lib_check/check_data_visualization.py @@ -34,7 +34,46 @@ def _check_data_window(data_window): def _check_plot_options(plot_options): """ Check the validity of the plot options (for the viewer and plotter). - The plot options are controlling the wireframe rendering. + The plot options are controlling the 3D wireframe rendering. + """ + + # check type + key_list = [ + "grid_plot", "grid_thickness", "grid_color", "grid_opacity", + "geom_plot", "geom_thickness", "geom_color", "geom_opacity", + "point_plot", "point_size", "point_color", "point_opacity", + "camera_roll", "camera_azimuth", "camera_elevation", + ] + datachecker.check_dict("data_window", plot_options, key_list=key_list) + + # check grid data + datachecker.check_boolean("grid_plot", plot_options["grid_plot"]) + datachecker.check_string("grid_color", plot_options["grid_color"], can_be_empty=False) + datachecker.check_float("grid_thickness", plot_options["grid_thickness"], is_positive=True, can_be_zero=True) + datachecker.check_float("grid_opacity", plot_options["grid_opacity"], is_positive=True, can_be_zero=True) + + # check geom data + datachecker.check_boolean("geom_plot", plot_options["geom_plot"]) + datachecker.check_string("geom_color", plot_options["geom_color"], can_be_empty=False) + datachecker.check_float("geom_thickness", plot_options["geom_thickness"], is_positive=True, can_be_zero=True) + datachecker.check_float("geom_opacity", plot_options["geom_opacity"], is_positive=True, can_be_zero=True) + + # check cloud data + datachecker.check_boolean("point_plot", plot_options["point_plot"]) + datachecker.check_string("point_color", plot_options["point_color"], can_be_empty=False) + datachecker.check_float("point_size", plot_options["point_size"], is_positive=True, can_be_zero=True) + datachecker.check_float("point_opacity", plot_options["point_opacity"], is_positive=True, can_be_zero=True) + + # check camera data + datachecker.check_float("camera_roll", plot_options["camera_roll"], can_be_none=True) + datachecker.check_float("camera_azimuth", plot_options["camera_azimuth"], can_be_none=True) + datachecker.check_float("camera_elevation", plot_options["camera_elevation"], can_be_none=True) + + +def _check_plot_theme(plot_options): + """ + Check the validity of the plot theme (for the viewer and plotter). + The plot options are controlling the 3D plot color and size. """ # check type @@ -285,10 +324,11 @@ def _check_data_plotter_pyvista(data_plot): """ # check type - key_list = ["plot_type", "clip_options", "data_options", "plot_options"] + key_list = ["plot_title", "plot_type", "clip_options", "data_options", "plot_options"] datachecker.check_dict("data_plot", data_plot, key_list=key_list) # extract the data + plot_title = data_plot["plot_title"] plot_type = data_plot["plot_type"] data_options = data_plot["data_options"] clip_options = data_plot["clip_options"] @@ -297,6 +337,9 @@ def _check_data_plotter_pyvista(data_plot): # check plot type datachecker.check_choice("plot_type", plot_type, ["material", "scalar_voxel", "scalar_point", "arrow_voxel", "arrow_point"]) + # check title data + datachecker.check_string("plot_title", plot_title, can_be_empty=False) + # check data _check_data_options_plotter_pyvista(plot_type, data_options) _check_clip_options(clip_options) diff --git a/pypeec/lib_visualization/manage_pyvista.py b/pypeec/lib_visualization/manage_pyvista.py index d9b2fed6..1a65a99b 100644 --- a/pypeec/lib_visualization/manage_pyvista.py +++ b/pypeec/lib_visualization/manage_pyvista.py @@ -25,7 +25,7 @@ import numpy.linalg as lna -def _get_plot_options(pl, grid, voxel, point, plot_options): +def _get_plot_options(pl, grid, voxel, point, plot_title, plot_options, plot_theme): """ Plot the geometry as wireframe (complete grid and non-empty voxels). Plot the point cloud used for the field evaluation. @@ -73,15 +73,16 @@ def _get_plot_options(pl, grid, voxel, point, plot_options): # add title and axes pl.add_axes( - line_width=plot_options["axis_size"], + line_width=plot_theme["axis_size"], + color=plot_theme["text_color"], interactive=False, ) pl.add_text( - plot_options["title_text"], - color=plot_options["title_color"], - font_size=plot_options["title_font"], + plot_title, + font_size=plot_theme["title_font"], + color=plot_theme["text_color"], ) - pl.set_background(plot_options["background_color"]) + pl.set_background(plot_theme["background_color"]) def _get_clip_mesh(pl, obj, arg, clip_options): @@ -208,7 +209,7 @@ def _get_clamp_scale_scalar(obj, var, color_lim, scale): return obj -def _plot_scalar(pl, obj, data_options, clip_options): +def _plot_scalar(pl, obj, data_options, clip_options, plot_theme): """ Plot a scalar variable. The plot is either made on: @@ -227,10 +228,11 @@ def _plot_scalar(pl, obj, data_options, clip_options): # color bar options scalar_bar_args = dict( - n_labels=5, - label_font_size=15, - title_font_size=15, title=legend, + n_labels=plot_theme["colorbar_size"], + label_font_size=plot_theme["colorbar_font"], + title_font_size=plot_theme["colorbar_font"], + color=plot_theme["text_color"], ) # scale and clamp the variable @@ -250,7 +252,7 @@ def _plot_scalar(pl, obj, data_options, clip_options): _get_clip_mesh(pl, obj_tmp, arg, clip_options) -def _plot_arrow(pl, grid, obj, data_options, clip_options): +def _plot_arrow(pl, grid, obj, data_options, clip_options, plot_theme): """ Plot a vector variable with an arrow plot (quiver plot). The plot is either made on: @@ -274,10 +276,11 @@ def _plot_arrow(pl, grid, obj, data_options, clip_options): # color bar options scalar_bar_args = dict( - n_labels=5, - label_font_size=15, - title_font_size=15, title=legend, + n_labels=plot_theme["colorbar_size"], + label_font_size=plot_theme["colorbar_font"], + title_font_size=plot_theme["colorbar_font"], + color=plot_theme["text_color"], ) # scale and clamp the variable @@ -396,10 +399,12 @@ def get_plot_viewer(pl, grid, voxel, point, reference, data_plot): """ # extract the data + plot_title = data_plot["plot_title"] plot_type = data_plot["plot_type"] data_options = data_plot["data_options"] clip_options = data_plot["clip_options"] plot_options = data_plot["plot_options"] + plot_theme = data_plot["plot_theme"] # get the main plot if plot_type == "domain": @@ -412,7 +417,7 @@ def get_plot_viewer(pl, grid, voxel, point, reference, data_plot): raise ValueError("invalid plot type and plot feature") # add the wireframe and axis - _get_plot_options(pl, grid, voxel, point, plot_options) + _get_plot_options(pl, grid, voxel, point, plot_title, plot_options, plot_theme) def get_plot_plotter(pl, grid, voxel, point, data_plot): @@ -427,24 +432,26 @@ def get_plot_plotter(pl, grid, voxel, point, data_plot): """ # extract the data + plot_title = data_plot["plot_title"] plot_type = data_plot["plot_type"] data_options = data_plot["data_options"] clip_options = data_plot["clip_options"] plot_options = data_plot["plot_options"] + plot_theme = data_plot["plot_theme"] # get the main plot if plot_type == "material": _plot_material(pl, voxel, data_options, clip_options) elif plot_type == "scalar_voxel": - _plot_scalar(pl, voxel, data_options, clip_options) + _plot_scalar(pl, voxel, data_options, clip_options, plot_theme) elif plot_type == "scalar_point": - _plot_scalar(pl, point, data_options, clip_options) + _plot_scalar(pl, point, data_options, clip_options, plot_theme) elif plot_type == "arrow_voxel": - _plot_arrow(pl, grid, voxel, data_options, clip_options) + _plot_arrow(pl, grid, voxel, data_options, clip_options, plot_theme) elif plot_type == "arrow_point": - _plot_arrow(pl, grid, point, data_options, clip_options) + _plot_arrow(pl, grid, point, data_options, clip_options, plot_theme) else: raise ValueError("invalid plot type and plot feature") # add the wireframe and axis - _get_plot_options(pl, grid, voxel, point, plot_options) + _get_plot_options(pl, grid, voxel, point, plot_title, plot_options, plot_theme)