diff --git a/opencsp/app/sofast/lib/ProcessSofastFixed.py b/opencsp/app/sofast/lib/ProcessSofastFixed.py index 947b87f5e..b58b1aeac 100644 --- a/opencsp/app/sofast/lib/ProcessSofastFixed.py +++ b/opencsp/app/sofast/lib/ProcessSofastFixed.py @@ -20,9 +20,10 @@ from opencsp.common.lib.csp.MirrorPoint import MirrorPoint from opencsp.common.lib.deflectometry.SlopeSolver import SlopeSolver from opencsp.common.lib.deflectometry.SlopeSolverData import SlopeSolverData +from opencsp.common.lib.deflectometry.Surface2DAbstract import Surface2DAbstract from opencsp.common.lib.geometry.RegionXY import RegionXY from opencsp.common.lib.geometry.Uxyz import Uxyz -from opencsp.common.lib.tool import log_tools as lt +import opencsp.common.lib.tool.log_tools as lt class ProcessSofastFixed: @@ -198,9 +199,13 @@ def load_measurement_data(self, measurement: MeasurementSofastFixed) -> None: """ self.measurement = measurement - def process_single_facet_optic(self, surface_data: dict) -> None: - """Processes single facet optic. Sets attribute - self.data_slope_solver + def process_single_facet_optic(self, surface: Surface2DAbstract) -> None: + """Processes single facet optic. Saves data to self.data_slope_solver + + Parameters + ---------- + surface : Surface2DAbstract + Surface 2d class """ # Find blobs blob_index = self.find_blobs() @@ -213,7 +218,7 @@ def process_single_facet_optic(self, surface_data: dict) -> None: kwargs = self.generate_geometry(blob_index, mask_raw) # Add surface fitting parameters - kwargs.update({'surface_data': surface_data}) + kwargs.update({'surface': surface}) # Calculate slope slope_solver = SlopeSolver(**kwargs) diff --git a/opencsp/app/sofast/test/test_ProcessSofastFixed.py b/opencsp/app/sofast/test/test_ProcessSofastFixed.py new file mode 100644 index 000000000..c7d6fa47f --- /dev/null +++ b/opencsp/app/sofast/test/test_ProcessSofastFixed.py @@ -0,0 +1,87 @@ +"""Example script that runs fixed pattern deflectometry analysis on saved data +""" + +from os.path import join +import unittest + +import numpy as np + +from opencsp.app.sofast.lib.DefinitionFacet import DefinitionFacet +from opencsp.app.sofast.lib.DotLocationsFixedPattern import DotLocationsFixedPattern +from opencsp.app.sofast.lib.MeasurementSofastFixed import MeasurementSofastFixed +from opencsp.app.sofast.lib.ProcessSofastFixed import ProcessSofastFixed +from opencsp.app.sofast.lib.SpatialOrientation import SpatialOrientation +from opencsp.common.lib.camera.Camera import Camera +from opencsp.common.lib.deflectometry.Surface2DParabolic import Surface2DParabolic +from opencsp.common.lib.opencsp_path.opencsp_root_path import opencsp_code_dir +import opencsp.common.lib.render.figure_management as fm +import opencsp.common.lib.render_control.RenderControlAxis as rca +import opencsp.common.lib.render_control.RenderControlFigure as rcfg +import opencsp.common.lib.tool.hdf5_tools as ht +import opencsp.common.lib.tool.file_tools as ft +import opencsp.common.lib.tool.log_tools as lt + + +class test_ProcessSofastFixed(unittest.TestCase): + @classmethod + def setUpClass(cls): + """Loads data and runs ProcessSofastFixed""" + dir_base = join(opencsp_code_dir(), 'test/data/measurements_sofast_fixed') + + # Definitions + file_camera = join(dir_base, "camera.h5") + file_facet = join(dir_base, "Facet_NSTTF.json") + file_ori = join(dir_base, 'spatial_orientation.h5') + file_dot_locs = join(dir_base, 'sofast_fixed_dot_locations.h5') + file_meas = join(dir_base, 'sofast_fixed_measurement.h5') + file_exp = join(dir_base, 'data_calculation_sofast_fixed.h5') + + cls.save_dir = join(opencsp_code_dir(), 'app/sofast/test/data/output') + ft.create_directories_if_necessary(cls.save_dir) + + lt.logger(join(cls.save_dir, 'sofast_fixed_process_log.txt'), lt.log.ERROR) + + surface = Surface2DParabolic(initial_focal_lengths_xy=(150.0, 150), robust_least_squares=False, downsample=1) + + # Load data + camera = Camera.load_from_hdf(file_camera) + facet_data = DefinitionFacet.load_from_json(file_facet) + dot_locs = DotLocationsFixedPattern.load_from_hdf(file_dot_locs) + orientation = SpatialOrientation.load_from_hdf(file_ori) + measurement = MeasurementSofastFixed.load_from_hdf(file_meas) + + # Load expected data + datasets = ['CalculationsFixedPattern/Facet_000/SlopeSolverData/slopes_facet_xy'] + data = ht.load_hdf5_datasets(datasets, file_exp) + cls.exp_slopes_xy = data['slopes_facet_xy'] + + # Instantiate class + cls.process_sofast_fixed = ProcessSofastFixed(orientation, camera, dot_locs, facet_data) + cls.process_sofast_fixed.load_measurement_data(measurement) + + # Process + cls.process_sofast_fixed.process_single_facet_optic(surface) + + def test_save_as_hdf(self): + """Tests saving to HDF file""" + self.process_sofast_fixed.save_to_hdf(join(self.save_dir, 'data_calculation_sofast_fixed.h5')) + + def test_save_figure(self): + """Tests generating and saving a figure""" + figure_control = rcfg.RenderControlFigure(tile_array=(1, 1), tile_square=True) + axis_control_m = rca.meters() + + fig_mng = fm.setup_figure(figure_control, axis_control_m, title='') + mirror = self.process_sofast_fixed.get_mirror('bilinear') + mirror.plot_orthorectified_slope(res=0.002, clim=7, axis=fig_mng.axis) + fig_mng.save(self.save_dir, 'sofast_fixed_orthorectified_slope_magnitude', 'png') + + def test_slopes_xy(self): + """Tests slope data""" + np.testing.assert_allclose( + self.process_sofast_fixed.data_slope_solver.slopes_facet_xy, self.exp_slopes_xy, rtol=0, atol=1e-6 + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/opencsp/test/data/measurements_sofast_fixed/Facet_NSTTF.json b/opencsp/test/data/measurements_sofast_fixed/Facet_NSTTF.json new file mode 100644 index 000000000..c8e5df1c0 --- /dev/null +++ b/opencsp/test/data/measurements_sofast_fixed/Facet_NSTTF.json @@ -0,0 +1,10 @@ +{ + "v_facet_corners": { + "x": [ 0.606, -0.606, -0.606, 0.606], + "y": [-0.606, -0.606, 0.606, 0.606], + "z": [ 0.0, 0.0, 0.0, 0.0 ] + }, + "v_centroid_facet": { + "x": [0.0], "y": [0.0], "z": [0.0] + } +} \ No newline at end of file diff --git a/opencsp/test/data/measurements_sofast_fixed/camera.h5 b/opencsp/test/data/measurements_sofast_fixed/camera.h5 new file mode 100644 index 000000000..aae693a2a Binary files /dev/null and b/opencsp/test/data/measurements_sofast_fixed/camera.h5 differ diff --git a/opencsp/test/data/measurements_sofast_fixed/data_calculation_sofast_fixed.h5 b/opencsp/test/data/measurements_sofast_fixed/data_calculation_sofast_fixed.h5 new file mode 100644 index 000000000..3b8e72949 Binary files /dev/null and b/opencsp/test/data/measurements_sofast_fixed/data_calculation_sofast_fixed.h5 differ diff --git a/opencsp/test/data/measurements_sofast_fixed/sofast_fixed_dot_locations.h5 b/opencsp/test/data/measurements_sofast_fixed/sofast_fixed_dot_locations.h5 new file mode 100644 index 000000000..7de6a0fa9 Binary files /dev/null and b/opencsp/test/data/measurements_sofast_fixed/sofast_fixed_dot_locations.h5 differ diff --git a/opencsp/test/data/measurements_sofast_fixed/sofast_fixed_measurement.h5 b/opencsp/test/data/measurements_sofast_fixed/sofast_fixed_measurement.h5 new file mode 100644 index 000000000..410b97526 Binary files /dev/null and b/opencsp/test/data/measurements_sofast_fixed/sofast_fixed_measurement.h5 differ diff --git a/opencsp/test/data/measurements_sofast_fixed/spatial_orientation.h5 b/opencsp/test/data/measurements_sofast_fixed/spatial_orientation.h5 new file mode 100644 index 000000000..61859cc1e Binary files /dev/null and b/opencsp/test/data/measurements_sofast_fixed/spatial_orientation.h5 differ