diff --git a/opencsp/app/target/target_color/target_color_2d_gradient.py b/contrib/app/target/target_color/target_color_2d_gradient.py similarity index 100% rename from opencsp/app/target/target_color/target_color_2d_gradient.py rename to contrib/app/target/target_color/target_color_2d_gradient.py diff --git a/opencsp/app/target/target_color/target_color_bullseye.py b/contrib/app/target/target_color/target_color_bullseye.py similarity index 99% rename from opencsp/app/target/target_color/target_color_bullseye.py rename to contrib/app/target/target_color/target_color_bullseye.py index 570871c93..efd90530d 100755 --- a/opencsp/app/target/target_color/target_color_bullseye.py +++ b/contrib/app/target/target_color/target_color_bullseye.py @@ -59,7 +59,9 @@ def bullseye_color_bar( cx_offset_trim_pix, target_img_width_pix, ): - # Bullseye. + """ + Placeholder + """ for row in range(0, n_rows): for col in range(0, n_cols): r_mrad = bullseye_error.radius_in_mrad_given_row_col( diff --git a/opencsp/app/target/target_color/target_color_bullseye_error.py b/contrib/app/target/target_color/target_color_bullseye_error.py similarity index 59% rename from opencsp/app/target/target_color/target_color_bullseye_error.py rename to contrib/app/target/target_color/target_color_bullseye_error.py index b3baf4fa2..afd012785 100755 --- a/opencsp/app/target/target_color/target_color_bullseye_error.py +++ b/contrib/app/target/target_color/target_color_bullseye_error.py @@ -9,20 +9,37 @@ def meters_given_pixels(d_pixel, dpi): + """ + Returns distance in meters given a distance in pixels and a dots per inch (DPI) value + + Parameters + ---------- + d_pixel : float + Distance in pixels + dpi : float + Dots per inch of image + + Returns + ------- + float + Distance in meters + """ d_inch = d_pixel / dpi d_meter = d_inch / (1000.0 / 25.4) return d_meter def surface_normal_error_magnitude_given_radius_in_meters(r_meter, focal_length_meter): - # Computes the surface normal error of a reflection with a reflected image the given - # radius r_meter away from the target center. - # - # Correct if the mirror design is spherical, the view position is along the optical axis, - # and the target-to-mirror and camera-to-mirror distances are equal to the radius of curvature. - # - # Returns value in milliradians. - # + """ + Computes the surface normal error of a reflection with a reflected image the given + radius r_meter away from the target center. + + Correct if the mirror design is spherical, the view position is along the optical axis, + and the target-to-mirror and camera-to-mirror distances are equal to the radius of curvature. + + Returns value in milliradians. + """ + radius_of_curvature_meter = 2 * focal_length_meter reflected_ray_angle = math.atan(r_meter / radius_of_curvature_meter) # radians surface_normal_error = reflected_ray_angle / 2.0 # radians @@ -30,6 +47,9 @@ def surface_normal_error_magnitude_given_radius_in_meters(r_meter, focal_length_ def radius_in_mrad_given_row_col(n_rows, row, col, x_max, cx_offset_pix, y_offset_pix, focal_length_meter): + """ + Placeholder + """ x = col y = n_rows - row cx = (x_max / 2) + cx_offset_pix diff --git a/opencsp/app/target/target_color/target_color_one_color.py b/contrib/app/target/target_color/target_color_one_color.py similarity index 100% rename from opencsp/app/target/target_color/target_color_one_color.py rename to contrib/app/target/target_color/target_color_one_color.py diff --git a/opencsp/app/target/target_color/target_color_polar.py b/contrib/app/target/target_color/target_color_polar.py similarity index 100% rename from opencsp/app/target/target_color/target_color_polar.py rename to contrib/app/target/target_color/target_color_polar.py diff --git a/doc/source/library_reference/app/target/target_color/config.rst b/doc/source/library_reference/app/target/target_color/config.rst index 80e495c41..6a011ad07 100644 --- a/doc/source/library_reference/app/target/target_color/config.rst +++ b/doc/source/library_reference/app/target/target_color/config.rst @@ -8,56 +8,6 @@ opencsp.app.target.target_color.lib.ImageColor :undoc-members: :show-inheritance: -opencsp.app.target.target_color.target_color_2d_gradient -======================================================== - -.. currentmodule:: opencsp.app.target.target_color.target_color_2d_gradient - -.. automodule:: opencsp.app.target.target_color.target_color_2d_gradient - :members: - :undoc-members: - :show-inheritance: - -opencsp.app.target.target_color.target_color_bullseye_error -=========================================================== - -.. currentmodule:: opencsp.app.target.target_color.target_color_bullseye_error - -.. automodule:: opencsp.app.target.target_color.target_color_bullseye_error - :members: - :undoc-members: - :show-inheritance: - -opencsp.app.target.target_color.target_color_bullseye -===================================================== - -.. currentmodule:: opencsp.app.target.target_color.target_color_bullseye - -.. automodule:: opencsp.app.target.target_color.target_color_bullseye - :members: - :undoc-members: - :show-inheritance: - -opencsp.app.target.target_color.target_color_one_color -====================================================== - -.. currentmodule:: opencsp.app.target.target_color.target_color_one_color - -.. automodule:: opencsp.app.target.target_color.target_color_one_color - :members: - :undoc-members: - :show-inheritance: - -opencsp.app.target.target_color.target_color_polar -================================================== - -.. currentmodule:: opencsp.app.target.target_color.target_color_polar - -.. automodule:: opencsp.app.target.target_color.target_color_polar - :members: - :undoc-members: - :show-inheritance: - opencsp.app.target.target_color.target_color ============================================ diff --git a/opencsp/app/camera_calibration/CameraCalibration.py b/opencsp/app/camera_calibration/CameraCalibration.py index 7ccef597e..8c7eee5de 100644 --- a/opencsp/app/camera_calibration/CameraCalibration.py +++ b/opencsp/app/camera_calibration/CameraCalibration.py @@ -24,6 +24,47 @@ class CalibrationGUI: + """ + A graphical user interface (GUI) for calibrating a machine vision camera. + + This class provides a user-friendly interface to load previously captured + calibration images, find checkerboard corners, and calibrate the camera + using the selected images. It also allows users to visualize the + reprojection error and save the calibrated camera parameters. + + The GUI includes options to select images, find corners, view found + corners, calibrate the camera, visualize distortion, and save the camera + configuration. + + Attributes + ---------- + root : tkinter.Tk + The main window of the GUI. + files : list[str] + List of selected image file paths. + images : list[np.ndarray] + List of loaded images as NumPy arrays. + used_file_names : list[str] + List of file names of the loaded images. + p_object : list[Vxyz] + List of object points in 3D space corresponding to the checkerboard corners. + p_image : list[Vxy] + List of image points in 2D space corresponding to the detected corners. + img_size_xy : tuple[int, int] + Size of the images (width, height). + camera : Camera + The calibrated camera object. + r_cam_object : list[Rotation] + List of rotation matrices for each calibration image. + v_cam_object_cam : list[Vxyz] + List of camera position vectors for each calibration image. + avg_reproj_error : list[float] + Average reprojection error for the calibration. + reproj_errors : list[float] + List of reprojection errors for each calibration image. + """ + + # "ChatGPT 4o-mini" assisted with generating this docstring. def __init__(self): """ GUI for calibrating machine vision Camera diff --git a/opencsp/app/camera_calibration/lib/ViewAnnotatedImages.py b/opencsp/app/camera_calibration/lib/ViewAnnotatedImages.py index ee6af39a8..48a5c379e 100644 --- a/opencsp/app/camera_calibration/lib/ViewAnnotatedImages.py +++ b/opencsp/app/camera_calibration/lib/ViewAnnotatedImages.py @@ -9,7 +9,8 @@ class ViewAnnotatedImages: - """Class that controls a window used to view images with a next and previous + """ + Class that controls a window used to view images with a next and previous button """ @@ -77,6 +78,9 @@ def __init__(self, root: tkinter.Tk, images: list[ndarray], image_names: list[st self.root.mainloop() def update_image(self): + """ + Updates displayed image and image label + """ # Update image title self.var_title.set(self.image_names[self.idx_im]) @@ -101,6 +105,9 @@ def update_image(self): self.canvas.itemconfig(self.canvas_image, image=image_tk) def show_next(self): + """ + Show the next image. + """ # Update index self.idx_im += 1 if self.idx_im >= len(self.images): @@ -110,6 +117,9 @@ def show_next(self): self.update_image() def show_prev(self): + """ + Show the previous image. + """ # Update index self.idx_im -= 1 if self.idx_im < 0: diff --git a/opencsp/app/sofast/SofastGUI.py b/opencsp/app/sofast/SofastGUI.py index 4910410c6..f5cf982fb 100644 --- a/opencsp/app/sofast/SofastGUI.py +++ b/opencsp/app/sofast/SofastGUI.py @@ -819,7 +819,9 @@ def _projector_closed(self, image_projection: ImageProjection): self._camera_closed(None) def close_image_acquisition(self) -> None: - """Closes image acquisition""" + """ + Close the single Image Acquisition object if open. + """ # Close the camera with et.ignored(Exception): ImageAcquisitionAbstract.instance().close() diff --git a/opencsp/app/sofast/lib/ImageCalibrationAbstract.py b/opencsp/app/sofast/lib/ImageCalibrationAbstract.py index ddccc9e45..643e214af 100644 --- a/opencsp/app/sofast/lib/ImageCalibrationAbstract.py +++ b/opencsp/app/sofast/lib/ImageCalibrationAbstract.py @@ -49,6 +49,19 @@ def get_calibration_name() -> str: @abstractmethod def apply_to_images(self, measurement) -> ndarray: + """ + Performs camera-projector brightness values calibration. + + Parameters + ---------- + fringe_images : ndarray + Measurement fringe images. + + Returns + ------- + ndarray + Calibrated fringe images, float. + """ pass def _create_response_function(self) -> None: @@ -165,7 +178,8 @@ def calculate_min_display_camera_values(self, derivative_thresh: float = 0.4) -> return (display_min_value, camera_min_value) def plot_gray_levels(self) -> None: - """Shows plot of gray levels calibration data. When the close() method of this instance is called (or this + """ + Shows plot of gray levels calibration data. When the close() method of this instance is called (or this instance is destructed), the plot will be closed automatically.""" title = 'Projector-Camera Calibration Curve' diff --git a/opencsp/app/target/target_color/target_color.py b/opencsp/app/target/target_color/target_color.py index d8447484d..091f25f26 100755 --- a/opencsp/app/target/target_color/target_color.py +++ b/opencsp/app/target/target_color/target_color.py @@ -12,7 +12,6 @@ import os import opencsp.common.lib.opencsp_path.opencsp_root_path as ort -import opencsp.app.target.target_color.target_color_bullseye_error import opencsp.common.lib.target.target_color_convert import opencsp.common.lib.target.target_color_1d_gradient import opencsp.common.lib.target.target_image diff --git a/opencsp/common/lib/camera/Camera.py b/opencsp/common/lib/camera/Camera.py index 062ded73e..76b0ffde8 100644 --- a/opencsp/common/lib/camera/Camera.py +++ b/opencsp/common/lib/camera/Camera.py @@ -16,23 +16,27 @@ class Camera: + """ + Calibrated machine vision camera representation. This represents a pinhole model of + a camera/lens assembly and includes lens distortion through the use of distortion + coefficients. This model uses the distortion model used by OpenCV; see + https://docs.opencv.org/4.9.0/d9/d0c/group__calib3d.html for more information. + + Parameters + ---------- + intrinsic_mat : np.ndarray + 3x3 numpy array, intrinsic camera matrix + distortion_coef : np.ndarray + 1d array, distortion coefficients, typically length 4. + image_shape_xy : tuple(int) + (x, y), image size in pixels. + name : str + Name of camera/lens combination. + """ + def __init__( self, intrinsic_mat: np.ndarray, distortion_coef: np.ndarray, image_shape_xy: tuple[int, int], name: str ): - """ - Calibrated machine vision camera representation. - - Parameters - ---------- - intrinsic_mat : np.ndarray - distortion_coef : np.ndarray - 1d array, distortion coefficients. - image_shape_xy : tuple(int) - (x, y), image size in pixels. - name : str - Name of camera/lens combination. - - """ if intrinsic_mat.shape[0] != 3 or intrinsic_mat.shape[1] != 3 or np.ndim(intrinsic_mat) != 2: raise ValueError('Input intrinsic_mat must be a 3x3 ndarray.') diff --git a/opencsp/common/lib/camera/ImageAcquisitionAbstract.py b/opencsp/common/lib/camera/ImageAcquisitionAbstract.py index e1ede1f03..1e96f4edc 100644 --- a/opencsp/common/lib/camera/ImageAcquisitionAbstract.py +++ b/opencsp/common/lib/camera/ImageAcquisitionAbstract.py @@ -9,6 +9,28 @@ class ImageAcquisitionAbstract(ABC): + """ + Abstract base class for image acquisition from cameras. + + This class defines the interface for acquiring images from various camera types. + It implements a multiton design pattern to ensure that only one instance of a + camera is active at a time. The class provides methods for exposure calibration, + frame retrieval, and managing camera settings. + + Attributes + ---------- + _instances : dict[int, ImageAcquisitionAbstract] + A dictionary of all instantiated camera instances, ensuring that each index + corresponds to a unique camera instance. + _next_instance_idx : int + The index to use for the next camera instance added to the `_instances` dictionary. + on_close : list[Callable[[ImageAcquisitionAbstract], None]] + A list of callback functions to be executed when the camera is closed. + is_closed : bool + A flag indicating whether the camera connection is closed. + """ + + # "ChatGPT 4o-mini" assisted with generating this docstring. _instances: dict[int, 'ImageAcquisitionAbstract'] = {} """ All instantiated camera instances. We use a dictionary to ensure that once an index is assigned, then all references to that same index will return the same camera (or None if the camera was closed). """ diff --git a/opencsp/common/lib/csp/MirrorPoint.py b/opencsp/common/lib/csp/MirrorPoint.py index f4656f98e..852a5cd36 100644 --- a/opencsp/common/lib/csp/MirrorPoint.py +++ b/opencsp/common/lib/csp/MirrorPoint.py @@ -1,7 +1,3 @@ -"""Mirror class representing mirrors with scattered surface point -locations. -""" - from typing import Literal from warnings import warn @@ -22,6 +18,10 @@ class MirrorPoint(MirrorAbstract): + """Mirror class representing mirrors with scattered surface point + locations. + """ + def __init__( self, surface_points: Pxyz, diff --git a/opencsp/common/lib/geometry/LineXY.py b/opencsp/common/lib/geometry/LineXY.py index cfb982fad..d8f673e7c 100644 --- a/opencsp/common/lib/geometry/LineXY.py +++ b/opencsp/common/lib/geometry/LineXY.py @@ -7,6 +7,28 @@ class LineXY: + """ + Representation of a homogeneous line in 2D space. + + The line is represented in the general form \( Ax + By + C = 0 \) and + provides various properties and methods to work with lines, including + calculating distances, intersections, and fitting lines to sets of points. + + Attributes + ---------- + A : float + Coefficient A of the line equation. + B : float + Coefficient B of the line equation. + C : float + Coefficient C of the line equation, representing the distance from the + origin along the normal vector. + _original_two_points : tuple[Vxy, Vxy] | None + The original two points used to create the line, if created with + `from_two_points`. + """ + + # "ChatGPT 4o-mini" assisted with generating this docstring. def __init__(self, A: float, B: float, C: float): """ Representation of a homogenous line with the following properties: diff --git a/opencsp/common/lib/geometry/Uxyz.py b/opencsp/common/lib/geometry/Uxyz.py index 59fef2f0f..8b933b07d 100644 --- a/opencsp/common/lib/geometry/Uxyz.py +++ b/opencsp/common/lib/geometry/Uxyz.py @@ -2,7 +2,38 @@ class Uxyz(Vxyz): + """ + A class representing a 3D unit vector. + + The Uxyz class extends the Vxyz class to specifically represent unit vectors + in three-dimensional space. Upon initialization, the vector is normalized to + ensure it has a magnitude of 1. + + Attributes + ---------- + _data : np.ndarray + The underlying data representing the vector, normalized to unit length. + """ + + # "ChatGPT 4o-mini" assisted with generating this docstring. def __init__(self, data, dtype=float): + """ + Instantiate class for representing a 3D unit vector. + + Parameters + ---------- + data : array-like + The input data for the vector, which can be a list, tuple, or + NumPy array of length 3. + dtype : data type, optional + The data type of the vector elements. The default is float. + + Returns + ------- + Uxyz + An instance of the Uxyz class representing a unit vector. + """ + # "ChatGPT 4o-mini" assisted with generating this docstring. # Initialize vector super().__init__(data, dtype) diff --git a/opencsp/common/lib/geometry/Vxy.py b/opencsp/common/lib/geometry/Vxy.py index 621b77b82..ea632a309 100644 --- a/opencsp/common/lib/geometry/Vxy.py +++ b/opencsp/common/lib/geometry/Vxy.py @@ -9,6 +9,29 @@ class Vxy: + """ + A class to represent 2D points or vectors. + + This class allows for the creation and manipulation of 2D vectors, + including operations such as addition, subtraction, scaling, + normalization, rotation, and dot/cross products. + + The vectors can be initialized from various data formats, including + NumPy arrays, tuples, lists, or other instances of the Vxy class. + + Attributes + ---------- + data : np.ndarray + An array with shape (2, N), where N is the number of 2D vectors. + dtype : np.dtype + The data type of the vector elements. + x : np.ndarray + The x-coordinates of the vectors. + y : np.ndarray + The y-coordinates of the vectors. + """ + + # "ChatGPT 4o-mini" assisted with generating this docstring. def __init__(self, data: Union[np.ndarray, tuple[float, float], tuple[list, list], "Vxy"], dtype=float): """ 2D vector class to represent 2D points/vectors. diff --git a/opencsp/test/test_DocStringsExist.py b/opencsp/test/test_DocStringsExist.py index 34bf61fb1..2f7e37ade 100644 --- a/opencsp/test/test_DocStringsExist.py +++ b/opencsp/test/test_DocStringsExist.py @@ -2,53 +2,143 @@ import unittest # Assume opencsp is in PYHTONPATH -from opencsp.app.sofast.lib.ProcessSofastFringe import ProcessSofastFringe as Sofast -from opencsp.common.lib.cv import CacheableImage, SpotAnalysis -from opencsp.common.lib.cv.spot_analysis import ImagesStream, SpotAnalysisImagesStream, SpotAnalysisOperable -from opencsp.common.lib.cv.spot_analysis.image_processor import * -from opencsp.common.lib.cv.spot_analysis.image_processor import AbstractSpotAnalysisImageProcessor +import opencsp as opencsp +import example as example -# TODO: import all user-facing classes here. +from opencsp.app.camera_calibration import CameraCalibration +from opencsp.app.camera_calibration.lib.ViewAnnotatedImages import ViewAnnotatedImages +from opencsp.app.sofast.SofastGUI import SofastGUI +from opencsp.app.sofast.lib import * +from opencsp.app.select_image_points import SelectImagePoints +import opencsp.common.lib.cv.SpotAnalysis + +import opencsp.app.target.target_color.target_color as target_color class test_Docstrings(unittest.TestCase): - class_list = [ - Sofast, - # Spot Analysis - SpotAnalysis, - SpotAnalysisOperable, - ImagesStream, - SpotAnalysisImagesStream, - CacheableImage, - AbstractAggregateImageProcessor, - AbstractSpotAnalysisImageProcessor, - AbstractVisualizationImageProcessor, - AnnotationImageProcessor, - AverageByGroupImageProcessor, - BcsLocatorImageProcessor, - ConvolutionImageProcessor, - CroppingImageProcessor, - EchoImageProcessor, - ExposureDetectionImageProcessor, - FalseColorImageProcessor, - HotspotImageProcessor, - LogScaleImageProcessor, - NullImageSubtractionImageProcessor, - PopulationStatisticsImageProcessor, - SupportingImagesCollectorImageProcessor, - View3dImageProcessor, - ViewCrossSectionImageProcessor, - # TODO: List all user-facing classes here. + camera_calibration_class_list = [ + CameraCalibration, + opencsp.app.camera_calibration.lib.calibration_camera, + opencsp.app.camera_calibration.lib.image_processing, + ViewAnnotatedImages, + ] + + scene_reconstruction_class_list = [opencsp.app.scene_reconstruction.lib.SceneReconstruction.SceneReconstruction] + + select_image_points_class_list = [SelectImagePoints] + + sofast_class_list = [ + SofastGUI, + opencsp.app.sofast.lib.AbstractMeasurementSofast, + opencsp.app.sofast.lib.BlobIndex, + opencsp.app.sofast.lib.CalibrateDisplayShape.CalibrateDisplayShape, + opencsp.app.sofast.lib.CalibrateSofastFixedDots.CalibrateSofastFixedDots, + opencsp.app.sofast.lib.CalibrateDisplayShape.DataCalculation, + opencsp.app.sofast.lib.CalibrateDisplayShape.DataInput, + opencsp.app.sofast.lib.DebugOpticsGeometry.DebugOpticsGeometry, + opencsp.app.sofast.lib.DefinitionEnsemble.DefinitionEnsemble, + opencsp.app.sofast.lib.DefinitionFacet.DefinitionFacet, + opencsp.app.sofast.lib.DisplayShape.DisplayShape, + opencsp.app.sofast.lib.DistanceOpticScreen.DistanceOpticScreen, + opencsp.app.sofast.lib.DotLocationsFixedPattern.DotLocationsFixedPattern, + opencsp.app.sofast.lib.Fringes.Fringes, + opencsp.app.sofast.lib.ImageCalibrationAbstract.ImageCalibrationAbstract, + opencsp.app.sofast.lib.ImageCalibrationGlobal.ImageCalibrationGlobal, + opencsp.app.sofast.lib.ImageCalibrationScaling.ImageCalibrationScaling, + opencsp.app.sofast.lib.MeasurementSofastFixed.MeasurementSofastFixed, + opencsp.app.sofast.lib.MeasurementSofastFringe.MeasurementSofastFringe, + opencsp.app.sofast.lib.ParamsMaskCalculation.ParamsMaskCalculation, + opencsp.app.sofast.lib.ParamsOpticGeometry.ParamsOpticGeometry, + opencsp.app.sofast.lib.ParamsSofastFixed.ParamsSofastFixed, + opencsp.app.sofast.lib.ParamsSofastFringe.ParamsSofastFringe, + opencsp.app.sofast.lib.PatternSofastFixed.PatternSofastFixed, + opencsp.app.sofast.lib.ProcessSofastAbstract.ProcessSofastAbstract, + opencsp.app.sofast.lib.ProcessSofastFixed.ProcessSofastFixed, + opencsp.app.sofast.lib.ProcessSofastFringe.ProcessSofastFringe, + opencsp.app.sofast.lib.SofastConfiguration.SofastConfiguration, + opencsp.app.sofast.lib.SpatialOrientation.SpatialOrientation, + opencsp.app.sofast.lib.SystemSofastFixed.SystemSofastFixed, + opencsp.app.sofast.lib.SystemSofastFringe.SystemSofastFringe, + opencsp.app.sofast.lib.calculation_data_classes.CalculationDataGeometryFacet, + opencsp.app.sofast.lib.calculation_data_classes.CalculationDataGeometryGeneral, + opencsp.app.sofast.lib.calculation_data_classes.CalculationError, + opencsp.app.sofast.lib.calculation_data_classes.CalculationFacetEnsemble, + opencsp.app.sofast.lib.calculation_data_classes.CalculationImageProcessingFacet, + opencsp.app.sofast.lib.calculation_data_classes.CalculationImageProcessingGeneral, + opencsp.app.sofast.lib.image_processing, + opencsp.app.sofast.lib.load_sofast_hdf_data, + opencsp.app.sofast.lib.process_optics_geometry, + opencsp.app.sofast.lib.sofast_common_functions, + opencsp.app.sofast.lib.spatial_processing, + ] + + target_class_list = [target_color, opencsp.app.target.target_color.lib.ImageColor] + + # TODO: example_camera_calibration_list + # TODO: example_csp_list + # TODO: example_scene_reconstruction_list + # TODO: example_sofast_fixed_list + # TODO: example_solarfield_list + # TODO: example_camera_io_list + # TODO: example_mirror_list + # TODO: example_raytrace_list + # TODO: example_sofast_calibration_list + # TODO: example_sofast_fringe_list + # TODO: example_targetcolor_list + + app_class_list = ( + camera_calibration_class_list + + scene_reconstruction_class_list + + select_image_points_class_list + + sofast_class_list + + target_class_list + ) + + cv_class_list = [ + opencsp.common.lib.cv.CacheableImage, + opencsp.common.lib.cv.SpotAnalysis, + opencsp.common.lib.cv.spot_analysis.ImagesStream, + opencsp.common.lib.cv.spot_analysis.SpotAnalysisImagesStream, + opencsp.common.lib.cv.spot_analysis.SpotAnalysisOperable, + opencsp.common.lib.cv.spot_analysis.image_processor.AbstractAggregateImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.AbstractSpotAnalysisImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.AbstractVisualizationImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.AnnotationImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.AverageByGroupImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.BcsLocatorImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.ConvolutionImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.CroppingImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.EchoImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.ExposureDetectionImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.FalseColorImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.HotspotImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.LogScaleImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.NullImageSubtractionImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.PopulationStatisticsImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.SupportingImagesCollectorImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.View3dImageProcessor, + opencsp.common.lib.cv.spot_analysis.image_processor.ViewCrossSectionImageProcessor, ] + class_list = app_class_list + cv_class_list + def test_docstrings_exist_for_methods(self): for class_module in self.class_list: - method_list = [ - func - for func in dir(class_module) - if callable(getattr(class_module, func)) and not func.startswith("__") and not func.startswith("_") - ] - + if inspect.isclass(class_module): + method_list = [ + func + for func in class_module.__dict__ + if callable(getattr(class_module, func)) + and not func.startswith("__") + and not func.startswith("_") + and not hasattr(super(class_module), func) + ] + else: + method_list = [ + func + for func in dir(class_module) + if callable(getattr(class_module, func)) and not func.startswith("__") and not func.startswith("_") + ] undocumented_methods: list[str] = [] for method in method_list: @@ -61,11 +151,11 @@ def test_docstrings_exist_for_methods(self): if not doc_exists: undocumented_methods.append(method) - self.assertEqual( - len(undocumented_methods), - 0, - f"Found undocumented methods in {class_module}:\n\t" + "\n\t".join(undocumented_methods), - ) + if len((undocumented_methods)) != 0: + print(f"Found undocumented methods in {class_module}:") + for name in undocumented_methods: + print(f"\t{name}") + assert len((undocumented_methods)) == 0 if __name__ == '__main__':