Skip to content
Commits on Source (5)
......@@ -5,6 +5,5 @@
- [ ] 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 ``git diff origin/master **/*py | flake8 --diff`` <!-- remove if you did not edit any Python files -->
- [ ] 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 -->
1
\ No newline at end of file
linters:
flake8:
max-line-length: 120
fixer: true
fixers:
enable: true
language: python
python:
- '2.7'
- "3.6"
- '3.6'
install:
- pip install dask[array] xarray
- pip install .
......@@ -15,4 +15,4 @@ deploy:
secure: P3WiHVzDAJyZmiIfSF3PhY7Xqp3P3pSHhogla8u3KOw4Sy5Ye6IWwMX1+pupAyhdXgo8ZgGT4+wOn9dBejaLEA0RGIRLMHXd1QxP9BbPD5te/k5aTpzHILx786g5R6G4yw/8s/sftQC6lJT+0jJd2OJjQJsnNUJJTG8OC2uwq3Y=
on:
tags: true
repo: mraspaud/pyorbital
repo: pytroll/pyorbital
## Version 1.5.0 (2018/11/16)
### Pull Requests Merged
#### Features added
* [PR 40](https://github.com/pytroll/pyorbital/pull/40) - Add platforms.txt to package data
In this release 1 pull request was closed.
## Version 1.4.0 (2018/10/23)
### Issues Closed
......
# Releasing Pyorbital
prerequisites: `pip install setuptools twine`
1. checkout master
2. pull from repo
3. run the unittests
......@@ -16,12 +14,10 @@ Don't forget to commit!
5. Create a tag with the new version number, starting with a 'v', eg:
```
git tag v0.22.45
git tag v0.22.45 -m "Version 0.22.45"
```
See [semver.org](http://semver.org/) on how to write a version number.
6. push changes to github `git push --follow-tags`
7. Verify travis tests passed and deployed sdist and wheel to PyPI
pyorbital (1.5.0-1) UNRELEASED; urgency=medium
* New upstream release.
* debian/patches
- drop 0001-install-test-sub-package.patch: no longer necessary.
- refresh and renumber remaining patches.
-- Antonio Valentino <antonio.valentino@tiscali.it> Tue, 20 Nov 2018 06:26:21 +0000
pyorbital (1.4.0-1) unstable; urgency=medium
[ Bas Couwenberg ]
......
From: Antonio Valentino <antonio.valentino@tiscali.it>
Date: Sun, 22 Jun 2014 11:03:14 +0000
Subject: install test sub-package
---
setup.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index a5410ef..7575249 100644
--- a/setup.py
+++ b/setup.py
@@ -41,7 +41,8 @@ setup(name='pyorbital',
url="https://github.com/pytroll/pyorbital",
test_suite='pyorbital.tests.suite',
package_dir={'pyorbital': 'pyorbital'},
- packages=['pyorbital'],
+ packages=['pyorbital', 'pyorbital.tests'],
+ package_data={'pyorbital.tests': ['aiaa_results', '*.TLE']},
install_requires=['numpy>=1.11.0,!=1.14.0', 'scipy'],
zip_safe=False,
)
0001-install-test-sub-package.patch
0002-Skip-tests-using-on-xarray-or-dask-if-they-are-not-a.patch
0001-Skip-tests-using-on-xarray-or-dask-if-they-are-not-a.patch
......@@ -30,23 +30,20 @@
# - test !!!
from __future__ import print_function
import numpy as np
from numpy import cos, sin, sqrt
# DIRTY STUFF. Needed the get_lonlatalt function to work on pos directly if
# we want to print out lonlats in the end.
from pyorbital import astronomy
from pyorbital.orbital import *
from pyorbital.orbital import XKMPER, F
from pyorbital.orbital import Orbital
a = 6378.137 # km
b = 6356.75231414 # km, GRS80
# b = 6356.752314245 # km, WGS84
A = 6378.137 # WGS84 Equatorial radius (km)
B = 6356.75231414 # km, GRS80
# B = 6356.752314245 # km, WGS84
def geodetic_lat(point, a=a, b=b):
def geodetic_lat(point, a=A, b=B):
x, y, z = point
r = np.sqrt(x * x + y * y)
geoc_lat = np.arctan2(z, r)
......@@ -55,31 +52,28 @@ def geodetic_lat(point, a=a, b=b):
e2 = (a * a - b * b) / (a * a)
while True:
phi = geod_lat
C = 1 / sqrt(1 - e2 * sin(phi)**2)
geod_lat = np.arctan2(z + a * C * e2 * sin(phi), r)
C = 1 / np.sqrt(1 - e2 * np.sin(phi)**2)
geod_lat = np.arctan2(z + a * C * e2 * np.sin(phi), r)
if np.allclose(geod_lat, phi):
return geod_lat
def subpoint(query_point, a=a, b=b):
"""Get the point on the ellipsoid under the *query_point*.
"""
def subpoint(query_point, a=A, b=B):
"""Get the point on the ellipsoid under the *query_point*."""
x, y, z = query_point
r = sqrt(x * x + y * y)
lat = geodetic_lat(query_point)
lon = np.arctan2(y, x)
e2_ = (a * a - b * b) / (a * a)
n__ = a / sqrt(1 - e2_ * sin(lat)**2)
nx_ = n__ * cos(lat) * cos(lon)
ny_ = n__ * cos(lat) * sin(lon)
nz_ = (1 - e2_) * n__ * sin(lat)
n__ = a / np.sqrt(1 - e2_ * np.sin(lat)**2)
nx_ = n__ * np.cos(lat) * np.cos(lon)
ny_ = n__ * np.cos(lat) * np.sin(lon)
nz_ = (1 - e2_) * n__ * np.sin(lat)
return np.stack([nx_, ny_, nz_], axis=0)
class ScanGeometry(object):
"""Description of the geometry of an instrument.
*fovs* is the x and y viewing angles of the instrument. y is zero if the we
......@@ -88,10 +82,7 @@ class ScanGeometry(object):
size as the *fovs*. *attitude* is the attitude correction to apply.
"""
def __init__(self,
fovs,
times,
attitude=(0, 0, 0)):
def __init__(self, fovs, times, attitude=(0, 0, 0)):
self.fovs = np.array(fovs)
self._times = np.array(times) * np.timedelta64(1000000000, 'ns')
self.attitude = attitude
......@@ -129,7 +120,7 @@ class ScanGeometry(object):
def times(self, start_of_scan):
# tds = [timedelta(seconds=i) for i in self._times]
tds = self._times.astype('timedelta64[us]')
# tds = self._times.astype('timedelta64[us]')
try:
return np.array(self._times) + np.datetime64(start_of_scan)
except ValueError:
......@@ -168,14 +159,14 @@ def qrotate(vector, axis, angle):
This function uses quaternion rotation.
"""
n_axis = axis / vnorm(axis)
sin_angle = np.expand_dims(sin(angle / 2), 0)
sin_angle = np.expand_dims(np.sin(angle / 2), 0)
if np.ndim(n_axis) == 1:
n_axis = np.expand_dims(n_axis, 1)
p__ = np.dot(n_axis, sin_angle)[:, np.newaxis]
else:
p__ = n_axis * sin_angle
q__ = Quaternion(cos(angle / 2), p__)
q__ = Quaternion(np.cos(angle / 2), p__)
shape = vector.shape
return np.einsum("kj, ikj->ij",
vector.reshape((3, -1)),
......@@ -183,15 +174,13 @@ def qrotate(vector, axis, angle):
def get_lonlatalt(pos, utc_time):
"""Calculate sublon, sublat and altitude of satellite, considering the
earth an ellipsoid.
"""Calculate sublon, sublat and altitude of satellite, considering the earth an ellipsoid.
http://celestrak.com/columns/v02n03/
"""
(pos_x, pos_y, pos_z) = pos / XKMPER
lon = ((np.arctan2(pos_y * XKMPER, pos_x * XKMPER) - astronomy.gmst(utc_time))
% (2 * np.pi))
lon = ((np.arctan2(pos_y * XKMPER, pos_x * XKMPER) - astronomy.gmst(utc_time)) % (2 * np.pi))
lon = np.where(lon > np.pi, lon - np.pi * 2, lon)
lon = np.where(lon <= -np.pi, lon + np.pi * 2, lon)
......@@ -213,8 +202,7 @@ def get_lonlatalt(pos, utc_time):
def compute_pixels(orb, sgeom, times, rpy=(0.0, 0.0, 0.0)):
"""Compute cartesian coordinates of the pixels in instrument scan.
"""
"""Compute cartesian coordinates of the pixels in instrument scan."""
if isinstance(orb, (list, tuple)):
tle1, tle2 = orb
orb = Orbital("mysatellite", line1=tle1, line2=tle2)
......@@ -255,24 +243,22 @@ def norm(v):
def mnorm(m, axis=None):
"""norm of a matrix of vectors stacked along the *axis* dimension.
"""
"""norm of a matrix of vectors stacked along the *axis* dimension."""
if axis is None:
axis = np.ndim(m) - 1
return np.sqrt((m**2).sum(axis))
def vnorm(m):
"""norms of a matrix of column vectors.
"""
"""norms of a matrix of column vectors."""
return np.sqrt((m**2).sum(0))
def hnorm(m):
"""norms of a matrix of row vectors.
"""
"""norms of a matrix of row vectors."""
return np.sqrt((m**2).sum(1))
if __name__ == '__main__':
# NOAA 18 (from the 2011-10-12, 16:55 utc)
# 1 28654U 05018A 11284.35271227 .00000478 00000-0 28778-3 0 9246
......
......@@ -26,6 +26,8 @@
import numpy as np
from datetime import datetime
from pyorbital.geoloc import ScanGeometry, compute_pixels, get_lonlatalt
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
tle1 = "1 33591U 09005A 12345.45213434 .00000391 00000-0 24004-3 0 6113"
tle2 = "2 33591 098.8821 283.2036 0013384 242.4835 117.4960 14.11432063197875"
......@@ -61,19 +63,18 @@ pos_time = get_lonlatalt(pixels_pos, s_times)
print(pos_time)
# Plot the result
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='stere', llcrnrlat=24, urcrnrlat=70, llcrnrlon=-25, urcrnrlon=120, lat_ts=58, lat_0=58, lon_0=14, resolution='l')
m = Basemap(projection='stere', llcrnrlat=24, urcrnrlat=70, llcrnrlon=-25, urcrnrlon=120,
lat_ts=58, lat_0=58, lon_0=14, resolution='l')
# convert and plot the predicted pixels in red
x, y = m(pos_time[0], pos_time[1])
p1 = m.plot(x,y, marker='+', color='red', markerfacecolor='red', markeredgecolor='red', markersize=1, markevery=1, zorder=4, linewidth=0.0)
p1 = m.plot(x, y, marker='+', color='red', markerfacecolor='red', markeredgecolor='red', markersize=1, markevery=1,
zorder=4, linewidth=0.0)
m.fillcontinents(color='0.85', lake_color=None, zorder=3)
m.drawparallels(np.arange(-90.,90.,5.), labels=[1,0,1,0],fontsize=10, dashes=[1, 0], color=[0.8,0.8,0.8], zorder=1)
m.drawmeridians(np.arange(-180.,180.,5.), labels=[0,1,0,1],fontsize=10, dashes=[1, 0], color=[0.8,0.8,0.8], zorder=2)
m.drawparallels(np.arange(-90., 90., 5.), labels=[1, 0, 1, 0], fontsize=10, dashes=[1, 0],
color=[0.8, 0.8, 0.8], zorder=1)
m.drawmeridians(np.arange(-180., 180., 5.), labels=[0, 1, 0, 1], fontsize=10, dashes=[1, 0],
color=[0.8, 0.8, 0.8], zorder=2)
plt.show()
......@@ -263,9 +263,12 @@ def amsua_edge_geom(scans_nb):
def mhs(scans_nb, edges_only=False):
""" Describe MHS instrument geometry
See:
- https://www.eumetsat.int/website/home/Satellites/CurrentSatellites/Metop/MetopDesign/MHS/index.html
- https://www1.ncdc.noaa.gov/pub/data/satellite/publications/podguides/N-15%20thru%20N-19/pdf/0.0%20NOAA%20KLM%20Users%20Guide.pdf
- https://www1.ncdc.noaa.gov/pub/data/satellite/publications/podguides/
N-15%20thru%20N-19/pdf/0.0%20NOAA%20KLM%20Users%20Guide.pdf
(NOAA KLM Users Guide –August 2014 Revision)
Parameters:
......@@ -316,10 +319,12 @@ def mhs_edge_geom(scans_nb):
################################################################
def hirs4(scans_nb, edges_only=False):
""" Describe HIRS/4 instrument geometry
"""Describe HIRS/4 instrument geometry.
See:
- https://www.eumetsat.int/website/home/Satellites/CurrentSatellites/Metop/MetopDesign/HIRS/index.html
- https://www1.ncdc.noaa.gov/pub/data/satellite/publications/podguides/N-15%20thru%20N-19/pdf/0.0%20NOAA%20KLM%20Users%20Guide.pdf
- https://www1.ncdc.noaa.gov/pub/data/satellite/publications/podguides/
N-15%20thru%20N-19/pdf/0.0%20NOAA%20KLM%20Users%20Guide.pdf
(NOAA KLM Users Guide –August 2014 Revision)
Parameters:
......@@ -372,8 +377,12 @@ def hirs4_edge_geom(scans_nb):
def atms(scans_nb, edges_only=False):
""" Describe MHS instrument geometry
See:
https://dtcenter.org/com-GSI/users/docs/presentations/2013_workshop/Garrett_GSI_2013.pdf (Assimilation of Suomi-NPP ATMS, Kevin Garrett et al., August 8, 2013)
https://www.star.nesdis.noaa.gov/star/documents/meetings/2016JPSSAnnual/S4/S4_13_JPSSScience2016_session4Part2_ATMS_Scan_Reversal_HYANG.pdf (Suomi NPP ATMS Scan Reversal Study, Hu (Tiger) Yang, NOAA/STAR ATMS SDR Working Group)
- https://dtcenter.org/com-GSI/users/docs/presentations/2013_workshop/
Garrett_GSI_2013.pdf (Assimilation of Suomi-NPP ATMS, Kevin Garrett et al., August 8, 2013)
- https://www.star.nesdis.noaa.gov/star/documents/meetings/2016JPSSAnnual/
S4/S4_13_JPSSScience2016_session4Part2_ATMS_Scan_Reversal_HYANG.pdf
(Suomi NPP ATMS Scan Reversal Study, Hu (Tiger) Yang, NOAA/STAR ATMS SDR Working Group)
Parameters:
scans_nb | int - number of scan lines
......
......@@ -181,7 +181,7 @@ class Orbital(object):
pos0, vel0 = self.get_position(t_old, normalize=False)
pos1, vel1 = self.get_position(t_new, normalize=False)
while not (pos0[2] > 0 and pos1[2] < 0):
pos0, vel0 = pos1, vel1
pos0 = pos1
t_old = t_new
t_new = t_old - dt
pos1, vel1 = self.get_position(t_new, normalize=False)
......@@ -194,7 +194,7 @@ class Orbital(object):
# Bisect to z within 1 km
while np.abs(pos1[2]) > 1:
pos0, vel0 = pos1, vel1
# pos0, vel0 = pos1, vel1
dt = (t_old - t_new) / 2
t_mid = t_old - dt
pos1, vel1 = self.get_position(t_mid, normalize=False)
......@@ -547,20 +547,20 @@ class _SGDP4(object):
def __init__(self, orbit_elements):
self.mode = None
perigee = orbit_elements.perigee
# perigee = orbit_elements.perigee
self.eo = orbit_elements.excentricity
self.xincl = orbit_elements.inclination
self.xno = orbit_elements.original_mean_motion
k_2 = CK2
k_4 = CK4
k_e = XKE
# k_2 = CK2
# k_4 = CK4
# k_e = XKE
self.bstar = orbit_elements.bstar
self.omegao = orbit_elements.arg_perigee
self.xmo = orbit_elements.mean_anomaly
self.xnodeo = orbit_elements.right_ascension
self.t_0 = orbit_elements.epoch
self.xn_0 = orbit_elements.mean_motion
A30 = -XJ3 * AE**3
# A30 = -XJ3 * AE**3
if not(0 < self.eo < ECC_LIMIT_HIGH):
raise OrbitalError('Eccentricity out of range: %e' % self.eo)
......@@ -632,12 +632,11 @@ class _SGDP4(object):
self.c1 = self.bstar * self.c2
self.c4 = (2.0 * self.xnodp * coef_1 * self.aodp * betao2 * (self.eta *
(2.0 + 0.5 * etasq) + self.eo * (0.5 + 2.0 *
etasq) - (2.0 * CK2) * tsi / (self.aodp * psisq) * (-3.0 *
self.x3thm1 * (1.0 - 2.0 * eeta + etasq *
(1.5 - 0.5 * eeta)) + 0.75 * self.x1mth2 * (2.0 *
etasq - eeta * (1.0 + etasq)) * np.cos(2.0 * self.omegao))))
self.c4 = (2.0 * self.xnodp * coef_1 * self.aodp * betao2 * (
self.eta * (2.0 + 0.5 * etasq) + self.eo * (0.5 + 2.0 * etasq) - (2.0 * CK2) * tsi /
(self.aodp * psisq) * (-3.0 * self.x3thm1 * (1.0 - 2.0 * eeta + etasq * (1.5 - 0.5 * eeta)) +
0.75 * self.x1mth2 * (2.0 * etasq - eeta * (1.0 + etasq)) *
np.cos(2.0 * self.omegao))))
self.c5, self.c3, self.omgcof = 0.0, 0.0, 0.0
......@@ -878,6 +877,7 @@ def kep2xyz(kep):
return np.array((x, y, z)), np.array((v_x, v_y, v_z))
if __name__ == "__main__":
obs_lon, obs_lat = np.deg2rad((12.4143, 55.9065))
obs_alt = 0.02
......
......@@ -19,17 +19,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""The tests package.
"""
"""The tests package."""
from pyorbital.tests import (test_aiaa, test_tlefile, test_orbital,
test_astronomy, test_geoloc)
import unittest
def suite():
"""The global test suite.
"""
"""The global test suite."""
mysuite = unittest.TestSuite()
# Test the documentation strings
# mysuite.addTests(doctest.DocTestSuite(image))
......@@ -39,8 +37,8 @@ def suite():
mysuite.addTests(test_orbital.suite())
mysuite.addTests(test_astronomy.suite())
mysuite.addTests(test_geoloc.suite())
return mysuite
if __name__ == '__main__':
unittest.TextTestRunner(verbosity=2).run(suite())
......@@ -28,7 +28,7 @@ from __future__ import print_function, with_statement
import os
import unittest
from datetime import datetime, timedelta
from datetime import datetime
import numpy as np
......@@ -107,10 +107,10 @@ class AIAAIntegrationTest(unittest.TestCase):
try:
o = LineOrbital("unknown", line1, line2)
except NotImplementedError as e:
except NotImplementedError:
test_line = f__.readline()
continue
except ChecksumError as e:
except ChecksumError:
self.assertTrue(test_line.split()[1] in [
"33333", "33334", "33335"])
for delay in times:
......
......@@ -26,16 +26,13 @@ from datetime import datetime
import pyorbital.astronomy as astr
class TestAstronomy(unittest.TestCase):
def setUp(self):
pass
def test_jdays(self):
"""Test julian day functions.
"""
"""Test julian day functions."""
t = datetime(2000, 1, 1, 12, 0)
self.assertEqual(astr.jdays(t), 2451545.0)
self.assertEqual(astr.jdays2000(t), 0)
......@@ -44,8 +41,7 @@ class TestAstronomy(unittest.TestCase):
self.assertEqual(astr.jdays2000(t), 3568.1041666666665)
def test_sunangles(self):
"""Test the sun-angle calculations:
"""
"""Test the sun-angle calculations."""
lat, lon = 58.6167, 16.1833 # Norrkoping
time_slot = datetime(2011, 9, 23, 12, 0)
......@@ -54,12 +50,11 @@ class TestAstronomy(unittest.TestCase):
sun_theta = astr.sun_zenith_angle(time_slot, 0., 0.)
self.assertAlmostEqual(sun_theta, 1.8751916863323426, places=8)
def suite():
"""The suite for test_astronomy
"""
"""The suite for test_astronomy."""
loader = unittest.TestLoader()
mysuite = unittest.TestSuite()
mysuite.addTest(loader.loadTestsFromTestCase(TestAstronomy))
return mysuite
......@@ -19,33 +19,23 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Test the geoloc module.
"""
import unittest
from datetime import datetime, timedelta
from datetime import datetime
import numpy as np
from pyorbital.geoloc import ScanGeometry, geodetic_lat, qrotate, subpoint
from pyorbital.geoloc_instrument_definitions import (avhrr,
viirs,
amsua,
mhs,
hirs4,
atms,
ascat)
from pyorbital.geoloc_instrument_definitions import avhrr, viirs, amsua, mhs, hirs4, atms, ascat
class TestQuaternion(unittest.TestCase):
"""Test the quaternion rotation.
"""
"""Test the quaternion rotation."""
def test_qrotate(self):
"""Test quaternion rotation
"""
"""Test quaternion rotation."""
vector = np.array([[1, 0, 0]]).T
axis = np.array([[0, 1, 0]]).T
angle = np.deg2rad(90)
......@@ -126,23 +116,15 @@ class TestGeoloc(unittest.TestCase):
np.timedelta64(100, 'ms'))
def test_geodetic_lat(self):
"""Test the determination of the geodetic latitude.
"""
a = 6378.137 # km
b = 6356.75231414 # km, GRS80
"""Test the determination of the geodetic latitude."""
point = np.array([7000, 0, 7000])
self.assertEqual(geodetic_lat(point), 0.78755832699854733)
points = np.array([[7000, 0, 7000],
[7000, 0, 7000]]).T
self.assertTrue(np.allclose(geodetic_lat(points),
np.array([0.78755832699854733,
0.78755832699854733])))
self.assertTrue(np.allclose(geodetic_lat(points), np.array([0.78755832699854733, 0.78755832699854733])))
def test_subpoint(self):
"""Test nadir determination.
"""
"""Test nadir determination."""
a = 6378.137 # km
b = 6356.75231414 # km, GRS80
point = np.array([0, 0, 7000])
......
......@@ -33,7 +33,6 @@ 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"
class TLETest(unittest.TestCase):
"""Test TLE reading.
......@@ -99,4 +98,3 @@ def suite():
mysuite.addTest(loader.loadTestsFromTestCase(TLETest))
return mysuite
......@@ -39,19 +39,23 @@ TLE_URLS = ('http://celestrak.com/NORAD/elements/weather.txt',
'https://www.celestrak.com/NORAD/elements/cubesat.txt',
'http://celestrak.com/NORAD/elements/stations.txt',
'https://www.celestrak.com/NORAD/elements/sarsat.txt',
'https://www.celestrak.com/NORAD/elements/noaa.txt')
'https://www.celestrak.com/NORAD/elements/noaa.txt',
'https://www.celestrak.com/NORAD/elements/amateur.txt')
LOGGER = logging.getLogger(__name__)
PKG_CONFIG_DIR = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'etc')
def read_platform_numbers(in_upper=False, num_as_int=False):
'''Read platform numbers from $PPP_CONFIG_DIR/platforms.txt if available.
'''
"""Read platform numbers from $PPP_CONFIG_DIR/platforms.txt if available."""
out_dict = {}
if "PPP_CONFIG_DIR" in os.environ:
platform_file = os.path.join(os.environ["PPP_CONFIG_DIR"],
"platforms.txt")
os.getenv('PPP_CONFIG_DIR', PKG_CONFIG_DIR)
platform_file = None
if 'PPP_CONFIG_DIR' in os.environ:
platform_file = os.path.join(os.environ['PPP_CONFIG_DIR'], 'platforms.txt')
if not platform_file or not os.path.isfile(platform_file):
platform_file = os.path.join(PKG_CONFIG_DIR, 'platforms.txt')
try:
fid = open(platform_file, 'r')
except IOError:
......@@ -85,16 +89,16 @@ in the following format:
def read(platform, tle_file=None, line1=None, line2=None):
"""Read TLE for *satellite* from *tle_file*, from *line1* and *line2*, from
the newest file provided in the TLES pattern, or from internet if none is
provided.
"""Read TLE for `platform` from `tle_file`
File is read from `line1` to `line2`, from the newest file provided in the
TLES pattern, or from internet if none is provided.
"""
return Tle(platform, tle_file=tle_file, line1=line1, line2=line2)
def fetch(destination):
"""fetch TLE from internet and save it to *destination*.
"""
"""Fetch TLE from internet and save it to `destination`."""
with io.open(destination, mode="w", encoding="utf-8") as dest:
for url in TLE_URLS:
response = urlopen(url)
......@@ -102,16 +106,12 @@ def fetch(destination):
class ChecksumError(Exception):
'''ChecksumError.
'''
"""ChecksumError."""
pass
class Tle(object):
"""Class holding TLE objects.
"""
"""Class holding TLE objects."""
def __init__(self, platform, tle_file=None, line1=None, line2=None):
self._platform = platform.strip().upper()
......@@ -146,22 +146,21 @@ class Tle(object):
@property
def line1(self):
'''Return first TLE line.'''
"""Return first TLE line."""
return self._line1
@property
def line2(self):
'''Return second TLE line.'''
"""Return second TLE line."""
return self._line2
@property
def platform(self):
'''Return satellite platform name.'''
"""Return satellite platform name."""
return self._platform
def _checksum(self):
"""Performs the checksum for the current TLE.
"""
"""Performs the checksum for the current TLE."""
for line in [self._line1, self._line2]:
check = 0
for char in line[:-1]:
......@@ -174,9 +173,7 @@ class Tle(object):
raise ChecksumError(self._platform + " " + line)
def _read_tle(self):
'''Read TLE data.
'''
"""Read TLE data."""
if self._line1 is not None and self._line2 is not None:
tle = self._line1.strip() + "\n" + self._line2.strip()
else:
......@@ -228,11 +225,10 @@ class Tle(object):
self._line1, self._line2 = tle.split('\n')
def _parse_tle(self):
'''Parse values from TLE data.
'''
"""Parse values from TLE data."""
def _read_tle_decimal(rep):
'''Convert *rep* to decimal value.
'''
"""Convert *rep* to decimal value."""
if rep[0] in ["-", " ", "+"]:
digits = rep[1:-2].strip()
val = rep[0] + "." + digits + "e" + rep[-2:]
......@@ -284,8 +280,7 @@ class Tle(object):
def main():
'''Main for testing TLE reading.
'''
"""Main for testing TLE reading."""
tle_data = read('Noaa-19')
print(tle_data)
......