tests/visualization/test_cphd_kmz_product_creation.py::test_create_kmz
/home/vscuser/git/glweb/software/third-party/sarpy/sarpy/visualization/kmz_utils.py:302: MatplotlibDeprecationWarning: The collections attribute was deprecated in Matplotlib 3.8 and will be removed in 3.10.
for path in contour_sets.collections[0].get_paths()
I found that due to our use of try...catch we had a testing gap that hid a bug that prevented some antenna beam footprints that should have been present from making it into KML.
What was the bug?
The code isn't currently handling the case where codes is None. We're currently following a pattern that matplotlib discourages:
Users of Path objects should not access the vertices and codes arrays directly. Instead, they should use iter_segments or cleaned to get the vertex/code pairs. This helps, in particular, to consistently handle the case of codes being None.
What is the fix?
Because we want to only consider closed polygons, using to_polygons seemed like a reasonable way to check for them:
If closed_only is False, any unclosed polygons in the path will be returned as unclosed polygons, and the closed polygons will be returned explicitly closed by setting the last point to the same as the first point.
This also avoids accessing members that shouldn't be accessed directly.
Description
In the course of addressing a semi-recent DeprecationWarning for our use of matplotlib contours in
make_beam_footprints
:I found that due to our use of
try...catch
we had a testing gap that hid a bug that prevented some antenna beam footprints that should have been present from making it into KML.What was the bug?
The code isn't currently handling the case where
codes
is None. We're currently following a pattern that matplotlib discourages:What is the fix?
Because we want to only consider closed polygons, using
to_polygons
seemed like a reasonable way to check for them:This also avoids accessing members that shouldn't be accessed directly.
New test
The new test currently fails without the bugfix:
results running new test in integration/1.3.59-rc in a python=3.6 environment
``` SARPY_TEST_PATH=/data/sarpy_test/ pytest tests/visualization/test_cphd_kmz_product_creation.py -sv ============================================================================================================================================================================== test session starts ============================================================================================================================================================================== platform linux -- Python 3.6.13, pytest-7.0.1, pluggy-1.0.0 -- /home/vscuser/miniconda3/envs/tmp/bin/python cachedir: .pytest_cache rootdir: /home/vscuser/git/glweb/software/third-party/sarpy collected 2 items tests/visualization/test_cphd_kmz_product_creation.py::test_create_kmz[True] FAILED tests/visualization/test_cphd_kmz_product_creation.py::test_create_kmz[False] PASSED =================================================================================================================================================================================== FAILURES ==================================================================================================================================================================================== _____________________________________________________________________________________________________________________________________________________________________________ test_create_kmz[True] _____________________________________________________________________________________________________________________________________________________________________________ cphd_file = '/data/sarpy_test/cphd/spotlight_example.cphd', tmp_path = PosixPath('/data/tmp/pytest-of-vscuser/pytest-288/test_create_kmz_True_0'), include_antenna = True @pytest.mark.parametrize("include_antenna", (True, False)) def test_create_kmz(cphd_file, tmp_path, include_antenna): reader = sarpy.io.phase_history.open(cphd_file) if not include_antenna: reader.cphd_meta.Antenna = None file_stem = f'has_antenna_is_{include_antenna}' cphd_kmz.cphd_create_kmz_view(reader, tmp_path, file_stem=file_stem) > _check_kmz(tmp_path, file_stem, expect_antenna=include_antenna) tests/visualization/test_cphd_kmz_product_creation.py:56: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ out_path = PosixPath('/data/tmp/pytest-of-vscuser/pytest-288/test_create_kmz_True_0'), file_stem = 'has_antenna_is_True', expect_antenna = True def _check_kmz(out_path, file_stem, expect_antenna): assert len(list(out_path.glob('**/*'))) == 1 produced_file = next(out_path.glob(file_stem + '*.kmz')) with zipfile.ZipFile(produced_file, 'r') as kmz: assert set(kmz.namelist()) == {'doc.kml'} with kmz.open('doc.kml') as kml_fd: tree = xml.etree.ElementTree.parse(kml_fd) ns = "{http://www.opengis.net/kml/2.2}" assert tree.getroot().tag == f'{ns}kml' for folder_name in ("Boresights", "-3dB Footprints"): folder = tree.find(f".//{ns}Folder/[{ns}name='Antenna']/{ns}Folder/[{ns}name='{folder_name}']") has_placemarks = len(folder.findall(f'.//{ns}Placemark')) > 0 > assert has_placemarks == expect_antenna E assert False == True E +False E -True tests/visualization/test_cphd_kmz_product_creation.py:46: AssertionError ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Captured log call ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- WARNING sarpy.visualization.kmz_utils:kmz_utils.py:326 Exception while calculating start beam footprint of transmit WARNING sarpy.visualization.kmz_utils:kmz_utils.py:328 argument of type 'NoneType' is not iterable WARNING sarpy.visualization.kmz_utils:kmz_utils.py:326 Exception while calculating middle beam footprint of transmit WARNING sarpy.visualization.kmz_utils:kmz_utils.py:328 argument of type 'NoneType' is not iterable WARNING sarpy.visualization.kmz_utils:kmz_utils.py:326 Exception while calculating end beam footprint of transmit WARNING sarpy.visualization.kmz_utils:kmz_utils.py:328 argument of type 'NoneType' is not iterable WARNING sarpy.visualization.kmz_utils:kmz_utils.py:326 Exception while calculating start beam footprint of receive WARNING sarpy.visualization.kmz_utils:kmz_utils.py:328 argument of type 'NoneType' is not iterable WARNING sarpy.visualization.kmz_utils:kmz_utils.py:326 Exception while calculating middle beam footprint of receive WARNING sarpy.visualization.kmz_utils:kmz_utils.py:328 argument of type 'NoneType' is not iterable WARNING sarpy.visualization.kmz_utils:kmz_utils.py:326 Exception while calculating end beam footprint of receive WARNING sarpy.visualization.kmz_utils:kmz_utils.py:328 argument of type 'NoneType' is not iterable ============================================================================================================================================================================ short test summary info ============================================================================================================================================================================ FAILED tests/visualization/test_cphd_kmz_product_creation.py::test_create_kmz[True] - assert False == True ========================================================================================================================================================================== 1 failed, 1 passed in 1.80s ========================================================================================================================================================================== ```Full test results in this branch
``` SARPY_TEST_PATH=/data/sarpy_test/ nox nox > Running session test(version='3.6') nox > Creating conda env in .nox/test-version-3-6 with python nox > conda install --yes --prefix /home/vscuser/git/glweb/software/third-party/sarpy/.nox/test-version-3-6 python=3.6 nox > python -m pip install '.[all]' nox > pytest tests ======================================================================================================================================================== test session starts ========================================================================================================================================================= platform linux -- Python 3.6.13, pytest-7.0.1, pluggy-1.0.0 rootdir: /home/vscuser/git/glweb/software/third-party/sarpy collected 562 items tests/test_class_string.py . [ 0%] tests/consistency/test_consistency.py ........ [ 1%] tests/consistency/test_cphd_consistency.py .............................................................. [ 12%] tests/consistency/test_sicd_consistency.py ... [ 13%] tests/consistency/test_sidd_consistency.py .... [ 13%] tests/geometry/test_geocoords.py .......... [ 15%] tests/geometry/test_geometry_elements.py .......... [ 17%] tests/geometry/test_latlon.py ... [ 17%] tests/geometry/test_point_projection.py .............. [ 20%] tests/io/test_kml.py . [ 20%] tests/io/DEM/test_dted.py . [ 20%] tests/io/DEM/test_geoid.py . [ 20%] tests/io/DEM/test_geotiff1deg_list.py .... [ 21%] tests/io/DEM/test_geotiff1deg_reader.py ........ [ 23%] tests/io/complex/test_other_nitf.py ... [ 23%] tests/io/complex/test_reader.py ..sss.ssss. [ 25%] tests/io/complex/test_remote.py s [ 25%] tests/io/complex/test_sicd.py . [ 25%] tests/io/complex/test_utils.py . [ 26%] tests/io/complex/sicd_elements/test_sicd_elements_antenna.py ... [ 26%] tests/io/complex/sicd_elements/test_sicd_elements_base.py ... [ 27%] tests/io/complex/sicd_elements/test_sicd_elements_blocks.py ..................... [ 30%] tests/io/complex/sicd_elements/test_sicd_elements_collectioninfo.py .. [ 31%] tests/io/complex/sicd_elements/test_sicd_elements_errorstatistics.py . [ 31%] tests/io/complex/sicd_elements/test_sicd_elements_geodata.py ... [ 32%] tests/io/complex/sicd_elements/test_sicd_elements_grid.py .. [ 32%] tests/io/complex/sicd_elements/test_sicd_elements_imagecreation.py . [ 32%] tests/io/complex/sicd_elements/test_sicd_elements_imagedata.py . [ 32%] tests/io/complex/sicd_elements/test_sicd_elements_imageformation.py ...... [ 33%] tests/io/complex/sicd_elements/test_sicd_elements_matchinfo.py . [ 33%] tests/io/complex/sicd_elements/test_sicd_elements_pfa.py . [ 34%] tests/io/complex/sicd_elements/test_sicd_elements_position.py ... [ 34%] tests/io/complex/sicd_elements/test_sicd_elements_radarcollection.py .............. [ 37%] tests/io/complex/sicd_elements/test_sicd_elements_radiometric.py . [ 37%] tests/io/complex/sicd_elements/test_sicd_elements_rgazcomp.py . [ 37%] tests/io/complex/sicd_elements/test_sicd_elements_rma.py ... [ 38%] tests/io/complex/sicd_elements/test_sicd_elements_scpcoa.py ................... [ 41%] tests/io/complex/sicd_elements/test_sicd_elements_sicd.py .................................. [ 47%] tests/io/complex/sicd_elements/test_sicd_elements_timeline.py .................. [ 50%] tests/io/complex/sicd_elements/test_sicd_elements_utils.py ... [ 51%] tests/io/general/test_base.py ... [ 51%] tests/io/general/test_data_segment.py .......... [ 53%] tests/io/general/test_format_function.py ........ [ 54%] tests/io/general/test_nitf.py .. [ 55%] tests/io/general/test_nitf_headers.py . [ 55%] tests/io/general/test_nitf_image.py .... [ 56%] tests/io/general/test_tre.py ... [ 56%] tests/io/phase_history/test_cphd.py ....... [ 58%] tests/io/phase_history/test_cphd_versions.py ..... [ 58%] tests/io/phase_history/cphd1_elements/test_cphd.py ...... [ 59%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_antenna.py ..... [ 60%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_blocks.py .... [ 61%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_channel.py . [ 61%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_data.py . [ 61%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_dwell.py . [ 62%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_geoinfo.py ... [ 62%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_global.py .. [ 62%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_pvp.py . [ 63%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_referencegeometry.py . [ 63%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_supportarray.py .. [ 63%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_txrcv.py . [ 63%] tests/io/phase_history/cphd1_elements/test_utils.py . [ 64%] tests/io/product/test_reader.py ...s [ 64%] tests/io/product/test_sidd.py ... [ 65%] tests/io/product/test_sidd_schema.py ......... [ 66%] tests/io/product/test_sidd_writing.py .. [ 67%] tests/io/product/sidd3_elements/test_exploitationfeatures.py .................................................................................................................................. [ 90%] tests/io/product/sidd3_elements/test_sidd3_elements.py ..... [ 91%] tests/io/received/test_crsd.py . [ 91%] tests/processing/sicd/test_spectral_taper.py ........ss........... [ 95%] tests/utils/test_sicd_sidelobe_control.py .. [ 95%] tests/visualization/test_cphd_kmz_product_creation.py .. [ 95%] tests/visualization/test_crsd_kmz_product_creation.py . [ 96%] tests/visualization/test_kmz_product_creation.py .x [ 96%] tests/visualization/test_remap.py .................... [100%] ========================================================================================================================================================== warnings summary ========================================================================================================================================================== tests/geometry/test_point_projection.py::test_image_to_ground_errors tests/geometry/test_point_projection.py::test_image_to_ground_dem /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/geometry/point_projection.py:1882: RuntimeWarning: divide by zero encountered in double_scalars lon_grid_size = min(10, lat_grid_size/abs(numpy.sin(numpy.deg2rad(ref_llh[0])))) tests/visualization/test_kmz_product_creation.py::test_create_kmz[True] /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/visualization/kmz_utils.py:169: RuntimeWarning: invalid value encountered in double_scalars + dir_z**2 * semiaxis_a**2 * semiaxis_b**2 -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ================================================================================================================================= 550 passed, 11 skipped, 1 xfailed, 3 warnings in 62.51s (0:01:02) ================================================================================================================================== nox > Session test(version='3.6') was successful. nox > Running session test(version='3.11') nox > Creating conda env in .nox/test-version-3-11 with python nox > conda install --yes --prefix /home/vscuser/git/glweb/software/third-party/sarpy/.nox/test-version-3-11 python=3.11 nox > python -m pip install '.[all]' nox > pytest tests ======================================================================================================================================================== test session starts ========================================================================================================================================================= platform linux -- Python 3.11.9, pytest-8.3.2, pluggy-1.5.0 rootdir: /home/vscuser/git/glweb/software/third-party/sarpy collected 562 items tests/consistency/test_consistency.py ........ [ 1%] tests/consistency/test_cphd_consistency.py .............................................................. [ 12%] tests/consistency/test_sicd_consistency.py ... [ 12%] tests/consistency/test_sidd_consistency.py .... [ 13%] tests/geometry/test_geocoords.py .......... [ 15%] tests/geometry/test_geometry_elements.py .......... [ 17%] tests/geometry/test_latlon.py ... [ 17%] tests/geometry/test_point_projection.py .............. [ 20%] tests/io/DEM/test_dted.py . [ 20%] tests/io/DEM/test_geoid.py . [ 20%] tests/io/DEM/test_geotiff1deg_list.py .... [ 21%] tests/io/DEM/test_geotiff1deg_reader.py ........ [ 22%] tests/io/complex/sicd_elements/test_sicd_elements_antenna.py ... [ 23%] tests/io/complex/sicd_elements/test_sicd_elements_base.py ... [ 23%] tests/io/complex/sicd_elements/test_sicd_elements_blocks.py ..................... [ 27%] tests/io/complex/sicd_elements/test_sicd_elements_collectioninfo.py .. [ 27%] tests/io/complex/sicd_elements/test_sicd_elements_errorstatistics.py . [ 28%] tests/io/complex/sicd_elements/test_sicd_elements_geodata.py ... [ 28%] tests/io/complex/sicd_elements/test_sicd_elements_grid.py .. [ 29%] tests/io/complex/sicd_elements/test_sicd_elements_imagecreation.py . [ 29%] tests/io/complex/sicd_elements/test_sicd_elements_imagedata.py . [ 29%] tests/io/complex/sicd_elements/test_sicd_elements_imageformation.py ...... [ 30%] tests/io/complex/sicd_elements/test_sicd_elements_matchinfo.py . [ 30%] tests/io/complex/sicd_elements/test_sicd_elements_pfa.py . [ 30%] tests/io/complex/sicd_elements/test_sicd_elements_position.py ... [ 31%] tests/io/complex/sicd_elements/test_sicd_elements_radarcollection.py .............. [ 33%] tests/io/complex/sicd_elements/test_sicd_elements_radiometric.py . [ 33%] tests/io/complex/sicd_elements/test_sicd_elements_rgazcomp.py . [ 34%] tests/io/complex/sicd_elements/test_sicd_elements_rma.py ... [ 34%] tests/io/complex/sicd_elements/test_sicd_elements_scpcoa.py ................... [ 38%] tests/io/complex/sicd_elements/test_sicd_elements_sicd.py .................................. [ 44%] tests/io/complex/sicd_elements/test_sicd_elements_timeline.py .................. [ 47%] tests/io/complex/sicd_elements/test_sicd_elements_utils.py ... [ 47%] tests/io/complex/test_other_nitf.py ... [ 48%] tests/io/complex/test_reader.py ..sss.ssss. [ 50%] tests/io/complex/test_remote.py s [ 50%] tests/io/complex/test_sicd.py . [ 50%] tests/io/complex/test_utils.py . [ 50%] tests/io/general/test_base.py ... [ 51%] tests/io/general/test_data_segment.py .......... [ 53%] tests/io/general/test_format_function.py ........ [ 54%] tests/io/general/test_nitf.py .. [ 54%] tests/io/general/test_nitf_headers.py . [ 55%] tests/io/general/test_nitf_image.py .... [ 55%] tests/io/general/test_tre.py ... [ 56%] tests/io/phase_history/cphd1_elements/test_cphd.py ...... [ 57%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_antenna.py ..... [ 58%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_blocks.py .... [ 59%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_channel.py . [ 59%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_data.py . [ 59%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_dwell.py . [ 59%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_geoinfo.py ... [ 60%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_global.py .. [ 60%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_pvp.py . [ 60%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_referencegeometry.py . [ 60%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_supportarray.py .. [ 61%] tests/io/phase_history/cphd1_elements/test_cphd1_elements_txrcv.py . [ 61%] tests/io/phase_history/cphd1_elements/test_utils.py . [ 61%] tests/io/phase_history/test_cphd.py ....... [ 62%] tests/io/phase_history/test_cphd_versions.py ..... [ 63%] tests/io/product/sidd3_elements/test_exploitationfeatures.py .................................................................................................................................. [ 86%] tests/io/product/sidd3_elements/test_sidd3_elements.py ..... [ 87%] tests/io/product/test_reader.py ...s [ 88%] tests/io/product/test_sidd.py ... [ 88%] tests/io/product/test_sidd_schema.py ......... [ 90%] tests/io/product/test_sidd_writing.py .. [ 90%] tests/io/received/test_crsd.py . [ 91%] tests/io/test_kml.py . [ 91%] tests/processing/sicd/test_spectral_taper.py ..................... [ 95%] tests/test_class_string.py . [ 95%] tests/utils/test_sicd_sidelobe_control.py .. [ 95%] tests/visualization/test_cphd_kmz_product_creation.py .. [ 95%] tests/visualization/test_crsd_kmz_product_creation.py . [ 96%] tests/visualization/test_kmz_product_creation.py .x [ 96%] tests/visualization/test_remap.py .................... [100%] ========================================================================================================================================================== warnings summary ========================================================================================================================================================== tests/geometry/test_geometry_elements.py: 77 warnings /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/geometry/geometry_elements.py:131: DeprecationWarning: Arrays of 2-dimensional vectors are deprecated. Use arrays of 3-dimensional vectors instead. (deprecated in NumPy 2.0) dir_cross = float(numpy.cross(R, S)) # the scalar cross product of the direction vectors tests/geometry/test_geometry_elements.py: 43 warnings /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/geometry/geometry_elements.py:137: DeprecationWarning: Arrays of 2-dimensional vectors are deprecated. Use arrays of 3-dimensional vectors instead. (deprecated in NumPy 2.0) end_cross_0 = float(numpy.cross(Q-P, S)) tests/geometry/test_geometry_elements.py: 43 warnings /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/geometry/geometry_elements.py:138: DeprecationWarning: Arrays of 2-dimensional vectors are deprecated. Use arrays of 3-dimensional vectors instead. (deprecated in NumPy 2.0) end_cross_1 = float(numpy.cross(Q-P, R)) tests/geometry/test_point_projection.py::test_image_to_ground_errors tests/geometry/test_point_projection.py::test_image_to_ground_dem /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/geometry/point_projection.py:1882: RuntimeWarning: divide by zero encountered in scalar divide lon_grid_size = min(10, lat_grid_size/abs(numpy.sin(numpy.deg2rad(ref_llh[0])))) tests/test_class_string.py::TestClassString::test_class_str /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/annotation/afrl_rde_schema/__init__.py:7: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html import pkg_resources tests/visualization/test_kmz_product_creation.py::test_create_kmz[True] /home/vscuser/git/glweb/software/third-party/sarpy/sarpy/visualization/kmz_utils.py:145: RuntimeWarning: invalid value encountered in scalar divide distance = ( -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ====================================================================================================================================== 552 passed, 9 skipped, 1 xfailed, 167 warnings in 30.01s ====================================================================================================================================== nox > Session test(version='3.11') was successful. nox > Ran multiple sessions: nox > * test(version='3.6'): success nox > * test(version='3.11'): success ```Note: This PR also addresses the deprecation warning.