Skip to content

Commit

Permalink
Merge branch 'develop' into 141-add-arrow-marker-type
Browse files Browse the repository at this point in the history
  • Loading branch information
bbean23 authored Aug 7, 2024
2 parents f3e689e + b8ca8f7 commit 3438a8a
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 20 deletions.
6 changes: 5 additions & 1 deletion opencsp/common/lib/render/View3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,11 @@ def save(self, output_dir, output_figure_body, format='png', dpi=300) -> str:
# Save the figure.
output_figure_dir_body_ext = output_figure_dir_body + '.' + format
lt.info('In View3d.save(), saving figure: ' + output_figure_dir_body_ext)
# plt.savefig(output_figure_dir_body_ext, format=format, dpi=dpi)
self.view.set_size_inches(self.view.get_figwidth(), self.view.get_figheight(), forward=True)
# it could be that another backend requires the following instead:
# self.view.set_figwidth(self.view.get_figwidth() * dpi)
# self.view.set_figheight(self.view.get_figheight() * dpi)
self.view.set_dpi(dpi)
self.view.savefig(output_figure_dir_body_ext, format=format, dpi=dpi)
# Return the outptu file path and directory.
return output_figure_dir_body_ext
Expand Down
12 changes: 11 additions & 1 deletion opencsp/common/lib/render/figure_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,17 @@ def _setup_figure(
upper_left_xy = figure_control.upper_left_xy
x = upper_left_xy[0]
y = upper_left_xy[1]
fig.canvas.manager.window.move(x, y)
window = fig.canvas.manager.window
if hasattr(window, "move"):
window.move(x, y) # qt
else:
window.geometry(f"+{x}+{y}") # tkinter
if figure_control.maximize:
window = fig.canvas.manager.window
if hasattr(window, "showMaximized"):
window.showMaximized() # qt
else:
window.state("zoomed") # tkinter
# Copying this command, as from Randy, which suppresses duplicate axes in tile_figure(). ~ BGB
plt.axis('off')

Expand Down
105 changes: 95 additions & 10 deletions opencsp/common/lib/render/test/test_figure_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
import unittest

import matplotlib.pyplot as plt
from PIL import Image

import opencsp.common.lib.render.figure_management as fm
import opencsp.common.lib.render.test.lib.RenderControlFigureRecordInfSave as rcfr_is
import opencsp.common.lib.render.view_spec as vs
import opencsp.common.lib.render_control.RenderControlAxis as rca
import opencsp.common.lib.render_control.RenderControlFigure as rcfg
import opencsp.common.lib.render.test.lib.RenderControlFigureRecordInfSave as rcfr_is
import opencsp.common.lib.tool.file_tools as ft

is_original_call = "--funcname" in sys.argv
Expand All @@ -18,14 +21,15 @@ class test_figure_management(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
path, name, _ = ft.path_components(__file__)
cls.dir_in = ft.join(path, 'data/input', name.split('test_')[-1])
cls.dir_out = ft.join(path, 'data/output', name.split('test_')[-1])

ret = super().setUpClass()
ft.create_directories_if_necessary(cls.dir_out)
cls.in_dir = ft.join(path, 'data/input', name.split('test_')[-1])
cls.out_dir = ft.join(path, 'data/output', name.split('test_')[-1])
ft.create_directories_if_necessary(cls.out_dir)
if is_original_call:
ft.delete_files_in_directory(cls.dir_out, "*")
return ret
ft.delete_files_in_directory(cls.out_dir, "*")
return super().setUpClass()

def setUp(self) -> None:
self.test_name = self.id().split('.')[-1]

def setUp(self) -> None:
self.test_name = self.id().split('.')[-1]
Expand Down Expand Up @@ -58,7 +62,7 @@ def test_save_all_figures_line(self):
line = list(range(100))
view.draw_p_list(line)

figs_txts = fm.save_all_figures(self.dir_out)
figs_txts = fm.save_all_figures(self.out_dir)
self.assert_exists(figs_txts, 1)

def test_save_all_figures_two_lines(self):
Expand All @@ -76,7 +80,7 @@ def test_save_all_figures_two_lines(self):
line = lines[i]
view.draw_p_list(line)

figs_txts = fm.save_all_figures(self.dir_out)
figs_txts = fm.save_all_figures(self.out_dir)
self.assert_exists(figs_txts, 2)

def _figure_manager_timeout_1(self):
Expand Down Expand Up @@ -106,6 +110,87 @@ def _figure_manager_timeout_1(self):

return fm

def test_upper_left_xy_no_exception(self):
"""
Verify that figure_management._setup_figure() with the figure control
parameter "upper_left_xy" set doesn't raise an exception.
"""
# TODO how to test that the window has actually been located correctly?
axis_control = rca.meters()
figure_control = rcfg.RenderControlFigure(tile=False, upper_left_xy=(100, 100))
view_spec_2d = vs.view_spec_xy()
fig_record = fm.setup_figure(
figure_control,
axis_control,
view_spec_2d,
title=self.test_name,
code_tag=f"{__file__}.{self.test_name}",
equal=False,
)
fig_record.view.show()
fig_record.close()

def test_maximize_no_exception(self):
"""
Verify that figure_management._setup_figure() with the figure control
parameter "maximize" set doesn't raise an exception.
"""
# TODO how to test that the window has actually been maximized?
axis_control = rca.meters()
figure_control = rcfg.RenderControlFigure(tile=False, maximize=True)
view_spec_2d = vs.view_spec_xy()
try:
fig_record = fm.setup_figure(
figure_control,
axis_control,
view_spec_2d,
title=self.test_name,
code_tag=f"{__file__}.{self.test_name}",
equal=False,
)
fig_record.view.show()
fig_record.close()
except Exception as ex:
ubi8_msg = '_tkinter.TclError: bad argument "zoomed": must be normal, iconic, or withdrawn'
if ubi8_msg in str(ex):
# TODO how to make this test work on ubi8?
self.skipTest("Window 'maximize' state doesn't working on our ubi8 test docker image.")

def test_save_figsize(self):
"""Verify that the size of the saved figure is as given in the save parameters."""
# create and save the figure with pixel sizes:
# small: 900 x 600
# regular: 1800 x 1200
# large: 2700 x 1800
axis_control = rca.meters()
figure_control = rcfg.RenderControlFigure(tile=False, figsize=(3, 2))
view_spec_2d = vs.view_spec_xy()
fig_record = fm.setup_figure(
figure_control,
axis_control,
view_spec_2d,
title=self.test_name,
code_tag=f"{__file__}.{self.test_name}",
equal=False,
)
# fig_record.view.show()
fig_record.save(self.out_dir, f"{self.test_name}_small", format="png", dpi=300, close_after_save=False)
fig_record.save(self.out_dir, f"{self.test_name}_regular", format="png", dpi=600, close_after_save=False)
fig_record.save(self.out_dir, f"{self.test_name}_large", format="png", dpi=900, close_after_save=False)
fig_record.view.show()
fig_record.close()

# load the images and verify their size in pixels
with Image.open(ft.join(self.out_dir, f"{self.test_name}_small_xy.png")) as img_small:
self.assertEqual(img_small.width, 900)
self.assertEqual(img_small.height, 600)
with Image.open(ft.join(self.out_dir, f"{self.test_name}_regular_xy.png")) as img_regular:
self.assertEqual(img_regular.width, 1800)
self.assertEqual(img_regular.height, 1200)
with Image.open(ft.join(self.out_dir, f"{self.test_name}_large_xy.png")) as img_large:
self.assertEqual(img_large.width, 2700)
self.assertEqual(img_large.height, 1800)


if __name__ == '__main__':
import argparse
Expand Down
32 changes: 24 additions & 8 deletions opencsp/common/lib/render_control/RenderControlFigure.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ class RenderControlFigure:
def __init__(
self,
tile=True, # True => Lay out figures in grid. False => Place at upper_left or default screen center.
tile_array=(3, 2), # (n_x, n_y)
tile_array: tuple[int, int] = (3, 2), # (n_x, n_y)
tile_square=False, # Set to True for equal-axis 3d plots.
figsize=(6.4, 4.8), # inch.
upper_left_xy=None, # pixel. (0,0) --> Upper left corner of screen.
grid=True,
maximize=False,
): # Whether or not to draw grid lines.
"""Set of controls for how to render figures.
Expand All @@ -35,13 +36,27 @@ def __init__(
view.draw_pq_list(energy_values, style=style)
view.show(block=True)
Args:
- tile (bool): True => Lay out figures in grid. False => Place at upper_left or default screen center. Default True
- tile_array (tuple[int]): How many tiles across and down (n_x, n_y). Default (3, 2)
- tile_square (bool): Set to True for equal-axis 3d plots. Default False
- figsize (tuple[float]): Size of the figure in inches. Default (6.4, 4.8)
- upper_left_xy (tuple[int]): Pixel placement for the first tile. (0,0) --> Upper left corner of screen. Default None
- grid (bool): Whether or not to draw grid lines. Note: this value seems to be inverted. Default True
Params:
-------
tile : bool, optional
True => Lay out figures in grid. False => Place at upper_left or
default screen center. If True, then figsize, upper_left_xy, and
maximize are ignored. Default True
tile_array : tuple[int] | None, optional
How many tiles across and down (n_x, n_y).
tile_square : bool, optional
Set to True for equal-axis 3d plots. Default False
figsize : tuple[float], optional
Size of the figure in inches. Ignored if tile is True. Default (6.4, 4.8)
upper_left_xy : tuple[int], optional
Pixel placement for the first tile. (0,0) --> Upper left corner of
screen. Ignored if tile is True. Default None
grid : bool, optional
Whether or not to draw grid lines. Note: this value seems to be
inverted. Default True
maximize : bool, optional
Whether the figure should be maximized (made full screen) as soon as
it is made visible. Ignored if tile is True. Default False.
"""

super(RenderControlFigure, self).__init__()
Expand All @@ -55,6 +70,7 @@ def __init__(
# Figure size and placement.
self.figsize = figsize
self.upper_left_xy = upper_left_xy
self.maximize = maximize

# Axis control.
self.x_label = 'x (m)'
Expand Down

0 comments on commit 3438a8a

Please sign in to comment.