Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NOAA-21 support #118

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<!-- Please make the PR against the `master` branch. -->
<!-- Please make the PR against the `main` branch. -->

<!-- Describe what your PR does, and why -->

- [ ] Closes #xxxx <!-- remove if there is no corresponding issue, which should only be the case for minor changes -->
- [ ] Tests added <!-- for all bug fixes or enhancements -->
- [ ] Tests passed <!-- for all non-documentation changes) -->
- [ ] Passes ``flake8 pyorbital`` <!-- remove if you did not edit any Python files -->
- [ ] Fully documented <!-- remove if this change should not be visible to users, e.g., if it is an internal clean-up, or if this is part of a larger project that will be documented later -->
97 changes: 92 additions & 5 deletions pyorbital/tests/test_tlefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
#
# Copyright (c) 2014-2023 Pytroll Community
#
# Author(s):
#
# Martin Raspaud <[email protected]>
# Panu Lahtinen <[email protected]>
#
# 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
Expand All @@ -25,6 +21,7 @@


from pyorbital.tlefile import Tle
from pyorbital import tlefile
from pyorbital.tlefile import (_get_config_path,
read_platform_numbers,
_get_local_tle_path_from_env,
Expand All @@ -34,18 +31,65 @@

import logging
import datetime
import pytest
import unittest
from unittest.mock import patch
from unittest import mock
import pytest
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"

Expand Down Expand Up @@ -78,6 +122,48 @@
'</multi-mission-administrative-message>'))


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)
with pytest.raises(KeyError) as exc_info:
_ = tlefile.read('NOAA 21', str(fake_tlefile))

assert str(exc_info.value) == '"Found no TLE entry for \'NOAA 21\'"'


@pytest.fixture
def fake_platforms_file(tmp_path):
"""Return file path to a fake platforms.txt file."""
Expand Down Expand Up @@ -537,6 +623,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)
Expand Down
46 changes: 23 additions & 23 deletions pyorbital/tlefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
#
# Copyright (c) 2011-2023 Pytroll Community
#
# Author(s):
#
# Esben S. Nielsen <[email protected]>
# Martin Raspaud <[email protected]>
# Panu Lahtinen <[email protected]>
# Will Evonosky <[email protected]>
#
# 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
Expand All @@ -22,20 +16,19 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Classes and functions for handling TLE files."""

import io
import logging
import datetime as dt
from urllib.request import urlopen
import os
import glob
import numpy as np
import requests
import sqlite3
from xml.etree import ElementTree as ET
from itertools import zip_longest
from xml.etree import ElementTree as ET
import sqlite3
import requests
import numpy as np
import glob
import os
from urllib.request import urlopen
import datetime as dt
import logging
import io


TLE_URLS = ('https://celestrak.org/NORAD/elements/active.txt',
Expand Down Expand Up @@ -341,22 +334,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(get_platforms_filepath(), 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))
Expand Down Expand Up @@ -487,8 +485,10 @@ def collect_filenames(paths):


def read_tles_from_mmam_xml_files(paths):
"""Read TLEs from EUMETSAT MMAM XML files."""
# 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:
Expand All @@ -500,7 +500,7 @@ def read_tles_from_mmam_xml_files(paths):


def read_tle_from_mmam_xml_file(fname):
"""Read TLEs from a EUMETSAT MMAM XML file."""
"""Read TLE data from MMAM XMl file (EUMETSAT)."""
tree = ET.parse(fname)
root = tree.getroot()
data = []
Expand Down