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 script to get SNOs for two platforms #51

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ dist
build
eggs
parts
bin
var
sdist
develop-eggs
Expand Down
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
exclude: '^$'
fail_fast: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.2.3
hooks:
- id: flake8
additional_dependencies: [flake8-docstrings, flake8-debugger, flake8-bugbear]
165 changes: 165 additions & 0 deletions bin/get_snos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2014 - 2019 Adam.Dybbroe

# Author(s):

# Adam.Dybbroe <[email protected]>
# Nina Håkansson <[email protected]>
# Erik Johansson <[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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Getting SNOs for two configurable satellite platforms."""

import sys
from datetime import datetime, timedelta

from pyorbital.orbital import Orbital
from pyorbital.sno_utils import get_config
from pyorbital.sno_utils import get_arc
from pyorbital.sno_utils import get_tle
from pyorbital.sno_utils import get_sno_point

import logging
import time

t = time.time()
LOG = logging.getLogger('snos')

handler = logging.StreamHandler(sys.stderr)
handler.setLevel(0)
LOG.setLevel(0)
LOG.addHandler(handler)


def get_arguments():
"""Get the comman line arguments required to run the script."""
import argparse

parser = argparse.ArgumentParser(description='Calculate SNOS between two satellite platforms')
parser.add_argument("-s", "--start-datetime",
required=True,
dest="start_datetime",
type=str,
default=None,
help="The datetime string corresponding to the start time of when SNOS should be calculated")
parser.add_argument("-e", "--end-datetime",
required=True,
dest="end_datetime",
type=str,
default=None,
help="The datetime string corresponding to the end time of when SNOS should be calculated")
parser.add_argument("-t", "--time-window",
required=True,
dest="time_window",
type=str,
default=None,
help=("The time window in number of minutes - the maximum time allowed between " +
"the two SNO observations"))
parser.add_argument("-p", "--platform-name",
required=True,
dest="platform_name",
type=str,
default=None,
help="The name of the satellite platform")
parser.add_argument("-c", "--configfile",
required=True,
dest="configfile",
type=str,
default=None,
help="The path to the configuration file")
parser.add_argument("-l", "--log-file", dest="log",
type=str,
default=None,
help="The file to log to (stdout per default).")

args = parser.parse_args()
return args


if __name__ == "__main__":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Encapsulate all this in main() function, and in if __name__ == "__main__": block call that. Can save some time later on when hunting a bug that is caused by polluted namespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


args = get_arguments()
conf = get_config(args.configfile)

station = {}
station['lon'] = conf['station']['longitude']
station['lat'] = conf['station']['latitude']
station['alt'] = conf['station']['altitude']

ref_platform_name = conf['reference_platform']['name']

tle_dirs = conf['tle-dirs']
tle_file_format = conf['tle-file-format']
platform_id = args.platform_name
minthr = int(args.time_window)
time_start = datetime.strptime(args.start_datetime, "%Y%m%d")
time_end = datetime.strptime(args.end_datetime, "%Y%m%d")

dtime = timedelta(seconds=60 * minthr * 2.0)
timestep = timedelta(seconds=60 * minthr * 1.0)
delta_t = dtime

tobj = time_start
tle_ref_pltfrm = None
tle_cmp_platform = None
tobj_tmp = time_start
is_within_antenna_horizon = False
while tobj < time_end:
if not tle_ref_pltfrm or abs(tle_ref_pltfrm.epoch.astype(datetime) - tobj) > timedelta(days=1):
tle_ref_pltfrm = get_tle(tle_dirs, tle_file_format, ref_platform_name, tobj)
if (not tle_cmp_platform or
abs(tle_cmp_platform.epoch.astype(datetime) - tobj) > timedelta(days=2)):
tle_cmp_platform = get_tle(tle_dirs, tle_file_format, platform_id, tobj)

ref_pltfrm = Orbital(ref_platform_name,
line1=tle_ref_pltfrm.line1,
line2=tle_ref_pltfrm.line2)
cmp_platform = Orbital(platform_id,
line1=tle_cmp_platform.line1,
line2=tle_cmp_platform.line2)

arc_ref_pltfrm = get_arc(tobj, timestep, ref_pltfrm)
arc_cmp_platform = get_arc(tobj, timestep, cmp_platform)

if arc_ref_pltfrm and arc_cmp_platform:
if arc_ref_pltfrm.intersects(arc_cmp_platform):
# If the two sub-satellite tracks of the overpasses intersects
# get the sub-satellite position and time where they cross,
# and determine if the time deviation is smaller than the require threshold:
sno = get_sno_point(platform_id, cmp_platform, ref_pltfrm,
tobj, delta_t, arc_ref_pltfrm,
arc_cmp_platform, station, minthr)

if sno:
print(" " +
str(sno['maxt_ref_pltfrm'].strftime("%Y-%m-%d %H:%M, ")) +
"%5.1f," % sno['ref_pltfrmsec'] + " "*5 +
str(sno['maxt'].strftime("%Y-%m-%d %H:%M, ")) +
"%5.1f," % sno['sec'] +
# " imager-orbit, %d, " % (sno['orbit_nr'] + 1) +
" %d, " % (sno['orbit_nr'] + 1) +
" "*6 + "%7.2f, %7.2f," % (sno['point'][1], sno['point'][0]) +
" " + "%4.1f," % abs(sno['tdmin']) + " " + str(sno['is_within_antenna_horizon'])
)

else:
LOG.error("Failed getting the track-segments")

tobj = tobj + dtime
if tobj - tobj_tmp > timedelta(days=1):
tobj_tmp = tobj
LOG.debug(tobj_tmp.strftime("%Y-%m-%d"))
23 changes: 23 additions & 0 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
The :mod:`pyorbital` API
=========================

Orbital computations
~~~~~~~~~~~~~~~~~~~~

.. automodule:: pyorbital.orbital
:members:
:undoc-members:

TLE handling
~~~~~~~~~~~~

.. automodule:: pyorbital.tlefile
:members:
:undoc-members:

Astronomical computations
~~~~~~~~~~~~~~~~~~~~~~~~~

.. automodule:: pyorbital.astronomy
:members:
:undoc-members:
11 changes: 11 additions & 0 deletions doc/source/astronomy.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Computing astronomical parameters
---------------------------------
The astronomy module enables computation of certain parameters of interest for satellite remote sensing for instance the Sun-zenith angle:

>>> from pyorbital import astronomy
>>> from datetime import datetime
>>> utc_time = datetime(2012, 5, 15, 15, 45)
>>> lon, lat = 12, 56
>>> astronomy.sun_zenith_angle(utc_time, lon, lat)
62.685986438071602

126 changes: 18 additions & 108 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,117 +3,27 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.

Pyorbital
=========
====================================
Welcome to Pyorbital's documentation
====================================

Pyorbital is a python package to compute orbital parameters for satellites from
TLE files as well as astronomical parameters of interest for satellite remote sensing.
Currently pyorbital only supports low earth orbit satellites.

Installation
------------
Pyorbital comes with a file platforms.txt that maps satellite name to NORAD identifier.
This file needs to be copied to the appropriate satpy etc directory ($PPP_CONFIG_DIR).
It is wise to check it contains your satellites of interest. The NORAD identifier can
be found as the first number of each line in the Two-Line Elements (eg. from celestrak).

TLE files
---------
Pyorbital has a module for parsing NORAD TLE-files

>>> from pyorbital import tlefile
>>> tle = tlefile.read('noaa 18', '/path/to/my/tle_file.txt')
>>> tle.inclination
99.043499999999995

If no path is given pyorbital tries to read the earth observation TLE-files from celestrak.com

Computing satellite position
----------------------------
The orbital module enables computation of satellite position and velocity at a specific time:

>>> from pyorbital.orbital import Orbital
>>> from datetime import datetime
>>> # Use current TLEs from the internet:
>>> orb = Orbital("Suomi NPP")
>>> now = datetime.utcnow()
>>> # Get normalized position and velocity of the satellite:
>>> orb.get_position(now)
(array([-0.20015267, 0.09001458, 1.10686756]),
array([ 0.06148495, 0.03234914, 0.00846805]))
>>> # Get longitude, latitude and altitude of the satellite:
>>> orb.get_lonlatalt(now)
(40.374855865574951, 78.849923885700363, 839.62504115338368)


Use actual TLEs to increase accuracy
------------------------------------

>>> from pyorbital.orbital import Orbital
>>> from datetime import datetime
>>> orb = Orbital("Suomi NPP")
>>> dtobj = datetime(2015,2,7,3,0)
>>> orb.get_lonlatalt(dtobj)
(152.11564698762811, 20.475251739329622, 829.37355785502211)

But since we are interested in knowing the position of the Suomi-NPP more than
two and half years from now (September 26, 2017) we can not rely on the current
TLEs, but rather need a TLE closer to the time of interest:

>>> snpp = Orbital('Suomi NPP', tle_file='/data/lang/satellit/polar/orbital_elements/TLE/201502/tle-20150207.txt')
>>> snpp.get_lonlatalt(dtobj)
(105.37373804512762, 79.160752404540133, 838.94605490133154)

If we take a TLE from one week earlier we get a slightly different result:

>>> snpp = Orbital('Suomi NPP', tle_file='/data/lang/satellit/polar/orbital_elements/TLE/201501/tle-20150131.txt')
>>> snpp.get_lonlatalt(dtobj)
(104.1539184988462, 79.328272480878141, 838.81555967963391)



Computing astronomical parameters
---------------------------------
The astronomy module enables computation of certain parameters of interest for satellite remote sensing for instance the Sun-zenith angle:

>>> from pyorbital import astronomy
>>> from datetime import datetime
>>> utc_time = datetime(2012, 5, 15, 15, 45)
>>> lon, lat = 12, 56
>>> astronomy.sun_zenith_angle(utc_time, lon, lat)
62.685986438071602

API
---

Orbital computations
~~~~~~~~~~~~~~~~~~~~

.. automodule:: pyorbital.orbital
:members:
:undoc-members:

TLE handling
~~~~~~~~~~~~

.. automodule:: pyorbital.tlefile
:members:
:undoc-members:

Astronomical computations
~~~~~~~~~~~~~~~~~~~~~~~~~

.. automodule:: pyorbital.astronomy
:members:
:undoc-members:


.. Contents:
.. toctree::
:maxdepth: 2
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. toctree::
:maxdepth: 2

install
tlefiles
sat_position
astronomy
snos
api

Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

41 changes: 41 additions & 0 deletions doc/source/install.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
=========================
Installation Instructions
=========================

Note
----
Pyorbital comes with a file platforms.txt that maps satellite name to NORAD identifier.
This file needs to be copied to the appropriate Satpy `etc` directory ($PPP_CONFIG_DIR).
It is wise to check it contains your satellites of interest. The NORAD identifier can
be found as the first number of each line in the Two-Line Elements (eg. from celestrak).

Pip-based Installation
======================

Pyorbital is available from the Python Packaging Index (PyPI). A sandbox
environment for `pyorbital` can be created using
`Virtualenv <http://pypi.python.org/pypi/virtualenv>`_.

To install the `pyorbital` package and the python dependencies:

.. code-block:: bash

$ pip install pyorbital


Conda-based Installation
========================

Starting with version 1.3.1, Pyorbital is available from the conda-forge channel. If
you have not configured your conda environment to search conda-forge already
then do:

.. code-block:: bash

$ conda config --add channels conda-forge

Then to install Pyorbital in to your current environment run:

.. code-block:: bash

$ conda install pyorbital
Loading