From c4fbabbfa7cdb66dc5348cdb72fd20b8a897a12b Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Sun, 19 Oct 2025 10:24:46 -0700 Subject: [PATCH 01/10] wip support square trihedrals and new format --- python/packages/isce3/cal/corner_reflector.py | 43 +++++++++++++------ python/packages/nisar/cal/corner_reflector.py | 23 +++++++--- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/python/packages/isce3/cal/corner_reflector.py b/python/packages/isce3/cal/corner_reflector.py index 57f6d4a21..5704d3fb5 100644 --- a/python/packages/isce3/cal/corner_reflector.py +++ b/python/packages/isce3/cal/corner_reflector.py @@ -3,6 +3,7 @@ import os from collections.abc import Iterable, Iterator, Mapping from dataclasses import dataclass +from enum import Enum from typing import Optional import numpy as np @@ -11,9 +12,12 @@ import isce3 +class CRShape(str, Enum): + SQUARE = "square" + TRIANGULAR = "triangular" @dataclass(frozen=True) -class TriangularTrihedralCornerReflector: +class TrihedralCornerReflector: """ A triangular trihedral corner reflector (CR). @@ -40,6 +44,7 @@ class TriangularTrihedralCornerReflector: elevation: float azimuth: float side_length: float + shape: CRShape def parse_triangular_trihedral_cr_csv( @@ -270,8 +275,8 @@ def target2platform_unit_vector( return normalize_vector(platform_xyz - target_xyz) -def predict_triangular_trihedral_cr_rcs( - cr: TriangularTrihedralCornerReflector, +def predict_trihedral_cr_rcs( + cr: TrihedralCornerReflector, orbit: isce3.core.Orbit, doppler: isce3.core.LUT2d, wavelength: float, @@ -280,9 +285,9 @@ def predict_triangular_trihedral_cr_rcs( geo2rdr_params: Optional[Mapping[str, float]] = None, ) -> float: r""" - Predict the radar cross-section (RCS) of a triangular trihedral corner reflector. + Predict the radar cross-section (RCS) of a trihedral corner reflector. - Calculate the predicted monostatic RCS of a triangular trihedral corner reflector, + Calculate the predicted monostatic RCS of a trihedral corner reflector, given the corner reflector dimensions and imaging geometry\ [1]_. Parameters @@ -323,6 +328,9 @@ def predict_triangular_trihedral_cr_rcs( Cross-Sections - VI. Cross-sections of corner reflectors and other multiple scatterers at microwave frequencies,” University of Michigan Radiation Laboratory, Tech. Rep., October 1953. + .. [2] Armin W. Doerry and Billy C. Brock, "Radar Cross Section of + Triangular Trihedral Reflector with Extended Bottom Plate," Sandia + Report SAND2009-2993, May 2009, p. 21. """ # Get the target-to-platform line-of-sight vector in ECEF coordinates. los_vec_ecef = target2platform_unit_vector( @@ -341,18 +349,25 @@ def predict_triangular_trihedral_cr_rcs( ) los_vec_cr = enu_to_cr_rotation(cr.elevation, cr.azimuth).rotate(los_vec_enu) - # Get the CR boresight unit vector in the same coordinates. - boresight_vec = normalize_vector([1.0, 1.0, 1.0]) - - # Get the direction cosines between the two vectors, sorted in ascending order. - p1, p2, p3 = np.sort(los_vec_cr * boresight_vec) + # Get the direction cosines sorted in ascending order. + p1, p2, p3 = np.sort(los_vec_cr) # Compute expected RCS. - a = p1 + p2 + p3 - if (p1 + p2) > p3: - b = np.sqrt(3.0) * a - 2.0 / (np.sqrt(3.0) * a) + if cr.shape == "triangular": + a = p1 + p2 + p3 + if (p1 + p2) > p3: + # typical case close to boresight + b = a - 2.0 / a + else: + b = 4.0 * p1 * p2 / a + elif cr.shape == "square": + if p2 >= (p3 / 2): + # typical case close to boresight + b = p1 * (4 - p3 / p2) + else: + b = 4 * p1 * p2 / p3 else: - b = 4.0 * p1 * p2 / a + raise ValueError(f"invalid trihedral shape={cr.shape}") return 4.0 * np.pi * cr.side_length ** 4 * b ** 2 / wavelength ** 2 diff --git a/python/packages/nisar/cal/corner_reflector.py b/python/packages/nisar/cal/corner_reflector.py index 81adf6ee6..001f6e27a 100644 --- a/python/packages/nisar/cal/corner_reflector.py +++ b/python/packages/nisar/cal/corner_reflector.py @@ -25,17 +25,26 @@ class CRValidity(IntFlag): References ---------- .. [1] B. Hawkins, "Corner Reflector Software Interface Specification," JPL - D-107698 (2023). + D-107698 (2025). """ INVALID = 0 """Not valid for any usage (out of service).""" - IPR = 1 - """Usable for assessing shape of impulse response (ISLR, PSLR, resolution).""" - RAD_POL = 2 - """Usable for radiometric and polarimetric calibration.""" + LSAR_IPR = 1 + """Usable for assessing shape of LSAR impulse response (ISLR, PSLR, resolution).""" + LSAR_RAD_POL = 2 + """Usable for LSAR radiometric and polarimetric calibration.""" GEOM = 4 """Usable for geometric calibration.""" + SSAR_IPR = 8 + """Usable for assessing shape of SSAR impulse response (ISLR, PSLR, resolution).""" + SSAR_RAD_POL = 16 + """Usable for SSAR radiometric and polarimetric calibration.""" + + +class CRShape(str, Enum): + SQUARE_TRIHEDRAL = "square" + TRIANGULAR_TRIHEDRAL = "triangular" @dataclass(frozen=True) @@ -299,7 +308,7 @@ def get_valid_crs( Validity flag(s) to check for. If None, only corner reflectors that are out of service (i.e. with validity code == 0) are filtered out. Otherwise, corner reflectors that do not have any of the specified validity flags set will be - filtered out. For example, using ``flags=CRValidity.RAD_POL | CRValidity.GEOM`` + filtered out. For example, using ``flags=CRValidity.LSAR_RAD_POL | CRValidity.GEOM`` would yield only those corner reflectors that were valid for either radiometric/polarimetric calibration or geometric calibration activities. Defaults to None. @@ -355,7 +364,7 @@ def parse_and_filter_corner_reflector_csv( Validity flag(s) to check for. If None, only corner reflectors that are out of service (i.e. with validity code == 0) are filtered out. Otherwise, corner reflectors that do not have any of the specified validity flags set will be - filtered out. For example, using ``flags=CRValidity.RAD_POL | CRValidity.GEOM`` + filtered out. For example, using ``flags=CRValidity.LSAR_RAD_POL | CRValidity.GEOM`` would yield only those corner reflectors that were valid for either radiometric/polarimetric calibration or geometric calibration activities. Defaults to None. From 6ace09dd2551431b0ea83deaa101eee6ab737e1e Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 08:50:43 -0800 Subject: [PATCH 02/10] Move CR model into a separate function for easier testing --- python/packages/isce3/cal/corner_reflector.py | 75 +++++++++++++------ 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/python/packages/isce3/cal/corner_reflector.py b/python/packages/isce3/cal/corner_reflector.py index 5704d3fb5..bd16181bd 100644 --- a/python/packages/isce3/cal/corner_reflector.py +++ b/python/packages/isce3/cal/corner_reflector.py @@ -275,6 +275,58 @@ def target2platform_unit_vector( return normalize_vector(platform_xyz - target_xyz) +def eval_trihedral_rcs_model(los, side_length, wavelength, shape): + """ + Calculate RCS of a trihedral corner reflector (CR). + + Parameters + ---------- + los : array_like + Line-of-sight direction from the corner reflector vertex to target, + expressed as a unit-vector in the right-handed coordinate system + defined by the legs of the corner reflector (Z-up). + side_length : float + Length of a leg of the corner reflector (e.g., the shorter side for + triangular trihedrals) in m. + wavelength : float + Wavelength of the sensor in m. + shape : CRShape | str + Shape of each panel. + + Returns + ------- + rcs : float + Radar cross section in m^2 + """ + # Get the direction cosines sorted in ascending order. + p1, p2, p3 = np.sort(los) + if p1 < 0.0: + raise ValueError("invalid corner reflector viewing geometry" + f" los={los}") + # Require unit vector. + if not np.isclose(np.linalg.norm(los), 1.0): + raise ValueError("line-of-sight direction must be a unit vector") + + # Compute expected RCS. + if shape == "triangular": + a = p1 + p2 + p3 + if (p1 + p2) > p3: + # typical case close to boresight + b = a - 2.0 / a + else: + b = 4.0 * p1 * p2 / a + elif shape == "square": + if p2 >= (p3 / 2): + # typical case close to boresight + b = p1 * (4 - p3 / p2) + else: + b = 4 * p1 * p2 / p3 + else: + raise ValueError(f"invalid trihedral shape={shape}") + + return 4.0 * np.pi * (side_length**2 * b / wavelength)**2 + + def predict_trihedral_cr_rcs( cr: TrihedralCornerReflector, orbit: isce3.core.Orbit, @@ -349,27 +401,8 @@ def predict_trihedral_cr_rcs( ) los_vec_cr = enu_to_cr_rotation(cr.elevation, cr.azimuth).rotate(los_vec_enu) - # Get the direction cosines sorted in ascending order. - p1, p2, p3 = np.sort(los_vec_cr) - - # Compute expected RCS. - if cr.shape == "triangular": - a = p1 + p2 + p3 - if (p1 + p2) > p3: - # typical case close to boresight - b = a - 2.0 / a - else: - b = 4.0 * p1 * p2 / a - elif cr.shape == "square": - if p2 >= (p3 / 2): - # typical case close to boresight - b = p1 * (4 - p3 / p2) - else: - b = 4 * p1 * p2 / p3 - else: - raise ValueError(f"invalid trihedral shape={cr.shape}") - - return 4.0 * np.pi * cr.side_length ** 4 * b ** 2 / wavelength ** 2 + return eval_trihedral_rcs_model(los_vec_cr, cr.side_length, wavelength, + cr.shape) def get_target_observation_time_and_elevation( From eb4c51821b620e386970360e2a209b2dc50b174c Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 12:26:21 -0800 Subject: [PATCH 03/10] Remove "triangular" from names in isce3 --- python/packages/isce3/cal/__init__.py | 4 ++-- python/packages/isce3/cal/corner_reflector.py | 23 +++++++++++-------- .../packages/isce3/cal/corner_reflector.py | 5 ++-- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/python/packages/isce3/cal/__init__.py b/python/packages/isce3/cal/__init__.py index 7638d4159..25cfeb6c2 100644 --- a/python/packages/isce3/cal/__init__.py +++ b/python/packages/isce3/cal/__init__.py @@ -1,9 +1,9 @@ from . import point_target_info from .corner_reflector import ( - TriangularTrihedralCornerReflector, + TrihedralCornerReflector, get_crs_in_polygon, get_target_observation_time_and_elevation, parse_triangular_trihedral_cr_csv, - predict_triangular_trihedral_cr_rcs, + predict_trihedral_cr_rcs, ) from .radar_cross_section import measure_target_rcs diff --git a/python/packages/isce3/cal/corner_reflector.py b/python/packages/isce3/cal/corner_reflector.py index bd16181bd..124188a7f 100644 --- a/python/packages/isce3/cal/corner_reflector.py +++ b/python/packages/isce3/cal/corner_reflector.py @@ -19,7 +19,7 @@ class CRShape(str, Enum): @dataclass(frozen=True) class TrihedralCornerReflector: """ - A triangular trihedral corner reflector (CR). + A trihedral corner reflector (CR). Parameters ---------- @@ -37,6 +37,8 @@ class TrihedralCornerReflector: geographic East, measured clockwise positive in the E-N plane. side_length : float The length of each leg of the trihedral, in meters. + shape : CRShape + The shape of the faces (triangular or square). """ id: str @@ -49,7 +51,7 @@ class TrihedralCornerReflector: def parse_triangular_trihedral_cr_csv( csvfile: os.PathLike, -) -> Iterator[TriangularTrihedralCornerReflector]: +) -> Iterator[TrihedralCornerReflector]: """ Parse a CSV file containing triangular trihedral corner reflector (CR) data. @@ -74,7 +76,7 @@ def parse_triangular_trihedral_cr_csv( Yields ------ - cr : TriangularTrihedralCornerReflector + cr : TrihedralCornerReflector A corner reflector. """ dtype = np.dtype( @@ -108,10 +110,13 @@ def parse_triangular_trihedral_cr_csv( for attr in ["lat", "lon", "az", "el"]: crs[attr] = np.deg2rad(crs[attr]) + # Old format, assume all corners are triangular. + shape = "triangular" + for cr in crs: id, lat, lon, height, az, el, side_length = cr llh = isce3.core.LLH(lon, lat, height) - yield TriangularTrihedralCornerReflector(id, llh, el, az, side_length) + yield TrihedralCornerReflector(id, llh, el, az, side_length, shape) def cr_to_enu_rotation(el: float, az: float) -> isce3.core.Quaternion: @@ -344,7 +349,7 @@ def predict_trihedral_cr_rcs( Parameters ---------- - cr : TriangularTrihedralCornerReflector + cr : TrihedralCornerReflector The corner reflector position, orientation, and size. orbit : isce3.core.Orbit The trajectory of the radar antenna phase center. @@ -501,10 +506,10 @@ def get_target_observation_time_and_elevation( def get_crs_in_polygon( - crs: Iterable[TriangularTrihedralCornerReflector], + crs: Iterable[TrihedralCornerReflector], polygon: shapely.Polygon, buffer: float | None = None, -) -> Iterator[TriangularTrihedralCornerReflector]: +) -> Iterator[TrihedralCornerReflector]: """ Filter out corner reflectors located outside of a Lon/Lat polygon. @@ -517,7 +522,7 @@ def get_crs_in_polygon( Parameters ---------- - crs : iterable of TriangularTrihedralCornerReflector + crs : iterable of TrihedralCornerReflector Input iterable of corner reflector data. polygon : shapely.Polygon A convex polygon, in geodetic Lon/Lat coordinates w.r.t the WGS 84 ellipsoid, @@ -532,7 +537,7 @@ def get_crs_in_polygon( Yields ------ - cr : TriangularTrihedralCornerReflector + cr : TrihedralCornerReflector A corner reflector from the input iterable that was contained within the polygon. diff --git a/tests/python/packages/isce3/cal/corner_reflector.py b/tests/python/packages/isce3/cal/corner_reflector.py index f55b21bb3..bb9b3f53d 100644 --- a/tests/python/packages/isce3/cal/corner_reflector.py +++ b/tests/python/packages/isce3/cal/corner_reflector.py @@ -34,7 +34,7 @@ def angle_between(u: ArrayLike, v: ArrayLike, *, degrees: bool = False) -> float return theta -class TestParseTriangularTrihedralCornerReflectorCSV: +class TestParseTrihedralCornerReflectorCSV: def test_parse_csv(self): # Parse CSV file containing 3 Northeast-looking corner reflectors. csv = Path(iscetest.data) / "abscal/REE_CORNER_REFLECTORS_INFO.csv" @@ -268,12 +268,13 @@ def test_get_crs_in_polygon(): # Make a list of corner reflectors with unique IDs, one at each lon/lat location. crs = [ - isce3.cal.TriangularTrihedralCornerReflector( + isce3.cal.TrihedralCornerReflector( id=f"CR{i}", llh=isce3.core.LLH(np.deg2rad(lon), np.deg2rad(lat), 0.0), elevation=0.0, azimuth=0.0, side_length=1.0, + shape="triangular", ) for i, (lon, lat) in enumerate(cr_lonlats) ] From 1f81c8ebbba327e744147844ccceb789096c62d6 Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 16:52:04 -0800 Subject: [PATCH 04/10] Remove "LSAR" from flags for easier refactor and support "Shape" column in CSV. --- python/packages/nisar/cal/corner_reflector.py | 52 ++++++++++++------- .../packages/nisar/cal/corner_reflector.py | 3 +- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/python/packages/nisar/cal/corner_reflector.py b/python/packages/nisar/cal/corner_reflector.py index a3b645c7f..ec8a75f58 100644 --- a/python/packages/nisar/cal/corner_reflector.py +++ b/python/packages/nisar/cal/corner_reflector.py @@ -9,7 +9,7 @@ import numpy as np import isce3 -from isce3.cal import TriangularTrihedralCornerReflector +from isce3.cal import TrihedralCornerReflector class CRValidity(IntFlag): @@ -30,9 +30,9 @@ class CRValidity(IntFlag): INVALID = 0 """Not valid for any usage (out of service).""" - LSAR_IPR = 1 + IPR = 1 """Usable for assessing shape of LSAR impulse response (ISLR, PSLR, resolution).""" - LSAR_RAD_POL = 2 + RAD_POL = 2 """Usable for LSAR radiometric and polarimetric calibration.""" GEOM = 4 """Usable for geometric calibration.""" @@ -42,17 +42,12 @@ class CRValidity(IntFlag): """Usable for SSAR radiometric and polarimetric calibration.""" -class CRShape(str, Enum): - SQUARE_TRIHEDRAL = "square" - TRIANGULAR_TRIHEDRAL = "triangular" - - @dataclass(frozen=True) -class CornerReflector(TriangularTrihedralCornerReflector): +class CornerReflector(TrihedralCornerReflector): """ - A triangular trihedral corner reflector (CR) used for NISAR calibration. + A trihedral corner reflector (CR) used for NISAR calibration. - Extends `isce3.cal.TriangularTrihedralCornerReflector` with additional information + Extends `isce3.cal.TrihedralCornerReflector` with additional information required for NISAR Science Calibration and Validation (Cal/Val) activities. Parameters @@ -82,10 +77,12 @@ class CornerReflector(TriangularTrihedralCornerReflector): motion. Velocity should be provided in a local East-North-Up (ENU) coordinate system with respect to the WGS 84 reference ellipsoid with its origin at the CR location. + shape : CRShape + The shape of the faces (triangular or square). See Also -------- - isce3.cal.TriangularTrihedralCornerReflector + isce3.cal.TrihedralCornerReflector parse_corner_reflector_csv """ @@ -133,6 +130,7 @@ def parse_corner_reflector_csv(csvfile: str | os.PathLike) -> Iterator[CornerRef 10. Velocity East (m/s) 11. Velocity North (m/s) 12. Velocity Up (m/s) + 13. Shape Parameters ---------- @@ -148,7 +146,8 @@ def parse_corner_reflector_csv(csvfile: str | os.PathLike) -> Iterator[CornerRef ----- This function outputs the full survey history for each corner reflector found in the CSV file. It does not filter out any invalid corner reflectors or outdated survey - data. + data. If the "Shape" column is not found, all corners will be assumed to be + triangular (backwards compatible with original spec). See Also -------- @@ -181,23 +180,33 @@ def parse_corner_reflector_csv(csvfile: str | os.PathLike) -> Iterator[CornerRef ("vel_e", np.float64), ("vel_n", np.float64), ("vel_u", np.float64), + ("shape", np.object_) ] ) # Parse CSV data. # Treat the header row ("Corner reflector ID, ...") as a comment so that it will be # ignored if present. - try: - data = np.loadtxt( + def loadtxt(dtype): + return np.loadtxt( csvfile, dtype=dtype, delimiter=",", ndmin=1, comments=["#", "Corner reflector ID,", '"Corner reflector ID",'], ) + + try: + data = loadtxt(dtype) except ValueError as e: - errmsg = f"error parsing NISAR corner reflector CSV file {csvfile}" - raise RuntimeError(errmsg) from e + # Try again without shape column, since that was added later. + dtype = np.dtype([(name, dt) for (name, (dt, _)) in dtype.fields.items() + if name != 'shape']) + try: + data = loadtxt(dtype) + except ValueError as e: + errmsg = f"error parsing NISAR corner reflector CSV file {csvfile}" + raise RuntimeError(errmsg) from e # Convert lat, lon, az, & el angles to radians. for attr in ["lat", "lon", "az", "el"]: @@ -211,6 +220,10 @@ def parse_corner_reflector_csv(csvfile: str | os.PathLike) -> Iterator[CornerRef survey_date = isce3.core.DateTime(d[7].strip()) validity = CRValidity(int(d[8])) velocity = np.asarray([d[9], d[10], d[11]], dtype=np.float64) + if "shape" in dtype.fields: + shape = d["shape"].strip() + else: + shape = "triangular" yield CornerReflector( id=corner_id, @@ -221,6 +234,7 @@ def parse_corner_reflector_csv(csvfile: str | os.PathLike) -> Iterator[CornerRef survey_date=survey_date, validity=validity, velocity=velocity, + shape=shape, ) @@ -406,7 +420,7 @@ def filter_crs_per_az_heading(crs, az_heading, az_atol=np.deg2rad(30.0)): Parameters ---------- crs : iterable of type CornerReflector or - TriangularTrihedralCornerReflector. + TrihedralCornerReflector. az_heading : float Desired AZ/heading angle in radians w.r.t. geographic North. az_atol : float, default=pi/6 (30 degrees) @@ -417,7 +431,7 @@ def filter_crs_per_az_heading(crs, az_heading, az_atol=np.deg2rad(30.0)): Yields ------ - cr : CornerReflector or TriangularTrihedralCornerReflector + cr : CornerReflector or TrihedralCornerReflector The datatype of cr depends on type of items in `crs`. """ diff --git a/tests/python/packages/nisar/cal/corner_reflector.py b/tests/python/packages/nisar/cal/corner_reflector.py index 2f9c9f430..79dc4adbb 100644 --- a/tests/python/packages/nisar/cal/corner_reflector.py +++ b/tests/python/packages/nisar/cal/corner_reflector.py @@ -42,7 +42,7 @@ def create_tmp_text_file(contents: str, suffix: str | None = None) -> Iterator[P yield filepath -@pytest.mark.parametrize("validity", [-1, 8]) +@pytest.mark.parametrize("validity", [-1, 32]) def test_bad_corner_reflector_validity(validity: int): errmsg = "validity flag has invalid value" with pytest.raises(ValueError, match=errmsg): @@ -55,6 +55,7 @@ def test_bad_corner_reflector_validity(validity: int): survey_date=isce3.core.DateTime("1970-01-01"), validity=validity, velocity=[0.0, 0.0, 0.0], + shape="triangular", ) From ae32ff7250207fb24fbd9dc6f76ff199d5cbf491 Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:06:24 -0800 Subject: [PATCH 05/10] check peak RCS value in unit test --- .../packages/isce3/cal/corner_reflector.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/python/packages/isce3/cal/corner_reflector.py b/tests/python/packages/isce3/cal/corner_reflector.py index bb9b3f53d..372abe5ff 100644 --- a/tests/python/packages/isce3/cal/corner_reflector.py +++ b/tests/python/packages/isce3/cal/corner_reflector.py @@ -15,6 +15,7 @@ cr_to_enu_rotation, enu_to_cr_rotation, normalize_vector, + eval_trihedral_rcs_model, ) import nisar @@ -292,3 +293,35 @@ def test_get_crs_in_polygon(): filtered_crs = isce3.cal.get_crs_in_polygon(crs, lonlat_polygon, buffer=0.1) filtered_cr_ids = [cr.id for cr in filtered_crs] assert filtered_cr_ids == cr_ids[:-1] + + +# Make sure angle-dependent model gives the same answer as the simple formulae +# for the peak RCS at the boresight direction. + +def get_peak_rcs_triangular(side_length, wavelength): + return 4 / 3 * np.pi * (side_length**2 / wavelength)**2 + +def get_peak_rcs_square(side_length, wavelength): + return 12 * np.pi * (side_length**2 / wavelength)**2 + +def pow2db(x): + return 10 * np.log10(x) + +@pytest.mark.parametrize("side_length,wavelength,shape", [ + (1.0, 0.03, "triangular"), + (1.0, 0.03, "square"), + (1.0, 0.25, "triangular"), + (1.0, 0.25, "square"), + (3.0, 0.5, "triangular"), + (3.0, 0.5, "square"), +]) +def test_peak_rcs(side_length, wavelength, shape): + los = np.array([1, 1, 1]) / np.sqrt(3) + rcs = eval_trihedral_rcs_model(los, side_length, wavelength, shape) + if shape == "triangular": + expected_rcs = get_peak_rcs_triangular(side_length, wavelength) + elif shape == "square": + expected_rcs = get_peak_rcs_square(side_length, wavelength) + else: + assert False, "invalid CR shape in unit test" + assert np.isclose(pow2db(rcs), pow2db(expected_rcs), rtol=0, atol=0.01) \ No newline at end of file From 3e359231c586548928d1528edb9eaf9179919c1c Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:35:37 -0800 Subject: [PATCH 06/10] Add RCS continuity check --- .../packages/isce3/cal/corner_reflector.py | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/python/packages/isce3/cal/corner_reflector.py b/tests/python/packages/isce3/cal/corner_reflector.py index 372abe5ff..50814713a 100644 --- a/tests/python/packages/isce3/cal/corner_reflector.py +++ b/tests/python/packages/isce3/cal/corner_reflector.py @@ -324,4 +324,26 @@ def test_peak_rcs(side_length, wavelength, shape): expected_rcs = get_peak_rcs_square(side_length, wavelength) else: assert False, "invalid CR shape in unit test" - assert np.isclose(pow2db(rcs), pow2db(expected_rcs), rtol=0, atol=0.01) \ No newline at end of file + assert np.isclose(pow2db(rcs), pow2db(expected_rcs), rtol=0, atol=0.01) + + +# There's a branch in the RCS vs angle model, so make sure the RCS is continuous + +@pytest.mark.parametrize("shape", ["triangular", "square"]) +def test_rcs_continuity(shape): + az = np.deg2rad(45) + el = np.deg2rad(np.linspace(15, 75, 361)) + los = np.array([ + np.cos(az) * np.cos(el), + np.sin(az) * np.cos(el), + np.sin(el) + ]).transpose() + a = 1.5 + λ = 0.23 + rcs = np.array([eval_trihedral_rcs_model(los[i], a, λ, shape) + for i in range(len(el))]) + rcs_db = pow2db(rcs) + eld_step = np.rad2deg(el[1] - el[0]) + diff_rcs_db = np.diff(rcs_db) / eld_step + max_diff = 1.5 # dB / deg + npt.assert_array_less(np.abs(diff_rcs_db), max_diff) \ No newline at end of file From 2e266ec410b67407266354818cafa217fa294785 Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:05:00 -0800 Subject: [PATCH 07/10] Add new format CSV unit test. Fix capitalization. --- python/packages/isce3/cal/__init__.py | 1 + python/packages/nisar/cal/corner_reflector.py | 10 +- .../NISAR_ANC_CORNER_REFLECTORS_006.csv | 189 ++++++++++++++++++ .../packages/nisar/cal/corner_reflector.py | 13 ++ 4 files changed, 208 insertions(+), 5 deletions(-) create mode 100644 tests/data/abscal/NISAR_ANC_CORNER_REFLECTORS_006.csv diff --git a/python/packages/isce3/cal/__init__.py b/python/packages/isce3/cal/__init__.py index 25cfeb6c2..3777e3548 100644 --- a/python/packages/isce3/cal/__init__.py +++ b/python/packages/isce3/cal/__init__.py @@ -1,5 +1,6 @@ from . import point_target_info from .corner_reflector import ( + CRShape, TrihedralCornerReflector, get_crs_in_polygon, get_target_observation_time_and_elevation, diff --git a/python/packages/nisar/cal/corner_reflector.py b/python/packages/nisar/cal/corner_reflector.py index ec8a75f58..ae25f2df7 100644 --- a/python/packages/nisar/cal/corner_reflector.py +++ b/python/packages/nisar/cal/corner_reflector.py @@ -9,7 +9,7 @@ import numpy as np import isce3 -from isce3.cal import TrihedralCornerReflector +from isce3.cal import CRShape, TrihedralCornerReflector class CRValidity(IntFlag): @@ -68,6 +68,8 @@ class CornerReflector(TrihedralCornerReflector): the clockwise direction. side_length : float The length of each leg of the trihedral, in meters. + shape : CRShape + The shape of the faces (triangular or square). survey_date : isce3.core.DateTime UTC date and time when the corner reflector survey was conducted. validity : CRValidity @@ -77,8 +79,6 @@ class CornerReflector(TrihedralCornerReflector): motion. Velocity should be provided in a local East-North-Up (ENU) coordinate system with respect to the WGS 84 reference ellipsoid with its origin at the CR location. - shape : CRShape - The shape of the faces (triangular or square). See Also -------- @@ -221,7 +221,7 @@ def loadtxt(dtype): validity = CRValidity(int(d[8])) velocity = np.asarray([d[9], d[10], d[11]], dtype=np.float64) if "shape" in dtype.fields: - shape = d["shape"].strip() + shape = d["shape"].strip().lower() else: shape = "triangular" @@ -231,10 +231,10 @@ def loadtxt(dtype): elevation=d[5], azimuth=d[4], side_length=d[6], + shape=CRShape(shape), survey_date=survey_date, validity=validity, velocity=velocity, - shape=shape, ) diff --git a/tests/data/abscal/NISAR_ANC_CORNER_REFLECTORS_006.csv b/tests/data/abscal/NISAR_ANC_CORNER_REFLECTORS_006.csv new file mode 100644 index 000000000..0088bee8d --- /dev/null +++ b/tests/data/abscal/NISAR_ANC_CORNER_REFLECTORS_006.csv @@ -0,0 +1,189 @@ +Corner reflector ID,Latitude (deg),Longitude (deg),Height above ellipsoid (m),Azimuth (deg),Tilt / Elevation (deg),Side length (m),Survey Date,Validity,Velocity East (m/s),Velocity North (m/s),Velocity Up (m/s), Shape +N01K,35.59190388,-98.93222547,480.08,359.25,14.26,2.8, 2021-06-04T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N01K,35.59190425,-98.93222642,480.1412,359.31,14.3,2.8, 2022-09-28T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N01K,35.59190298,-98.93222671,480.111,359.54,13.97,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N02K,35.58689743,-99.26711946,491.0526,180,12.55,2.8, 2021-12-17T00:00:00.0000,15,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N02K,35.58689741,-99.26702565,491.0525,182.5,15.5,2.8, 2022-06-25T00:00:00.0000,15,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N02K,35.58689632,-99.26702981,491.0222,183.5,15.73,2.8, 2022-09-28T00:00:00.0000,15,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N02K,35.53645902,-99.2100412,481.1742,179.76,17.17,2.8, 2023-05-22T00:00:00.0000,15,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N02K,35.53645813,-99.21004162,481.1376,199.23,17.55,2.8, 2025-05-09T00:00:00.0000,15,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N03K,35.58880508,-98.93568049,479.2867,178.5,14.33,2.8, 2021-06-04T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N03K,35.58880389,-98.93568388,479.2929,180.95,14.9,2.8, 2022-09-28T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N03K,35.58880704,-98.93568521,479.3595,179.86,14,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N04K,35.58365554,-99.2671665,491.404,359,16.6,2.8, 2021-12-17T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N04K,35.58365552,-99.26716659,491.404,359,17.25,2.8, 2022-06-25T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N04K,35.58365554,-99.26716663,491.4049,0.5,17.9,2.8, 2022-09-28T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N04K,35.55705116,-99.21896392,475.6039,2.98,15.03,2.8, 2023-05-22T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N04K,35.55705137,-99.21896447,475.6046,4.04,15.25,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N05K,35.66009171,-99.30843614,479.2629,182.01,14.7,2.8, 2023-05-22T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N05K,35.66009144,-99.30843592,479.2605,181.97,14.6,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N06K,35.89871957,-98.96084083,561.1503,181.96,16.6,2.8, 2023-05-22T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N06K,35.89871981,-98.96084082,561.1718,181.38,16.77,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N07K,36.3846247,-98.11048841,368.6874,178.99,14.37,2.8, 2023-05-22T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N07K,36.38462472,-98.11048842,368.6754,178.31,14.75,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N08K,36.75490924,-97.25457974,272.6516,179.86,17.33,2.8, 2023-05-22T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N08K,36.75490924,-97.25457971,272.6406,180.05,17.02,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N09K,36.16779646,-97.16946788,267.8307,176.27,15.73,2.8, 2023-10-30T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N09K,36.16779635,-97.16946778,267.808,176.28,16.52,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N10K,35.84867942,-97.48050158,300.9426,177.03,15.43,2.8, 2023-05-22T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N10K,35.84867902,-97.48050146,300.9297,177.26,15.6,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N11K,34.91477491,-98.29206879,413.9211,180.46,15.4,2.8, 2023-10-30T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N11K,34.91477495,-98.29206859,413.9073,180.62,15.88,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N12K,34.42325114,-98.33622525,284.0768,180.85,16.93,2.8, 2023-10-30T00:00:00.0000,15,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N12K,34.42324978,-98.3362236,284.0825,197.97,17.75,2.8, 2025-05-09T00:00:00.0000,15,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N13K,34.4223163,-98.3366171,283.6485,359.18,13.67,2.8, 2023-10-30T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N13K,34.42231664,-98.33661711,283.6386,359.92,13.95,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N14K,34.1679857,-97.98778941,257.6385,183.04,13.66,2.8, 2023-10-30T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N14K,34.16798653,-97.98778911,257.6385,181.32,14.25,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N15K,34.16725235,-97.98811257,256.1933,357.78,15.66,2.8, 2023-10-30T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N15K,34.16725262,-97.98811288,256.1992,358.82,16.23,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N16K,34.43949176,-99.13844737,358.8068,178.85,14.7,2.8, 2023-10-30T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N16K,34.43949129,-99.1384468,358.8394,180.11,15.45,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N17K,34.99093509,-99.05292137,446.3246,176.47,15.57,2.8, 2023-10-30T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N17K,34.99093496,-99.05292078,446.3374,176.79,16.57,2.8, 2025-05-09T00:00:00.0000,31,-4.71E-10,-1.36E-10,0.00E+00, Triangular +N01A,63.8878745,-145.249248,382.4447,169.5,15.64,2.8, 2021-09-01T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N01A,63.88787474,-145.2492483,382.4485,168,17.4,2.8, 2022-10-13T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N01A,63.88787172,-145.2492467,382.3969,214.8,17.15,2.8, 2023-09-16T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N01A,63.88787303,-145.2492436,382.4179,216.27,17.03,2.8, 2024-09-11T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N02A,64.03277032,-145.1558211,344.3146,9.5,14.09,2.8, 2021-09-01T00:00:00.0000,11,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N02A,64.03244506,-145.1557959,344.3432,321.5,17.81,2.8, 2022-10-13T00:00:00.0000,11,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N02A,64.03244455,-145.1557957,344.35,320.38,17.58,2.8, 2023-09-16T00:00:00.0000,11,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N02A,64.02902868,-145.1568408,345.2605,330.61,16.77,2.4257, 2024-09-11T00:00:00.0000,11,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N02A,64.02902759,-145.1568476,344.7471,328.4,17.8,2.4257, 2025-08-01T00:00:00.0000,11,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N03A,63.89871843,-145.2910236,392.8584,330,18,2.4, 2024-01-08T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N03A,63.89871802,-145.2910235,393.2849,329.54,17.2,2.4257, 2024-09-11T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N03A,63.89871775,-145.2910228,392.8047,329,17.3,2.4257, 2025-08-01T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N04A,63.80003836,-145.8035903,724.4187,325.19,12.5,2.8, 2024-09-11T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N04A,63.8000382,-145.8035904,724.4216,325.19,12.7,2.8, 2025-08-01T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N05A,63.93601487,-145.3391505,383.7014,213.95,12.73,3, 2024-09-11T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N05A,63.93601335,-145.3391485,383.381,214.3,12.7,2.4257, 2025-08-01T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N31A,64.76151103,-148.1085197,181.4899,10.5,15.23,3, 2021-09-01T00:00:00.0000,15,-2.47E-10,-7.13E-10,2.99E-11, Triangular +N31A,64.7615108,-148.1085199,181.4909,10.5,15.23,3, 2022-10-13T00:00:00.0000,15,-2.47E-10,-7.13E-10,2.99E-11, Triangular +N31A,64.76150999,-148.1085176,181.3719,329.75,13.88,3, 2023-09-16T00:00:00.0000,15,-2.47E-10,-7.13E-10,2.99E-11, Triangular +N31A,64.76150983,-148.1085175,181.3387,329,17.4,3, 2024-09-11T00:00:00.0000,15,-2.47E-10,-7.13E-10,2.99E-11, Triangular +N31A,64.76150965,-148.1085177,181.3395,329,16.5,3, 2025-08-01T00:00:00.0000,15,-2.47E-10,-7.13E-10,2.99E-11, Triangular +N32A,63.9260891,-145.7462243,462.8973,168,14.24,3, 2021-09-01T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N32A,63.92607352,-145.7462326,462.8965,218,17.04,3, 2022-10-13T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N32A,63.92607377,-145.7461547,462.4229,214,17.57,3, 2023-09-16T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N32A,63.92607272,-145.7461565,462.4312,216.25,18.37,3, 2024-09-11T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +N32A,63.92607256,-145.7461566,462.4341,213.5,17.7,3, 2025-08-01T00:00:00.0000,15,-2.32E-10,-6.64E-10,1.06E-10, Triangular +S01A,64.86973817,-147.8638304,173.5171,12.85,21.92,0.8, 2024-09-11T00:00:00.0000,28,-2.47E-10,-7.13E-10,2.99E-11, Square +S01A,64.86973595,-147.8638297,173.4982,326,16.8,0.8, 2025-08-01T00:00:00.0000,28,-2.47E-10,-7.13E-10,2.99E-11, Square +S02A,64.86963046,-147.8635721,172.9735,165.23,18.58,0.8, 2024-09-11T00:00:00.0000,28,-2.47E-10,-7.13E-10,2.99E-11, Square +S02A,64.86962692,-147.8635738,172.948,210.5,17.5,0.8, 2025-08-01T00:00:00.0000,28,-2.47E-10,-7.13E-10,2.99E-11, Square +N00R,34.79696871,-118.0965295,660.7837,170,12.5,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N00R,34.79696904,-118.0965302,660.7917,171,11.5,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N00R,34.79696908,-118.0965304,660.7915,170.5,12.1,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N00R,34.7969692,-118.0965309,660.7911,170.5,12.1,2.4384, 2024-06-20T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N00R,34.79696923,-118.096531,660.791,170.5,12.87,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N01R,34.79977281,-118.0869948,660.9953,170,12.4,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N01R,34.79982502,-118.0869994,661.053,171,10.75,2.4384, 2021-06-22T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N01R,34.79982515,-118.0869997,661.0408,170.5,11.5,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N01R,34.79984845,-118.0869889,661.04,170.5,8.72,2.4384, 2024-06-20T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N01R,34.79984848,-118.086989,661.0399,170.5,9.37,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N02R,34.80523723,-118.0874599,660.7678,170,13.2,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N02R,34.80523725,-118.0873884,660.8021,169.5,9.2,2.4384, 2020-10-14T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N02R,34.80523731,-118.0873886,660.8019,170.5,8.5,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N02R,34.80523735,-118.0873888,660.8017,168.5,8.7,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N02R,34.8052374,-118.087389,660.8015,170,9.3,2.4384, 2023-06-01T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N02R,34.80523749,-118.0873894,660.8012,170,10.07,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N03R,34.80534213,-118.0819095,660.952,176,13,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N03R,34.8053381,-118.0819442,660.9979,170,7.3,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N03R,34.80533814,-118.0819444,660.9977,170,8.63,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N03R,34.80533823,-118.0820138,660.9951,171.9,15.67,2.4384, 2024-06-20T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N03R,34.80533826,-118.0820139,660.995,171.9,15.93,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N04R,34.80541511,-118.0763771,661.1612,176,12.03,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N04R,34.80541525,-118.0763777,661.1607,176,12.2,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N04R,34.80541528,-118.0763778,661.1605,176,11.93,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N04R,34.80541543,-118.0763785,661.16,176,12.1,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N05R,34.80549333,-118.0708022,661.2309,172,11.1,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N05R,34.80549347,-118.0708028,661.2304,170,10.8,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N05R,34.80549351,-118.070803,661.2302,171,11.07,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N05R,34.80549365,-118.0708036,661.2297,171,11.1,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N06R,34.80558439,-118.0652247,661.258,172,10.8,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N06R,34.80558452,-118.0652253,661.2575,172,10.5,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N06R,34.80558456,-118.0652254,661.2573,170,10.53,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N06R,34.80558471,-118.0652261,661.2568,170,10.55,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N06R,34.80558234,-118.0652815,661.3749,167.12,14.87,2.4384, 2025-06-18T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N07R,34.80566945,-118.0596656,661.3211,174,13.8,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N07R,34.80566959,-118.0596662,661.3206,174,13.2,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N07R,34.80566963,-118.0596664,661.3204,172,13.4,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N07R,34.80566733,-118.0596983,661.4065,170,14.7,2.4384, 2023-09-28T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N07R,34.8056674,-118.0596986,661.4062,170,15.93,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N08R,34.80575126,-118.0540727,661.4349,172.5,10.8,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N08R,34.8057514,-118.0540733,661.4344,172.5,10.1,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N08R,34.80575143,-118.0540734,661.4342,172,10.1,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N08R,34.80575768,-118.0540219,661.578,170.25,14.53,2.3989, 2022-11-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N08R,34.8057578,-118.0540225,661.5776,170.25,15.13,2.3989, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N09R,34.80581376,-118.0489144,661.4515,175,11.16,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N09R,34.80581389,-118.048915,661.451,175,10,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N09R,34.80581393,-118.0489151,661.4508,175,10.63,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N09R,34.80581407,-118.0489157,661.4503,175,10.87,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N10R,34.80592508,-118.0433661,661.5203,174,8.96,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N10R,34.80592522,-118.0433667,661.5198,174,9.6,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N10R,34.80592526,-118.0433669,661.5196,177,9.8,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N10R,34.80592439,-118.043414,661.5825,170,14.6,2.4384, 2023-09-28T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N10R,34.80592446,-118.0434143,661.5822,170,14.9,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N11R,34.80602381,-118.0376922,661.6012,170,9.82,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N11R,34.80602394,-118.0376928,661.6007,170,10.2,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N11R,34.80602398,-118.0376929,661.6005,170,10.7,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N11R,34.80602467,-118.0377364,661.7067,170,14.6,2.3989, 2022-11-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N11R,34.80602479,-118.0377369,661.7063,170,15.33,2.3989, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N12R,34.80607358,-118.0323011,661.9193,171,9.2,2.4384, 2019-07-25T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N12R,34.80607372,-118.0323017,661.9188,171,8.5,2.4384, 2021-11-10T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N12R,34.80607376,-118.0323019,661.9186,169.5,8.1,2.4384, 2022-06-29T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N12R,34.8060739,-118.0323025,661.9181,169.5,8.6,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N13R,34.80519236,-118.0844186,660.9427,350,9.78,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N13R,34.8051925,-118.0844192,660.9422,350,12,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N13R,34.80519254,-118.0844194,660.942,347,11.9,2.4384, 2022-06-29T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N13R,34.80519268,-118.08442,660.9415,347,12.97,2.4384, 2024-12-04T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N14R,34.80544018,-118.0789142,660.9532,350,9.05,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N14R,34.80544032,-118.0789148,660.9527,350,10,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N14R,34.80544036,-118.078915,660.9525,349,10.4,2.4384, 2022-06-29T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N14R,34.80544002,-118.0789224,661.1623,350,16,2.4384, 2023-07-28T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N14R,34.8054401,-118.0789227,661.162,350,15.87,2.4384, 2024-12-04T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N15R,34.80551853,-118.0733415,661.2342,350.75,7.35,2.4384, 2019-07-25T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N15R,34.80551867,-118.073342,661.2337,350.75,8.4,2.4384, 2021-11-10T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N15R,34.80551871,-118.0733422,661.2335,350,8.53,2.4384, 2022-06-29T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N15R,34.80552353,-118.0732803,661.356,350.5,14.2,2.3989, 2022-11-29T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N15R,34.80552365,-118.0732808,661.3556,350.5,14.93,2.3989, 2024-12-04T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N16R,34.80554827,-118.0678682,661.29,350.83,6.9,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N16R,34.80554841,-118.0678688,661.2895,349,7.6,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N16R,34.80554845,-118.067869,661.2893,350,8.03,2.4384, 2022-06-29T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N16R,34.80554859,-118.0678696,661.2888,350,8.83,2.4384, 2024-12-04T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N17R,34.80555327,-118.0626278,661.3277,346.5,11.2,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N17R,34.80555341,-118.0626284,661.3272,346.5,11.1,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N17R,34.80555344,-118.0626285,661.327,346,11,2.4384, 2022-06-29T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N17R,34.80555359,-118.0626292,661.3265,346,11.42,2.4384, 2024-12-04T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N18R,34.80568732,-118.0564273,661.449,350,9.13,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N18R,34.80568745,-118.0564279,661.4485,348,8.5,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N18R,34.80568761,-118.0564286,661.4479,346,8.97,2.4384, 2024-06-20T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N18R,34.80568764,-118.0564287,661.4478,346,9.3,2.4384, 2024-12-04T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N19R,34.80572223,-118.0518153,661.4154,351,11.56,2.4384, 2019-07-25T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N19R,34.80572237,-118.0518159,661.4149,350,11.1,2.4384, 2021-11-10T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N19R,34.8057224,-118.0518161,661.4147,350,11.3,2.4384, 2022-06-29T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N19R,34.80572711,-118.0517596,661.5723,351.25,13.8,2.3989, 2022-11-29T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N19R,34.80572723,-118.0517601,661.5719,351.25,14.57,2.3989, 2024-12-04T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N20R,34.80583767,-118.046357,661.4521,350,10.61,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N20R,34.80583781,-118.0463576,661.4516,349,11.4,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N20R,34.80583784,-118.0463578,661.4514,350,10.77,2.4384, 2022-06-29T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N20R,34.80583799,-118.0463584,661.4509,350,11.63,2.4384, 2024-12-04T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N21R,34.80590094,-118.0403331,661.4674,355,9.95,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N21R,34.80590108,-118.0403336,661.4669,355,11.2,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N21R,34.80590023,-118.0403331,661.4743,352,8.67,2.4384, 2022-06-29T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N21R,34.80590037,-118.0403337,661.4738,352,9.27,2.4384, 2024-12-04T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N22R,34.80603131,-118.035064,661.7181,354,10.59,2.4384, 2019-07-25T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N22R,34.80603145,-118.0350646,661.7176,354,11.3,2.4384, 2021-11-10T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N22R,34.80603148,-118.0350648,661.7174,350,10.97,2.4384, 2022-06-29T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N22R,34.80603154,-118.035065,661.7172,350,10.97,2.4384, 2023-06-01T00:00:00.0000,15,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N22R,34.80605048,-118.0351916,661.8069,9.8,16,2.4384, 2023-12-12T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N22R,34.80599618,-118.0351481,661.8154,10.82,16.23,2.4384, 2024-06-20T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N22R,34.80599621,-118.0351482,661.8153,10.82,16.13,2.4384, 2024-12-04T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N23R,34.8025042,-118.0858044,661.2062,351.06,21,4.8, 2019-07-25T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N24R,34.80290922,-118.0766457,661.4343,350.97,20.9,4.8, 2019-07-25T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N25R,34.80315633,-118.0687795,661.5192,349.69,21,4.8, 2019-07-25T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N26R,34.80322809,-118.0605815,661.6334,350.66,20.82,4.8, 2019-07-25T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +N27R,34.8035193,-118.0522795,661.6526,349.64,20.93,4.8, 2019-07-25T00:00:00.0000,31,-7.50E-10,2.09E-10,-6.84E-12, Triangular +S28R,34.79888368,-118.0948329,661.7742,9.9,15.05,0.8, 2023-12-12T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Square +S28R,34.79888382,-118.0948329,661.7268,11.63,14.8,0.8, 2024-06-20T00:00:00.0000,4,-7.50E-10,2.09E-10,-6.84E-12, Square +S34R,34.80349559,-118.0633953,662.2344,350.54,19.5,0.8, 2024-06-20T00:00:00.0000,28,-7.50E-10,2.09E-10,-6.84E-12, Square \ No newline at end of file diff --git a/tests/python/packages/nisar/cal/corner_reflector.py b/tests/python/packages/nisar/cal/corner_reflector.py index 79dc4adbb..b35896e9f 100644 --- a/tests/python/packages/nisar/cal/corner_reflector.py +++ b/tests/python/packages/nisar/cal/corner_reflector.py @@ -338,3 +338,16 @@ def test_parse_sample_nisar_csv(sample_nisar_csv: Path): # check that strings are parsed without issues due to spaces. npt.assert_(crs[0].id == "N01K") npt.assert_(crs[0].survey_date == isce3.core.DateTime("2021-06-04")) + + +@pytest.fixture +def sample_nisar_csv_with_shape() -> Path: + return Path(iscetest.data) / "abscal" / "NISAR_ANC_CORNER_REFLECTORS_006.csv" + + +def test_parse_sample_nisar_csv(sample_nisar_csv_with_shape: Path): + crs = list(nisar.cal.parse_corner_reflector_csv(sample_nisar_csv_with_shape)) + # The last one is a SWOT CR which is square. + npt.assert_(crs[-1].id == "S34R") + # should map "Square" -> "square" + npt.assert_(crs[-1].shape == "square") \ No newline at end of file From 28bb6f23ee46696419e55ca3fa3d505359ed9827 Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:28:47 -0800 Subject: [PATCH 08/10] Generalize abscal workflow to square trihedrals --- python/packages/nisar/workflows/estimate_abscal_factor.py | 8 ++++---- .../packages/nisar/workflows/estimate_abscal_factor.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/packages/nisar/workflows/estimate_abscal_factor.py b/python/packages/nisar/workflows/estimate_abscal_factor.py index 690827d5e..b9936df6e 100644 --- a/python/packages/nisar/workflows/estimate_abscal_factor.py +++ b/python/packages/nisar/workflows/estimate_abscal_factor.py @@ -25,7 +25,7 @@ def default(self, obj): CornerReflectorIterable = Union[ - Iterable[isce3.cal.TriangularTrihedralCornerReflector], + Iterable[isce3.cal.TrihedralCornerReflector], Iterable[nisar.cal.CornerReflector], ] @@ -68,7 +68,7 @@ def estimate_abscal_factor( ---------- corner_reflectors : iterable Iterable of corner reflectors in the scene. The elements may be instances of - `isce3.cal.TriangularTrihedralCornerReflector` or `nisar.cal.CornerReflector`. + `isce3.cal.TrihedralCornerReflector` or `nisar.cal.CornerReflector`. In the latter case, additional information about the survey date and plate motion velocity of each corner reflector is populated in the output. rslc : nisar.products.readers.SLC @@ -248,9 +248,9 @@ def estimate_abscal_factor( # Estimate the absolute calibration error (the ratio of the measured RCS to the # predicted RCS) for a single corner reflector. def estimate_abscal_error( - cr: isce3.cal.TriangularTrihedralCornerReflector, + cr: isce3.cal.TrihedralCornerReflector, ) -> float: - predicted_rcs = isce3.cal.predict_triangular_trihedral_cr_rcs( + predicted_rcs = isce3.cal.predict_trihedral_cr_rcs( cr=cr, orbit=orbit, doppler=native_doppler, diff --git a/tests/python/packages/nisar/workflows/estimate_abscal_factor.py b/tests/python/packages/nisar/workflows/estimate_abscal_factor.py index 6ce98a9be..9c22c4c48 100644 --- a/tests/python/packages/nisar/workflows/estimate_abscal_factor.py +++ b/tests/python/packages/nisar/workflows/estimate_abscal_factor.py @@ -71,7 +71,7 @@ def test_predict_triangular_trihedral_cr_rcs(bandwidth): for cr in d["corner_reflectors"]: # Compute predicted RCS. - predicted_rcs = isce3.cal.predict_triangular_trihedral_cr_rcs( + predicted_rcs = isce3.cal.predict_trihedral_cr_rcs( cr=cr, orbit=d["orbit"], doppler=d["native_doppler"], @@ -97,7 +97,7 @@ class TestMeasureTargetRCS: def test_measure_target_rcs(self, peak_find_domain: str): d = get_test_data() - def measure_rcs_db(cr: isce3.cal.TriangularTrihedralCornerReflector) -> float: + def measure_rcs_db(cr: isce3.cal.TrihedralCornerReflector) -> float: rcs = isce3.cal.measure_target_rcs( target_llh=cr.llh, img_data=d["img_data"], From 880266cc5290a17882ffbfa8f25d0f46415b2247 Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:31:41 -0800 Subject: [PATCH 09/10] Generalize PTA to square trihedrals --- python/packages/nisar/workflows/point_target_analysis.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/packages/nisar/workflows/point_target_analysis.py b/python/packages/nisar/workflows/point_target_analysis.py index f05539557..a7f78ecfe 100755 --- a/python/packages/nisar/workflows/point_target_analysis.py +++ b/python/packages/nisar/workflows/point_target_analysis.py @@ -21,7 +21,7 @@ from isce3.cal import ( parse_triangular_trihedral_cr_csv, point_target_info as pti, - TriangularTrihedralCornerReflector as CornerReflector, + TrihedralCornerReflector as CornerReflector, ) import nisar @@ -426,7 +426,7 @@ def slc_pt_performance( CornerReflectorIterable = Union[ - Iterable[isce3.cal.TriangularTrihedralCornerReflector], + Iterable[isce3.cal.TrihedralCornerReflector], Iterable[nisar.cal.CornerReflector], ] @@ -532,7 +532,7 @@ def analyze_corner_reflectors( ---------- corner_reflectors : iterable Iterable of corner reflectors in the scene. The elements may be instances of - `isce3.cal.TriangularTrihedralCornerReflector` or `nisar.cal.CornerReflector`. + `isce3.cal.TrihedralCornerReflector` or `nisar.cal.CornerReflector`. In the latter case, additional information about the survey date, validity, and plate motion velocity of each corner reflector is populated in the output. rslc : nisar.products.readers.RSLC @@ -844,7 +844,7 @@ def get_corner_reflectors_from_csv( Returns ------ - Iterator of isce3.cal.TriangularTrihedralCornerReflector + Iterator of isce3.cal.TrihedralCornerReflector An iterator over the set of corner reflectors. """ if format == "nisar": From e805a26c541a749ac7897a6becece5618df3b15c Mon Sep 17 00:00:00 2001 From: Brian Hawkins <1729052+bhawkins@users.noreply.github.com> Date: Mon, 3 Nov 2025 22:04:44 -0800 Subject: [PATCH 10/10] Update some comments --- python/packages/nisar/cal/corner_reflector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/packages/nisar/cal/corner_reflector.py b/python/packages/nisar/cal/corner_reflector.py index ae25f2df7..deb52e0af 100644 --- a/python/packages/nisar/cal/corner_reflector.py +++ b/python/packages/nisar/cal/corner_reflector.py @@ -322,7 +322,7 @@ def get_valid_crs( Validity flag(s) to check for. If None, only corner reflectors that are out of service (i.e. with validity code == 0) are filtered out. Otherwise, corner reflectors that do not have any of the specified validity flags set will be - filtered out. For example, using ``flags=CRValidity.LSAR_RAD_POL | CRValidity.GEOM`` + filtered out. For example, using ``flags=CRValidity.RAD_POL | CRValidity.GEOM`` would yield only those corner reflectors that were valid for either radiometric/polarimetric calibration or geometric calibration activities. Defaults to None. @@ -378,7 +378,7 @@ def parse_and_filter_corner_reflector_csv( Validity flag(s) to check for. If None, only corner reflectors that are out of service (i.e. with validity code == 0) are filtered out. Otherwise, corner reflectors that do not have any of the specified validity flags set will be - filtered out. For example, using ``flags=CRValidity.LSAR_RAD_POL | CRValidity.GEOM`` + filtered out. For example, using ``flags=CRValidity.RAD_POL | CRValidity.GEOM`` would yield only those corner reflectors that were valid for either radiometric/polarimetric calibration or geometric calibration activities. Defaults to None.