Skip to content

Commit 9d40536

Browse files
authored
Merge pull request #251 from braden6521/run_sofast_debug_on
Run SOFAST with debug on
2 parents 2f4de11 + bbb07e1 commit 9d40536

File tree

5 files changed

+178
-12
lines changed

5 files changed

+178
-12
lines changed

doc/source/example/sofast_fringe/config.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ Generating Standard Mirror Output Plots
3737
:members:
3838
:show-inheritance:
3939

40+
41+
Running SOFAST in Debug Mode
42+
============================
43+
44+
.. currentmodule:: example.sofast_fringe.example_process_in_debug_mode
45+
46+
.. automodule:: example.sofast_fringe.example_process_in_debug_mode
47+
48+
4049
Generate Rectangular Screen Definition
4150
======================================
4251

@@ -46,6 +55,7 @@ Generate Rectangular Screen Definition
4655
:members:
4756
:show-inheritance:
4857

58+
4959
Process SOFAST Temperature Experiment Data
5060
==========================================
5161

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"v_facet_corners": {
3+
"x": [0.606, -0.606, -0.606, 0.606],
4+
"y": [-0.606, -0.606, 1.606, 1.606],
5+
"z": [0.0, 0.0, 0.0, 0.0]
6+
},
7+
"v_centroid_facet": {
8+
"x": [0.0],
9+
"y": [0.0],
10+
"z": [0.0]
11+
}
12+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
"""
2+
Processes SOFAST data with debug mode enabled.
3+
4+
This module provides a function to process optical measurements using the SOFAST
5+
framework while enabling debug mode. The function performs the following tasks:
6+
loading necessary data files, calibrating fringe images, and processing the
7+
measurements. If an error occurs during processing, debug figures are saved for
8+
further analysis.
9+
10+
Usage:
11+
To execute the processing with debug mode, run the module directly. The output
12+
figures and log files will be saved in a specified directory structure.
13+
"""
14+
15+
# ChatGPT 4o-mini assisted with docstring creation
16+
17+
from os.path import join, dirname
18+
19+
from opencsp.app.sofast.lib.DisplayShape import DisplayShape as Display
20+
from opencsp.app.sofast.lib.DefinitionFacet import DefinitionFacet
21+
from opencsp.app.sofast.lib.ImageCalibrationScaling import ImageCalibrationScaling
22+
from opencsp.app.sofast.lib.MeasurementSofastFringe import MeasurementSofastFringe
23+
from opencsp.app.sofast.lib.ProcessSofastFringe import ProcessSofastFringe as Sofast
24+
from opencsp.app.sofast.lib.SpatialOrientation import SpatialOrientation
25+
from opencsp.common.lib.camera.Camera import Camera
26+
from opencsp.common.lib.deflectometry.Surface2DParabolic import Surface2DParabolic
27+
from opencsp.common.lib.opencsp_path.opencsp_root_path import opencsp_code_dir
28+
import opencsp.common.lib.tool.file_tools as ft
29+
import opencsp.common.lib.tool.log_tools as lt
30+
31+
32+
def example_process_in_debug_mode():
33+
"""
34+
Processes SOFAST data with debug mode enabled. This example intentionally runs SOFAST
35+
on a single facet with erroneous facet corner location information. When SOFAST is in
36+
debug mode, the cause of the most common errors can easily be diagnosed by looking at
37+
the produced figures from debug mode. Run this script as-is, the look through the output
38+
figures produced (location is printed in terminal) to see the cause of the error (the
39+
erroneous facet corner definition file).
40+
41+
This function performs the following steps:
42+
43+
1. Sets up the necessary directories and logging for output.
44+
2. Loads required data files, including camera, display, spatial orientation,
45+
measurement, calibration, and facet definition data.
46+
3. Calibrates the fringe images from the measurement data.
47+
4. Instantiates a SOFAST processing object and enables debug mode.
48+
5. Processes the optical data for a single facet. If an error occurs during
49+
processing, all debug figures are saved to the specified output directory.
50+
51+
Notes
52+
-----
53+
The function needs the following files to run:
54+
55+
- Measurement data (HDF5 format)
56+
- Camera calibration data (HDF5 format)
57+
- Display shape data (HDF5 format)
58+
- Spatial orientation data (HDF5 format)
59+
- Image calibration data (HDF5 format)
60+
- Facet definition data (JSON format)
61+
62+
Example
63+
-------
64+
To process the SOFAST data with debug mode enabled, simply call the function:
65+
66+
>>> example_process_in_debug_mode()
67+
68+
The resulting debug figures will be saved in the output directory if an error
69+
occurs during processing.
70+
"""
71+
# 1. General setup
72+
# ================
73+
74+
# Define save dir
75+
dir_save = join(dirname(__file__), "data/output/sofast_with_debug_mode_on")
76+
ft.create_directories_if_necessary(dir_save)
77+
78+
# Set up logger
79+
lt.logger(join(dir_save, "log.txt"), lt.log.INFO)
80+
81+
# Define sample data directory
82+
dir_data_sofast = join(opencsp_code_dir(), "test/data/sofast_fringe")
83+
dir_data_common = join(opencsp_code_dir(), "test/data/sofast_common")
84+
85+
# Directory Setup
86+
file_measurement = join(dir_data_sofast, "data_measurement/measurement_facet.h5")
87+
file_camera = join(dir_data_common, "camera_sofast_downsampled.h5")
88+
file_display = join(dir_data_common, "display_distorted_2d.h5")
89+
file_orientation = join(dir_data_common, "spatial_orientation.h5")
90+
file_calibration = join(dir_data_sofast, "data_measurement/image_calibration.h5")
91+
file_facet = join(dirname(__file__), "data/input/incorrect_facet_definition.json")
92+
93+
# 2. Load saved single facet Sofast collection data
94+
# =================================================
95+
camera = Camera.load_from_hdf(file_camera)
96+
display = Display.load_from_hdf(file_display)
97+
orientation = SpatialOrientation.load_from_hdf(file_orientation)
98+
measurement = MeasurementSofastFringe.load_from_hdf(file_measurement)
99+
calibration = ImageCalibrationScaling.load_from_hdf(file_calibration)
100+
facet_data = DefinitionFacet.load_from_json(file_facet)
101+
102+
# 3. Processes data with SOFAST and handle errors
103+
# ===============================================
104+
# Define surface definition (parabolic surface), this is the mirror
105+
surface = Surface2DParabolic(initial_focal_lengths_xy=(300.0, 300.0), robust_least_squares=True, downsample=10)
106+
107+
# Calibrate fringes - (aka sinosoidal image)
108+
measurement.calibrate_fringe_images(calibration)
109+
110+
# Instantiate sofast object
111+
sofast = Sofast(measurement, orientation, camera, display)
112+
113+
# Turn on debug mode
114+
sofast.params.debug_geometry.debug_active = True
115+
116+
# Process
117+
try:
118+
sofast.process_optic_singlefacet(facet_data, surface)
119+
except ValueError:
120+
# Save all debug figures
121+
lt.info(f'An error occured when processing SOFAST data. Saving all debug figures to {dir_save}.')
122+
for idx, fig in enumerate(sofast.params.debug_geometry.figures):
123+
fig.savefig(join(dir_save, f'{idx:02d}.png'))
124+
125+
126+
if __name__ == "__main__":
127+
example_process_in_debug_mode()

opencsp/app/sofast/lib/process_optics_geometry.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,13 @@ def process_singlefacet_geometry(
159159
plt.title("Expected Optic Corners")
160160

161161
# Refine locations of optic corners with mask
162-
prs = [params.perimeter_refine_axial_search_dist, params.perimeter_refine_perpendicular_search_dist]
163-
loop_facet_image_refine = ip.refine_mask_perimeter(loop_optic_image_exp, v_edges_image, *prs)
164-
data_image_processing_facet.loop_facet_image_refine = loop_facet_image_refine
162+
try:
163+
prs = [params.perimeter_refine_axial_search_dist, params.perimeter_refine_perpendicular_search_dist]
164+
loop_facet_image_refine = ip.refine_mask_perimeter(loop_optic_image_exp, v_edges_image, *prs)
165+
data_image_processing_facet.loop_facet_image_refine = loop_facet_image_refine
166+
except ValueError as er:
167+
lt.critical(repr(er))
168+
lt.error_and_raise(ValueError, "SOFAST failed to find the corners of the optic.")
165169

166170
# Plot refined optic corners
167171
if debug.debug_active:
@@ -516,12 +520,16 @@ def process_multifacet_geometry(
516520
plt.title("Expected Perimeter Points")
517521

518522
# Refine perimeter points
519-
args = [
520-
params_geometry.perimeter_refine_axial_search_dist,
521-
params_geometry.perimeter_refine_perpendicular_search_dist,
522-
]
523-
loop_ensemble_image_refine = ip.refine_mask_perimeter(loop_ensemble_exp, v_edges_image, *args)
524-
data_image_processing_general.loop_optic_image_refine = loop_ensemble_image_refine
523+
try:
524+
args = [
525+
params_geometry.perimeter_refine_axial_search_dist,
526+
params_geometry.perimeter_refine_perpendicular_search_dist,
527+
]
528+
loop_ensemble_image_refine = ip.refine_mask_perimeter(loop_ensemble_exp, v_edges_image, *args)
529+
data_image_processing_general.loop_optic_image_refine = loop_ensemble_image_refine
530+
except ValueError as er:
531+
lt.critical(repr(er))
532+
lt.error_and_raise(ValueError, "SOFAST failed to find the corners of the optic.")
525533

526534
# Plot refined perimeter points
527535
if debug.debug_active:
@@ -558,9 +566,15 @@ def process_multifacet_geometry(
558566
]
559567
loops_facets_refined: list[LoopXY] = []
560568
for idx in range(num_facets):
561-
loop = ip.refine_facet_corners(v_facet_corners_image_exp[idx], v_uv_facet_cent_exp[idx], v_edges_image, *args)
562-
loops_facets_refined.append(loop)
563-
data_image_processing_facet[idx].loop_facet_image_refine = loop
569+
try:
570+
loop = ip.refine_facet_corners(
571+
v_facet_corners_image_exp[idx], v_uv_facet_cent_exp[idx], v_edges_image, *args
572+
)
573+
loops_facets_refined.append(loop)
574+
data_image_processing_facet[idx].loop_facet_image_refine = loop
575+
except ValueError as er:
576+
lt.critical(repr(er))
577+
lt.error_and_raise(ValueError, "SOFAST failed to find the corners of the optic.")
564578

565579
# Plot refined perimeter points
566580
if debug.debug_active:

opencsp/test/test_DocStringsExist.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33

44
# Assume opencsp is in PYTHONPATH
55
import opencsp as opencsp
6+
import example.sofast_fringe.example_process_in_debug_mode
67
import example.sofast_calibration.example_calibration_screen_shape
78

89
# Examples
910
import example.sofast_fringe.example_make_rectangular_screen_definition
1011
import example.sofast_fringe.sofast_temperature_analysis
1112

13+
1214
# TODO: why aren't these imported from import opencsp as opencsp above
1315
from opencsp.app.camera_calibration import CameraCalibration
1416
from opencsp.app.camera_calibration.lib.ViewAnnotatedImages import ViewAnnotatedImages
@@ -183,6 +185,7 @@ class test_Docstrings(unittest.TestCase):
183185
# TODO: example_sofast_fringe_list
184186
# TODO: example_targetcolor_list
185187
example_list = [
188+
example.sofast_fringe.example_process_in_debug_mode,
186189
example.sofast_fringe.sofast_temperature_analysis,
187190
example.sofast_fringe.example_make_rectangular_screen_definition,
188191
example.sofast_calibration.example_calibration_screen_shape,

0 commit comments

Comments
 (0)