From bfe39f66681e2f918021b3beb4e6937b38edd52e Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Wed, 15 Feb 2023 10:49:44 +0100 Subject: [PATCH 1/3] Add NOAA-21 to the list of designators/ids in the built in platforms.txt file Signed-off-by: Adam.Dybbroe --- pyorbital/etc/platforms.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/pyorbital/etc/platforms.txt b/pyorbital/etc/platforms.txt index cf84fce..e63f72a 100644 --- a/pyorbital/etc/platforms.txt +++ b/pyorbital/etc/platforms.txt @@ -65,6 +65,7 @@ NOAA-17 27453 NOAA-18 28654 NOAA-19 33591 NOAA-20 43013 +NOAA-21 54234 RadarSat-2 32382 Sentinel-1A 39634 Sentinel-3A 41335 From 902e2908e60e1fa4602707b2ccef0ecdea444786 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Wed, 15 Feb 2023 10:55:21 +0100 Subject: [PATCH 2/3] Fix PR template to reflect actual main branch and the fact that we use automated bots for checking code quality and tests Signed-off-by: Adam.Dybbroe --- .github/PULL_REQUEST_TEMPLATE.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a8db991..a1aae28 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,9 +1,7 @@ - + - [ ] Closes #xxxx - [ ] Tests added - - [ ] Tests passed - - [ ] Passes ``flake8 pyorbital`` - [ ] Fully documented From 6f42f15fcc32761c9fd86f5f29525a278118d849 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Wed, 15 Feb 2023 20:00:25 +0100 Subject: [PATCH 3/3] Add test cases and add draft solution (commented out atm) for discussion Signed-off-by: Adam.Dybbroe --- pyorbital/tests/test_tlefile.py | 99 +++++++++++++++++++++++++++++++-- pyorbital/tlefile.py | 29 +++++----- 2 files changed, 110 insertions(+), 18 deletions(-) diff --git a/pyorbital/tests/test_tlefile.py b/pyorbital/tests/test_tlefile.py index 7765b1b..50f8f65 100644 --- a/pyorbital/tests/test_tlefile.py +++ b/pyorbital/tests/test_tlefile.py @@ -1,12 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# Copyright (c) 2014 Martin Raspaud +# Copyright (c) 2014-2023 Pyorbital developers # -# Author(s): -# -# Martin Raspaud -# Panu Lahtinen # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,17 +21,67 @@ from pyorbital.tlefile import Tle +from pyorbital import tlefile + import datetime +import pytest import unittest from unittest import mock import os from contextlib import suppress import time +from pathlib import Path + line0 = "ISS (ZARYA)" line1 = "1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927" line2 = "2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537" + +def _write_fake_platforms_txt_file(platforms_filename) -> None: + with open(platforms_filename, 'w') as platforms_file: + platforms_file.write("""NOAA-18 28654 +NOAA-19 33591 +NOAA-20 43013 +NOAA-21 54234 +# ISS 25544 +""") + + +# NOAA 18 +# 1 28654U 05018A 23045.48509621 .00000446 00000+0 26330-3 0 9998 +# 2 28654 98.9223 120.4228 0014233 11.3574 348.7916 14.12862494914152 + +def _write_fake_tle_file(tlefilename: Path) -> None: + with open(tlefilename, "w") as tle_file: + tle_file.write("""NOAA 20 +1 43013U 17073A 23045.54907786 .00000253 00000+0 14081-3 0 9995 +2 43013 98.7419 345.5839 0001610 80.3742 279.7616 14.19558274271576 +NOAA 21 (JPSS-2) +1 54234U 22150A 23045.56664999 .00000332 00000+0 17829-3 0 9993 +2 54234 98.7059 345.5113 0001226 81.6523 278.4792 14.19543871 13653 +ISS (ZARYA) +1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927 +2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537 +""") + + +@pytest.fixture +def fake_platforms_txt_file(tmp_path: Path) -> Path: + """Make fake platforms.txt file.""" + filename = tmp_path / 'platforms.txt' + _write_fake_platforms_txt_file(filename) + yield filename + + +@pytest.fixture +def fake_tlefile(tmp_path: Path) -> Path: + """Make fake tle file.""" + filename = tmp_path / 'sometlefile.txt' + _write_fake_tle_file(filename) + yield filename + + line1_2 = "1 38771U 12049A 21137.30264622 .00000000 00000+0 -49996-5 0 00017" line2_2 = "2 38771 98.7162 197.7716 0002383 106.1049 122.6344 14.21477797449453" @@ -67,6 +113,48 @@ '')) +def test_read_tlefile_standard_platform_name(monkeypatch, fake_platforms_txt_file, fake_tlefile): + """Test create a tle-object by reading tle data from file. + + Use Oscar naming matching name in platforms.txt. + """ + path_to_platforms_txt_file = fake_platforms_txt_file.parent + monkeypatch.setenv('PPP_CONFIG_DIR', str(path_to_platforms_txt_file)) + + tle_n21 = tlefile.read('NOAA-21', str(fake_tlefile)) + assert tle_n21.line1 == '1 54234U 22150A 23045.56664999 .00000332 00000+0 17829-3 0 9993' + assert tle_n21.line2 == '2 54234 98.7059 345.5113 0001226 81.6523 278.4792 14.19543871 13653' + + +def test_read_tlefile_non_standard_platform_name(monkeypatch, fake_platforms_txt_file, fake_tlefile): + """Test create a tle-object by reading tle data from file. + + Use naming matching what is in the TLE files, but non-standard (non Oscar) naming. + """ + path_to_platforms_txt_file = fake_platforms_txt_file.parent + monkeypatch.setenv('PPP_CONFIG_DIR', path_to_platforms_txt_file) + + tle_n20 = tlefile.read('NOAA 20', str(fake_tlefile)) + + assert tle_n20.line1 == '1 43013U 17073A 23045.54907786 .00000253 00000+0 14081-3 0 9995' + assert tle_n20.line2 == '2 43013 98.7419 345.5839 0001610 80.3742 279.7616 14.19558274271576' + + +def test_read_tlefile_non_standard_platform_name_matching_start_of_name_in_tlefile(monkeypatch, + fake_platforms_txt_file, + fake_tlefile): + """Test create a tle-object by reading tle data from file. + + Use non-standard naming matching only the beginning of what is in the TLE files. + """ + path_to_platforms_txt_file = fake_platforms_txt_file.parent + monkeypatch.setenv('PPP_CONFIG_DIR', path_to_platforms_txt_file) + tle_n21 = tlefile.read('NOAA 21', str(fake_tlefile)) + + assert tle_n21.line1 == '1 54234U 22150A 23045.56664999 .00000332 00000+0 17829-3 0 9993' + assert tle_n21.line2 == '2 54234 98.7059 345.5113 0001226 81.6523 278.4792 14.19543871 13653' + + class TLETest(unittest.TestCase): """Test TLE reading. @@ -323,6 +411,7 @@ def test_read_tle_files(self): fname = os.path.join(save_dir.name, 'tle_20200129_1600.txt') with open(fname, 'w') as fid: fid.write(tle_text) + # Add a non-existent file, it shouldn't cause a crash nonexistent = os.path.join(save_dir.name, 'not_here.txt') # Use a wildcard to collect files (passed to glob) diff --git a/pyorbital/tlefile.py b/pyorbital/tlefile.py index 6a57398..40ad480 100644 --- a/pyorbital/tlefile.py +++ b/pyorbital/tlefile.py @@ -1,14 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# Copyright (c) 2011 - 2018 +# Copyright (c) 2011-2023 Pytroll developers # -# Author(s): -# -# Esben S. Nielsen -# Martin Raspaud -# Panu Lahtinen -# Will Evonosky # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -89,7 +83,7 @@ def read_platform_numbers(in_upper=False, num_as_int=False): SATELLITES = read_platform_numbers(in_upper=True, num_as_int=False) """ -The platform numbers are given in a file $PPP_CONFIG/platforms.txt +The platform numbers are given in a file $PPP_CONFIG_DIR/platforms.txt in the following format: .. literalinclude:: ../../etc/platforms.txt @@ -286,22 +280,27 @@ def _get_first_tle(uris, open_func, platform=''): def _get_tles_from_uris(uris, open_func, platform='', only_first=True): tles = [] - designator = "1 " + SATELLITES.get(platform, '') + _satellites = read_platform_numbers(in_upper=True, num_as_int=False) + + designator = "1 " + _satellites.get(platform, '') for url in uris: fid = open_func(url) for l_0 in fid: tle = "" l_0 = _decode(l_0) + # This will make the all the tests pass, but not prety! + # So, should the new test case that fails added in a draft PR, Feb 15, 2023, be removed? + # if l_0.strip() == platform or l_0.startswith(platform) and 'NOAA' in platform: if l_0.strip() == platform: l_1 = _decode(next(fid)) l_2 = _decode(next(fid)) tle = l_1.strip() + "\n" + l_2.strip() - elif (platform in SATELLITES or not only_first) and l_0.strip().startswith(designator): + elif (platform in _satellites or not only_first) and l_0.strip().startswith(designator): l_1 = l_0 l_2 = _decode(next(fid)) tle = l_1.strip() + "\n" + l_2.strip() if platform: - LOGGER.debug("Found platform %s, ID: %s", platform, SATELLITES[platform]) + LOGGER.debug("Found platform %s, ID: %s", platform, _satellites[platform]) elif open_func == _dummy_open_stringio and l_0.startswith(designator): l_1 = l_0 l_2 = _decode(next(fid)) @@ -432,7 +431,10 @@ def collect_filenames(paths): def read_tles_from_mmam_xml_files(paths): - # Collect filenames + """Read TLE data from a list of MMAM XMl file (EUMETSAT). + + MMAM = Multi-Mission Administration Message + """ fnames = collect_filenames(paths) tles = [] for fname in fnames: @@ -444,6 +446,7 @@ def read_tles_from_mmam_xml_files(paths): def read_tle_from_mmam_xml_file(fname): + """Read TLE data from MMAM XMl file (EUMETSAT).""" tree = ET.parse(fname) root = tree.getroot() data = [] @@ -455,7 +458,7 @@ def read_tle_from_mmam_xml_file(fname): def _group_iterable_to_chunks(n, iterable, fillvalue=None): - "Collect data into fixed-length chunks or blocks" + """Collect data into fixed-length chunks or blocks.""" # _group_iterable_to_chunks(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" args = [iter(iterable)] * n return zip_longest(fillvalue=fillvalue, *args)