From a9d242af62578635a983325d4bcbf3d07290e8e7 Mon Sep 17 00:00:00 2001 From: Evan Harvey Date: Mon, 11 Nov 2024 17:24:42 -0700 Subject: [PATCH] opencsp/common/lib/render: test docs --- opencsp/common/lib/render/Color.py | 288 +++++++++++++++++- opencsp/common/lib/render/PowerpointSlide.py | 4 + opencsp/common/lib/render/VideoHandler.py | 7 + .../common/lib/render/figure_management.py | 69 +++++ opencsp/common/lib/render/general_plot.py | 58 ++++ opencsp/common/lib/render/image_plot.py | 47 ++- .../common/lib/render/lib/PowerpointImage.py | 2 + .../common/lib/render/lib/PowerpointText.py | 35 +++ opencsp/common/lib/render/pandas_plot.py | 46 ++- opencsp/common/lib/render/view_spec.py | 139 ++++++++- .../RenderControlPowerpointSlide.py | 2 + .../render_control/RenderControlSurface.py | 4 + opencsp/test/test_DocStringsExist.py | 21 ++ 13 files changed, 698 insertions(+), 24 deletions(-) diff --git a/opencsp/common/lib/render/Color.py b/opencsp/common/lib/render/Color.py index e194e3b55..93fec05b5 100644 --- a/opencsp/common/lib/render/Color.py +++ b/opencsp/common/lib/render/Color.py @@ -49,10 +49,50 @@ def __init__(self, red: float, green: float, blue: float, name: str, short_name: @classmethod def from_i255(cls, red: int, green: int, blue: int, name: str, short_name: str): + """ + Creates a Color instance from 8-bit RGB values. + + Parameters + ---------- + red : int + The red component in the RGB color space (0-255). + green : int + The green component in the RGB color space (0-255). + blue : int + The blue component in the RGB color space (0-255). + name : str + A descriptive name for the color. + short_name : str + A shorthand name for the color. + + Returns + ------- + Color + A Color instance with the specified RGB values. + """ + # "ChatGPT 4o" assisted with generating this docstring. return cls(red / 255, green / 255, blue / 255, name, short_name) @classmethod def from_hex(cls, hexval: str, name: str, short_name: str) -> "Color": + """ + Creates a Color instance from a hexadecimal color string. + + Parameters + ---------- + hexval : str + The hexadecimal color string (e.g., "#RRGGBB"). + name : str + A descriptive name for the color. + short_name : str + A shorthand name for the color. + + Returns + ------- + Color + A Color instance with the RGB values extracted from the hexadecimal string. + """ + # "ChatGPT 4o" assisted with generating this docstring. if hexval.startswith("0x"): hexval = "#" + hexval[2:] elif hexval.startswith("x"): @@ -67,11 +107,47 @@ def from_hex(cls, hexval: str, name: str, short_name: str) -> "Color": @classmethod def from_hsv(cls, hue: float, saturation: float, value: float, name: str, short_name: str): + """ + Creates a Color instance from HSV values. + + Parameters + ---------- + hue : float + The hue component in the HSV color space (0-1). + saturation : float + The saturation component in the HSV color space (0-1). + value : float + The value (brightness) component in the HSV color space (0-1). + name : str + A descriptive name for the color. + short_name : str + A shorthand name for the color. + + Returns + ------- + Color + A Color instance with the RGB values converted from the HSV values. + """ + # "ChatGPT 4o" assisted with generating this docstring. rgb = matplotlib.colors.hsv_to_rgb((hue, saturation, value)) return cls(rgb[0], rgb[1], rgb[2], name, value) @classmethod def from_str(cls, sval='b') -> "Color": + """ + Creates a Color instance from a string representation. + + Parameters + ---------- + sval : str, optional + The string representation of the color (e.g., 'b' for blue). Defaults to 'b'. + + Returns + ------- + Color + A Color instance corresponding to the specified string representation. + """ + # "ChatGPT 4o" assisted with generating this docstring. longhand = sval if sval in _plot_color_shorthands: longhand = _plot_color_shorthands[sval] @@ -82,6 +158,20 @@ def from_str(cls, sval='b') -> "Color": @classmethod def convert(cls, val: Union["Color", str, tuple, None]) -> "Color": + """ + Converts various representations to a Color instance. + + Parameters + ---------- + val : Color | str | tuple | None + The value to convert, which can be a Color instance, a string, or a tuple of RGB values. + + Returns + ------- + Color + A Color instance corresponding to the input value. + """ + # "ChatGPT 4o" assisted with generating this docstring. if val is None: return None elif isinstance(val, Color): @@ -94,43 +184,92 @@ def convert(cls, val: Union["Color", str, tuple, None]) -> "Color": def rgb(self) -> tuple[float, float, float]: """ - Returns color in [R,G,B] format, with range [0,1] for each. + Returns the RGB values of the color. + + Returns + ------- + tuple[float, float, float] + A tuple containing the RGB values of the color, each in the range [0, 1]. """ + # "ChatGPT 4o" assisted with generating this docstring. return (self.red, self.green, self.blue) def rgba(self, alpha=1.0) -> tuple[float, float, float, float]: + """ + Returns the RGBA values of the color. + + Parameters + ---------- + alpha : float, optional + The alpha (transparency) value of the color. Defaults to 1.0 (fully opaque). + + Returns + ------- + tuple[float, float, float, float] + A tuple containing the RGBA values of the color, each in the range [0, 1]. + """ + # "ChatGPT 4o" assisted with generating this docstring. return (self.red, self.green, self.blue, alpha) def rgb_255(self) -> tuple[int, int, int]: """ - Returns color in [R,G,B] format, with range [0,255] for each. + Returns the RGB values of the color in the range [0, 255]. + + Returns + ------- + tuple[int, int, int] + A tuple containing the RGB values of the color, each in the range [0, 255]. """ + # "ChatGPT 4o" assisted with generating this docstring. return (int(self.red * 255), int(self.green * 255), int(self.blue * 255)) def to_hex(self) -> str: + """ + Converts the color to a hexadecimal string representation. + + Returns + ------- + str + The hexadecimal string representation of the color (e.g., "#RRGGBB"). + """ + # "ChatGPT 4o" assisted with generating this docstring. return matplotlib.colors.to_hex(self.rgb()).upper() def to_hsv(self) -> tuple[float, float, float]: + """ + Converts the RGB color to HSV representation. + + Returns + ------- + tuple[float, float, float] + A tuple containing the HSV values of the color, each in the range [0, 1]. + """ + # "ChatGPT 4o" assisted with generating this docstring. ret = matplotlib.colors.rgb_to_hsv(self.rgb()) return float(ret[0]), float(ret[1]), float(ret[2]) def build_colormap(self, *next_colors: "Color") -> matplotlib.colors.Colormap: """ - Build a colormap that will return a color between this instance and the - next color(s), given a value between 0 and 1. - - TODO add a "N" parameter to increase the number of colors in the - colormap. See the "N" parameter of - https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib-colors-listedcolormap. + Builds a colormap that transitions between this color and the specified next colors, + given a value between 0 and 1. Parameters ---------- - next_colors: list[Color] - The color(s) to fade this instance with. Typically this will only be - one color, such as for a red-to-blue fade. However, it could also be - multiple colors, such as for a blue-to-purple-to-yellow fade (the - matplotlib 'viridis' default). + next_colors : Color + The color(s) to fade this instance with. Typically this will only be one color, + such as for a red-to-blue fade. However, it could also be multiple colors, such + as for a blue-to-purple-to-yellow fade (the matplotlib 'viridis' default). + + Returns + ------- + matplotlib.colors.Colormap + A colormap object that can be used for rendering. """ + # "ChatGPT 4o" assisted with generating this docstring. + + # TODO add a "N" parameter to increase the number of colors in the + # colormap. See the "N" parameter of + # https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib-colors-listedcolormap. colors_sequence = [self] + list(next_colors) colors_rgb = [np.array(list(clr.rgb())) for clr in colors_sequence] ncolors = len(colors_sequence) @@ -166,50 +305,173 @@ def build_colormap(self, *next_colors: "Color") -> matplotlib.colors.Colormap: def black(): + """ + Returns a Color instance representing black. + + Returns + ------- + Color + A Color instance with RGB values (0.0, 0.0, 0.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(0.0, 0.0, 0.0, 'black', 'k') def dark_grey(): + """ + Returns a Color instance representing dark grey. + + Returns + ------- + Color + A Color instance with RGB values (0.25, 0.25, 0.25). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(0.25, 0.25, 0.25, 'dark grey', 'dg') def grey(): + """ + Returns a Color instance representing grey. + + Returns + ------- + Color + A Color instance with RGB values (0.5, 0.5, 0.5). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(0.5, 0.5, 0.5, 'grey', 'gy') def light_grey(): + """ + Returns a Color instance representing light grey. + + Returns + ------- + Color + A Color instance with RGB values (0.75, 0.75, 0.75). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(0.75, 0.75, 0.75, 'light grey', 'lg') def white(): + """ + Returns a Color instance representing white. + + Returns + ------- + Color + A Color instance with RGB values (1.0, 1.0, 1.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(1.0, 1.0, 1.0, 'white', 'w') def red(): + """ + Returns a Color instance representing red. + + Returns + ------- + Color + A Color instance with RGB values (1.0, 0.0, 0.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(1.0, 0.0, 0.0, 'red', 'r') def green(): + """ + Returns a Color instance representing green. + + Returns + ------- + Color + A Color instance with RGB values (0.0, 1.0, 0.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(0.0, 1.0, 0.0, 'green', 'g') def blue(): + """ + Returns a Color instance representing blue. + + Returns + ------- + Color + A Color instance with RGB values (0.0, 0.0, 1.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(0.0, 0.0, 1.0, 'blue', 'b') def cyan(): + """ + Returns a Color instance representing cyan. + + Returns + ------- + Color + A Color instance with RGB values (0.0, 1.0, 1.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(0.0, 1.0, 1.0, 'cyan', 'c') def magenta(): + """ + Returns a Color instance representing magenta. + + Returns + ------- + Color + A Color instance with RGB values (1.0, 0.0, 1.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(1.0, 0.0, 1.0, 'magenta', 'm') def yellow(): + """ + Returns a Color instance representing yellow. + + Returns + ------- + Color + A Color instance with RGB values (1.0, 1.0, 0.0). + """ + # "ChatGPT 4o" assisted with generating this docstring. return Color(1.0, 1.0, 0.0, 'yellow', 'y') def color_map(*colors_sequence: "Color"): + """ + Creates a colormap that transitions between a sequence of colors. + + This function takes a sequence of Color instances and builds a colormap that smoothly + transitions between the specified colors. The first color in the sequence is used as the + starting point, and the subsequent colors are used to define the transitions. + + Parameters + ---------- + colors_sequence : Color + A variable number of Color instances that define the colors to be included in the colormap. + The first color is the starting color, and the subsequent colors define the transitions. + + Returns + ------- + matplotlib.colors.Colormap + A colormap object that can be used for rendering. + + Raises + ------ + ValueError + If no colors are provided in the sequence. + """ + # "ChatGPT 4o" assisted with generating this docstring. colors_sequence = list(colors_sequence) return colors_sequence[0].build_colormap(*colors_sequence[1:]) diff --git a/opencsp/common/lib/render/PowerpointSlide.py b/opencsp/common/lib/render/PowerpointSlide.py index 28da4d7da..606e3eb10 100644 --- a/opencsp/common/lib/render/PowerpointSlide.py +++ b/opencsp/common/lib/render/PowerpointSlide.py @@ -12,6 +12,10 @@ class PowerpointSlide: + """ + Generate a powerpoint slide. Once completed, it should be added to a powerpoint presentation. + """ + def __init__( self, slide_control: RenderControlPowerpointSlide, diff --git a/opencsp/common/lib/render/VideoHandler.py b/opencsp/common/lib/render/VideoHandler.py index acfeab4e3..730e300cd 100644 --- a/opencsp/common/lib/render/VideoHandler.py +++ b/opencsp/common/lib/render/VideoHandler.py @@ -18,6 +18,13 @@ class VideoHandler: + """Handle video creation, frame extraction, and video transcoding. The format for generated videos and + frames is controlled by the video_control and frame_control render controllers. + + Not all of these arguments are required for every use case of this class. The generator methods + VideoCreator(), VideoTransformer(), and VideoExtractor() can be used to simplify the required + parameters down to the most common use cases.""" + _video_extensions = [ "mp4", "avi", diff --git a/opencsp/common/lib/render/figure_management.py b/opencsp/common/lib/render/figure_management.py index 0f7352e3c..5f5595451 100644 --- a/opencsp/common/lib/render/figure_management.py +++ b/opencsp/common/lib/render/figure_management.py @@ -31,11 +31,38 @@ def reset_figure_tiles(): + """ + Resets the index of figure tiles to zero. + + This function sets the global variable `figure_tile_idx` to 0, effectively + resetting the state of figure tiles for subsequent operations. + + Returns + ------- + None + """ + # "ChatGPT 4o" assisted with generating this docstring. global figure_tile_idx figure_tile_idx = 0 def do_show_figures(flag: bool = True): + """ + Sets the global flag for displaying figures. + + This function updates the global variable `show_figures` to control whether + figures should be displayed or not. + + Parameters + ---------- + flag : bool, optional + A boolean flag indicating whether to show figures. Defaults to True. + + Returns + ------- + None + """ + # "ChatGPT 4o" assisted with generating this docstring. global show_figures show_figures = flag @@ -48,6 +75,18 @@ def do_show_figures(flag: bool = True): def reset_figure_management(): + """ + Resets the figure management system to its initial state. + + This function resets the figure tile index, sets the figure number to zero, + and clears the list of recorded figure records. It effectively reinitializes + the figure management system, allowing for a fresh start in managing figures. + + Returns + ------- + None + """ + # "ChatGPT 4o" assisted with generating this docstring. reset_figure_tiles() global figure_num figure_num = 0 @@ -521,6 +560,18 @@ def _display_bar( def print_figure_summary() -> None: + """ + Prints a summary of recorded figures. + + This function iterates through a global list of figure records (`fig_record_list`) + and prints comments associated with each figure. It provides a way to review the + details of the figures that have been recorded during the session. + + Returns + ------- + None + """ + # "ChatGPT 4o" assisted with generating this docstring. global fig_record_list for fig_record in fig_record_list: print() @@ -561,4 +612,22 @@ def save_all_figures(output_path: str, format: str = None): def formatted_fig_display(block: bool = False) -> None: + """ + Displays the current figure in a formatted manner. + + This function utilizes Matplotlib's `plt.show()` to display the current figure. + The `block` parameter controls whether the display is blocking or non-blocking. + + Parameters + ---------- + block : bool, optional + If True, the function will block execution until the figure window is closed. + If False, the function will return immediately, allowing further code execution. + Defaults to False. + + Returns + ------- + None + """ + # "ChatGPT 4o" assisted with generating this docstring. plt.show(block=block) diff --git a/opencsp/common/lib/render/general_plot.py b/opencsp/common/lib/render/general_plot.py index c18c3a7d5..0699f41f1 100644 --- a/opencsp/common/lib/render/general_plot.py +++ b/opencsp/common/lib/render/general_plot.py @@ -25,6 +25,41 @@ def plot_xy_list( y_axis_grid=False, # Draw horizontal grid lines. legend=True, ): # Whether to draw the plot legend. + """ + Plots a list of (x, y) points on a 2D graph. + + This function creates a 2D plot using the provided data points, styles, and labels. + It sets up the figure, plots the data, and displays the plot. + + Parameters + ---------- + figure_control : object + Control object for managing the figure. + xy_list : list[tuple[float, float]] + A list of (x, y) tuples representing the data points to plot. + title : str + The title of the plot. + style : RenderControlPointSeq + An object defining the style of the plot (line style, color, etc.). + label : str | None + The label for the legend. If None, no label is shown. + x_axis_label : str | None + The label for the x-axis. If None, no label is shown. + y_axis_label : str | None + The label for the y-axis. If None, no label is shown. + x_axis_grid : bool, optional + If True, vertical grid lines are drawn on the x-axis. Defaults to False. + y_axis_grid : bool, optional + If True, horizontal grid lines are drawn on the y-axis. Defaults to False. + legend : bool, optional + If True, the plot legend is displayed. Defaults to True. + + Returns + ------- + object + A figure record object containing information about the created figure. + """ + # "ChatGPT 4o" assisted with generating this docstring. figure_record = fm.setup_figure(figure_control, title=title) x_list = [] y_list = [] @@ -59,6 +94,29 @@ def add_xy_list_to_plot( style, # A RenderControlPointSeq object. label=None, ): # Legend label or None. + """ + Adds a list of (x, y) points to an existing plot. + + This function appends additional data points to an already created plot. It updates + the figure with the new data and displays the updated plot. + + Parameters + ---------- + figure_record : object + The figure to which the new data will be added. + xy_list : list[tuple[float, float]] + A list of (x, y) tuples representing the data points to add to the plot. + style : RenderControlPointSeq + An object defining the style of the plot (line style, color, etc.). + label : str | None, optional + The label for the legend. If None, no label is shown. Defaults to None. + + Returns + ------- + object + The updated figure record object containing information about the modified figure. + """ + # "ChatGPT 4o" assisted with generating this docstring. if (xy_list != None) and (len(xy_list) > 0): x_list = [] y_list = [] diff --git a/opencsp/common/lib/render/image_plot.py b/opencsp/common/lib/render/image_plot.py index 311acbdb1..86e828a24 100644 --- a/opencsp/common/lib/render/image_plot.py +++ b/opencsp/common/lib/render/image_plot.py @@ -1,8 +1,5 @@ """ Image plotting, with annotations. - - - """ from cv2 import cv2 as cv @@ -26,6 +23,50 @@ def plot_image_figure( dpi=200, # Resolution to write. include_figure_idx_in_filename=True, ): # Whether to auto-index the filenames. + """ + Plots an image with optional annotations and saves it to disk. + + This function creates a figure to display an image, optionally drawing annotations + and saving the figure to a specified directory. The image can be displayed in either + RGB or BGR format. + + Parameters + ---------- + image : np.ndarray + The image to be plotted, represented as a NumPy array. + draw_image : bool, optional + If True, the image will be displayed in the figure. Defaults to True. + rgb : bool, optional + If True, the image is assumed to be in RGB format. If False, it is assumed to be in BGR format. Defaults to True. + title : str | None, optional + The title to display at the top of the figure. Defaults to None. + annotation_list : list, optional + A list of annotations to draw on the plot. Each annotation should have a `plot` method. Defaults to None. + crop_box : list[list[int]] | None, optional + A list defining the crop box as [[x_min, y_min], [x_max, y_max]]. If None, no cropping is applied. Defaults to None. + context_str : str | None, optional + An explanatory string to include in the status output line. Defaults to None. + save : bool, optional + If True, the figure will be saved to disk. Defaults to True. + output_dir : str | None, optional + The directory where the figure will be saved. Defaults to None. + output_body : str, optional + The base filename for the saved figure. Defaults to 'image'. + dpi : int, optional + The resolution (dots per inch) for the saved figure. Defaults to 200. + include_figure_idx_in_filename : bool, optional + If True, the figure index will be included in the filename. Defaults to True. + + Returns + ------- + None + + Raises + ------ + ValueError + If the output directory is not specified when saving the figure. + """ + # "ChatGPT 4o" assisted with generating this docstring. # Create the figure. plt.figure() plt.title(title) diff --git a/opencsp/common/lib/render/lib/PowerpointImage.py b/opencsp/common/lib/render/lib/PowerpointImage.py index 474f7efb8..911b8e9fd 100644 --- a/opencsp/common/lib/render/lib/PowerpointImage.py +++ b/opencsp/common/lib/render/lib/PowerpointImage.py @@ -11,6 +11,8 @@ class PowerpointImage(pps.PowerpointShape): + """Our own representation of a pptx powerpoint image, for more control over layouts.""" + _tmp_save_path = os.path.join(orp.opencsp_temporary_dir(), "PowerpointImage/images/tmp") def __init__( diff --git a/opencsp/common/lib/render/lib/PowerpointText.py b/opencsp/common/lib/render/lib/PowerpointText.py index e54e4e644..1caeec0c4 100644 --- a/opencsp/common/lib/render/lib/PowerpointText.py +++ b/opencsp/common/lib/render/lib/PowerpointText.py @@ -7,6 +7,24 @@ class PowerpointText(pps.PowerpointShape): + """ + A class representing text elements in a PowerPoint presentation. + + This class allows for the creation, manipulation, and storage of text elements + that can be added to PowerPoint slides. It supports saving to and loading from + text files for persistence. + + Attributes + ---------- + dims : tuple[float, float, float, float] + The dimensions of the text element in the PowerPoint slide. + is_title : bool + A flag indicating whether this text element is a title. + parent_slide : PowerpointSlide + The parent slide to which this text element belongs. + """ + + # "ChatGPT 4o" assisted with generating this docstring. _tmp_save_path = os.path.join(orp.opencsp_temporary_dir(), "PowerpointTexts", "texts", "tmp") def __init__( @@ -17,6 +35,23 @@ def __init__( is_title=False, parent_slide=None, ): + """ + Initializes the PowerpointText instance. + + Parameters + ---------- + val : str, optional + The text value of the PowerPoint text element. Defaults to None. + dims : tuple[float, float, float, float], optional + The dimensions of the text element (left, top, width, height). Defaults to None. + cell_dims : tuple[float, float, float, float], optional + The dimensions of the cell containing the text. Defaults to None. + is_title : bool, optional + A flag indicating whether this text element is a title. Defaults to False. + parent_slide : PowerpointSlide, optional + The parent slide to which this text element belongs. Defaults to None. + """ + # "ChatGPT 4o" assisted with generating this docstring. super().__init__(cell_dims) self._val = val self.dims = dims diff --git a/opencsp/common/lib/render/pandas_plot.py b/opencsp/common/lib/render/pandas_plot.py index f2d8d466b..51cf68386 100644 --- a/opencsp/common/lib/render/pandas_plot.py +++ b/opencsp/common/lib/render/pandas_plot.py @@ -1,9 +1,5 @@ """ - Plotting Pandas Objects - - - """ import matplotlib.pyplot as plt @@ -24,6 +20,48 @@ def dataframe_plot( y_axis_grid=False, # Draw horizontal grid lines. legend=True, ): # Whether to draw the plot legend. + """ + Plots data from a Pandas DataFrame. + + This function creates a plot using data from the specified DataFrame, allowing for multiple + curves to be plotted based on the provided column specifications. It sets up the figure, + plots the data, and displays the plot. + + Parameters + ---------- + figure_control : object + Control object for managing the figure. + df : pd.DataFrame + The DataFrame containing the data to plot. + title : str + The title of the plot. + x_column : str + The name of the column to use for the horizontal axis. + y_column_label_styles : list[list] + A list of specifications for the data curves to plot. Each specification should be a list + containing the column heading, legend label (or None), and point sequence render control. + x_axis_label : str | None + The label for the x-axis. If None, no label is shown. + y_axis_label : str | None + The label for the y-axis. If None, no label is shown. + x_axis_grid : bool, optional + If True, vertical grid lines are drawn on the x-axis. Defaults to False. + y_axis_grid : bool, optional + If True, horizontal grid lines are drawn on the y-axis. Defaults to False. + legend : bool, optional + If True, the plot legend is displayed. Defaults to True. + + Returns + ------- + object + A figure record object containing information about the created figure. + + Raises + ------ + ValueError + If the specified x_column or any y_column in y_column_label_styles does not exist in the DataFrame. + """ + # "ChatGPT 4o" assisted with generating this docstring. figure_record = fm.setup_figure(figure_control, title=title) for y_column_label_style in y_column_label_styles: y_column = y_column_label_style[0] diff --git a/opencsp/common/lib/render/view_spec.py b/opencsp/common/lib/render/view_spec.py index 1762805d9..d6e5f3131 100644 --- a/opencsp/common/lib/render/view_spec.py +++ b/opencsp/common/lib/render/view_spec.py @@ -1,14 +1,10 @@ """ - Specifying a view of a three-dimensional space. Options include general 3-d (allowing interactive rotation), xy, xz, yz, general section plane. In all of the 2-d cases, there is an embedded (p,q) parameter space, which corresponds to different projections of the 3-d coordinates. - - - """ import numpy as np @@ -20,36 +16,91 @@ def view_spec_3d() -> dict: + """Returns a specification dictionary for a 3D view. + + Returns + ------- + dict + A dictionary containing the view type set to '3d'. + """ + # "ChatGPT 4o" assisted with generating this docstring. spec = {} spec['type'] = '3d' return spec def view_spec_xy() -> dict: + """Returns a specification dictionary for an XY view. + + Returns + ------- + dict + A dictionary containing the view type set to 'xy'. + """ + # "ChatGPT 4o" assisted with generating this docstring. spec = {} spec['type'] = 'xy' return spec def view_spec_xz() -> dict: + """Returns a specification dictionary for an XZ view. + + Returns + ------- + dict + A dictionary containing the view type set to 'xz'. + """ + # "ChatGPT 4o" assisted with generating this docstring. spec = {} spec['type'] = 'xz' return spec def view_spec_yz() -> dict: + """Returns a specification dictionary for a YZ view. + + Returns + ------- + dict + A dictionary containing the view type set to 'yz'. + """ + # "ChatGPT 4o" assisted with generating this docstring. spec = {} spec['type'] = 'yz' return spec def view_spec_im() -> dict: + """Returns a specification dictionary for an image view. + + Returns + ------- + dict + A dictionary containing the view type set to 'image'. + """ + # "ChatGPT 4o" assisted with generating this docstring. spec = {} spec['type'] = 'image' return spec def view_spec_vplane(segment_xy) -> dict: # A vertical plane containing the segment. + """Returns a specification dictionary for a vertical plane defined by a segment. + + This function constructs a vertical plane based on the provided segment defined by two points. + + Parameters + ---------- + segment_xy : list[list[float]] + A list containing two points that define the segment in 2D space, where each point is represented as [x, y]. + + Returns + ------- + dict + A dictionary containing the view type set to 'vplane' and additional information about the plane and segment. + """ + # "ChatGPT 4o" assisted with generating this docstring. # Construct embedding line. line = g2d.homogeneous_line(segment_xy[0], segment_xy[1]) @@ -103,6 +154,21 @@ def view_spec_vplane(segment_xy) -> dict: # A vertical plane containing the seg def view_spec_camera(camera, camera_xform) -> dict: + """Returns a specification dictionary for a camera view. + + Parameters + ---------- + camera : object + The camera object representing the camera's properties. + camera_xform : object + The transformation object for the camera. + + Returns + ------- + dict + A dictionary containing the view type set to 'camera' and the camera properties. + """ + # "ChatGPT 4o" assisted with generating this docstring. spec = {} spec['type'] = 'camera' spec['camera'] = camera @@ -114,6 +180,21 @@ def view_spec_camera(camera, camera_xform) -> dict: def xyz2pqw(xyz, view_spec): + """Converts 3D coordinates to (p, q, w) coordinates based on the view specification. + + Parameters + ---------- + xyz : np.ndarray + The 3D coordinates to convert. + view_spec : dict + The view specification that determines the conversion method. + + Returns + ------- + list[float] | None + The converted (p, q, w) coordinates, or None if the point is behind the camera in a camera view. + """ + # "ChatGPT 4o" assisted with generating this docstring. # Enforces the right-hand rule in all conversions. # That is, [p,q,w] is a right-handed coordinate system. if view_spec['type'] == '3d': @@ -156,6 +237,21 @@ def xyz2pqw(xyz, view_spec): def xyz2pq(xyz, view_spec): + """Converts 3D coordinates to (p, q) coordinates based on the view specification. + + Parameters + ---------- + xyz : np.ndarray + The 3D coordinates to convert. + view_spec : dict + The view specification that determines the conversion method. + + Returns + ------- + list[float] | None + The converted (p, q) coordinates, or None if the point is behind the camera in a camera view. + """ + # "ChatGPT 4o" assisted with generating this docstring. pqw = xyz2pqw(xyz, view_spec) if pqw == None: return None @@ -164,6 +260,26 @@ def xyz2pq(xyz, view_spec): def pqw2xyz(pqw, view_spec): + """Converts (p, q, w) coordinates back to 3D coordinates based on the view specification. + + Parameters + ---------- + pqw : list[float] + The (p, q, w) coordinates to convert. + view_spec : dict + The view specification that determines the conversion method. + + Returns + ------- + list[float] + The converted 3D coordinates. + + Raises + ------ + ValueError + If the view specification type is unrecognized. + """ + # "ChatGPT 4o" assisted with generating this docstring. # Assumes the right-hand rule for all conversions. # That is, [p,q,w] is viewed as a right-handed coordinate system. if view_spec['type'] == '3d': @@ -193,6 +309,21 @@ def pqw2xyz(pqw, view_spec): def pq2xyz(pq, view_spec): + """Converts (p, q) coordinates to 3D coordinates based on the view specification. + + Parameters + ---------- + pq : list[float] + The (p, q) coordinates to convert. + view_spec : dict + The view specification that determines the conversion method. + + Returns + ------- + list[float] + The converted 3D coordinates. + """ + # "ChatGPT 4o" assisted with generating this docstring. pqw = pq.copy() pqw.append(0) return pqw2xyz(pqw, view_spec) diff --git a/opencsp/common/lib/render_control/RenderControlPowerpointSlide.py b/opencsp/common/lib/render_control/RenderControlPowerpointSlide.py index 9a6af93d5..d21ee9586 100644 --- a/opencsp/common/lib/render_control/RenderControlPowerpointSlide.py +++ b/opencsp/common/lib/render_control/RenderControlPowerpointSlide.py @@ -2,6 +2,8 @@ class RenderControlPowerpointSlide: + """Controls for how to render a power slide.""" + def __init__( self, title_size=30, diff --git a/opencsp/common/lib/render_control/RenderControlSurface.py b/opencsp/common/lib/render_control/RenderControlSurface.py index 69618a41f..1adf84728 100644 --- a/opencsp/common/lib/render_control/RenderControlSurface.py +++ b/opencsp/common/lib/render_control/RenderControlSurface.py @@ -5,6 +5,10 @@ class RenderControlSurface: + """ + Render control information for how to style surface plots (see View3d + function plot_surface and plot_trisurface).""" + def __init__( self, draw_title=True, diff --git a/opencsp/test/test_DocStringsExist.py b/opencsp/test/test_DocStringsExist.py index 8b461aa94..96f03bedf 100644 --- a/opencsp/test/test_DocStringsExist.py +++ b/opencsp/test/test_DocStringsExist.py @@ -28,6 +28,11 @@ import opencsp.common.lib.opencsp_path.optical_analysis_data_path as optical_analysis_data_path import opencsp.common.lib.process.ServerSynchronizer as ServerSynchronizer import opencsp.common.lib.process.parallel_video_tools as parallel_video_tools +import opencsp.common.lib.render.PlotAnnotation as PlotAnnotation +import opencsp.common.lib.render.PowerpointSlide as PowerpointSlide +import opencsp.common.lib.render.general_plot as general_plot +import opencsp.common.lib.render.image_plot as image_plot +import opencsp.common.lib.render.pandas_plot as pandas_plot def test_docstrings_exist_for_methods(): @@ -232,6 +237,21 @@ def test_docstrings_exist_for_methods(): opencsp.common.lib.process.subprocess_tools, ] + render_class_list = [ + opencsp.common.lib.render.Color, + opencsp.common.lib.render.ImageAttributeParser, + opencsp.common.lib.render.PlotAnnotation, + opencsp.common.lib.render.PowerpointSlide, + opencsp.common.lib.render.VideoHandler, + opencsp.common.lib.render.View3d, + opencsp.common.lib.render.axis_3d, + opencsp.common.lib.render.figure_management, + opencsp.common.lib.render.general_plot, + opencsp.common.lib.render.image_plot, + opencsp.common.lib.render.pandas_plot, + opencsp.common.lib.render.view_spec, + ] + common_class_list = ( camera_class_list + csp_class_list @@ -243,6 +263,7 @@ def test_docstrings_exist_for_methods(): + opencsp_path_class_list + photogrammetry_class_list + process_class_list + + render_class_list ) class_list = app_class_list + common_class_list