Skip to content
Commits on Source (9)
[bumpversion]
current_version = 1.3.1
commit = True
tag = True
[bumpversion:file:pyorbital/version.py]
pyorbital/version.py export-subst
##
## Format
##
## ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...]
##
## Description
##
## ACTION is one of 'chg', 'fix', 'new'
##
## Is WHAT the change is about.
##
## 'chg' is for refactor, small improvement, cosmetic changes...
## 'fix' is for bug fixes
## 'new' is for new features, big improvement
##
## AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc'
##
## Is WHO is concerned by the change.
##
## 'dev' is for developpers (API changes, refactors...)
## 'usr' is for final users (UI changes)
## 'pkg' is for packagers (packaging changes)
## 'test' is for testers (test only related changes)
## 'doc' is for doc guys (doc only changes)
##
## COMMIT_MSG is ... well ... the commit message itself.
##
## TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic'
##
## They are preceded with a '!' or a '@' (prefer the former, as the
## latter is wrongly interpreted in github.) Commonly used tags are:
##
## 'refactor' is obviously for refactoring code only
## 'minor' is for a very meaningless change (a typo, adding a comment)
## 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...)
## 'wip' is for partial functionality but complete subfunctionality.
##
## Example:
##
## new: usr: support of bazaar implemented
## chg: re-indentend some lines !cosmetic
## new: dev: updated code to be compatible with last version of killer lib.
## fix: pkg: updated year of licence coverage.
## new: test: added a bunch of test around user usability of feature X.
## fix: typo in spelling my name in comment. !minor
##
## Please note that multi-line commit message are supported, and only the
## first line will be considered as the "summary" of the commit message. So
## tags, and other rules only applies to the summary. The body of the commit
## message will be displayed in the changelog without reformatting.
##
## ``ignore_regexps`` is a line of regexps
##
## Any commit having its full commit message matching any regexp listed here
## will be ignored and won't be reported in the changelog.
##
ignore_regexps = [
r'@minor', r'!minor',
r'@cosmetic', r'!cosmetic',
r'@refactor', r'!refactor',
r'@wip', r'!wip',
r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:',
r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:',
r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$',
]
## ``section_regexps`` is a list of 2-tuples associating a string label and a
## list of regexp
##
## Commit messages will be classified in sections thanks to this. Section
## titles are the label, and a commit is classified under this section if any
## of the regexps associated is matching.
##
section_regexps = [
('New', [
r'^[nN]ew\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
]),
('Changes', [
r'^[cC]hg\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
]),
('Fix', [
r'^[fF]ix\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
]),
('Other', None ## Match all lines
),
]
## ``body_process`` is a callable
##
## This callable will be given the original body and result will
## be used in the changelog.
##
## Available constructs are:
##
## - any python callable that take one txt argument and return txt argument.
##
## - ReSub(pattern, replacement): will apply regexp substitution.
##
## - Indent(chars=" "): will indent the text with the prefix
## Please remember that template engines gets also to modify the text and
## will usually indent themselves the text if needed.
##
## - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns
##
## - noop: do nothing
##
## - ucfirst: ensure the first letter is uppercase.
## (usually used in the ``subject_process`` pipeline)
##
## - final_dot: ensure text finishes with a dot
## (usually used in the ``subject_process`` pipeline)
##
## - strip: remove any spaces before or after the content of the string
##
## Additionally, you can `pipe` the provided filters, for instance:
#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ")
#body_process = Wrap(regexp=r'\n(?=\w+\s*:)')
body_process = noop
## ``subject_process`` is a callable
##
## This callable will be given the original subject and result will
## be used in the changelog.
##
## Available constructs are those listed in ``body_process`` doc.
subject_process = (strip |
ReSub(r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') |
ucfirst | final_dot)
## ``tag_filter_regexp`` is a regexp
##
## Tags that will be used for the changelog must match this regexp.
##
tag_filter_regexp = r'^v[0-9]+\.[0-9]+(\.[0-9]+)?$'
## ``unreleased_version_label`` is a string
##
## This label will be used as the changelog Title of the last set of changes
## between last valid tag and HEAD if any.
unreleased_version_label = "%%version%% (unreleased)"
## ``output_engine`` is a callable
##
## This will change the output format of the generated changelog file
##
## Available choices are:
##
## - rest_py
##
## Legacy pure python engine, outputs ReSTructured text.
## This is the default.
##
## - mustache(<template_name>)
##
## Template name could be any of the available templates in
## ``templates/mustache/*.tpl``.
## Requires python package ``pystache``.
## Examples:
## - mustache("markdown")
## - mustache("restructuredtext")
##
## - makotemplate(<template_name>)
##
## Template name could be any of the available templates in
## ``templates/mako/*.tpl``.
## Requires python package ``mako``.
## Examples:
## - makotemplate("restructuredtext")
##
output_engine = rest_py
#output_engine = mustache("restructuredtext")
#output_engine = mustache("markdown")
#output_engine = makotemplate("restructuredtext")
## ``include_merges`` is a boolean
##
## This option tells git-log whether to include merge commits in the log.
## The default is to include them.
include_merges = True
<!-- Please make the PR against the `develop` branch. -->
<!-- Please make the PR against the `master` 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 ``git diff origin/develop **/*py | flake8 --diff`` <!-- remove if you did not edit any Python files -->
- [ ] Passes ``git diff origin/master **/*py | flake8 --diff`` <!-- 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
language: python
python:
- '2.7'
- "3.5"
- "3.6"
install:
- pip install dask[array] xarray
- pip install .
- pip install coveralls
script: coverage run --source=pyorbital setup.py test
......
## Version 1.4.0 (2018/10/23)
### Issues Closed
* [Issue 36](https://github.com/pytroll/pyorbital/issues/36) - Issue(s) with get_next_passes
* [Issue 34](https://github.com/pytroll/pyorbital/issues/34) - Get root secant converging to wrong solution ([PR 35](https://github.com/pytroll/pyorbital/pull/35))
* [Issue 30](https://github.com/pytroll/pyorbital/issues/30) - get_observer_look turns xarray.DataArray objects into dask.array objects
* [Issue 29](https://github.com/pytroll/pyorbital/issues/29) - URL error
* [Issue 27](https://github.com/pytroll/pyorbital/issues/27) - satellite.get_lonlatalt(now) returns wrong longitude with numpy < 1.11
* [Issue 18](https://github.com/pytroll/pyorbital/issues/18) - Sun-satellite angle ranges are not consistent
In this release 6 issues were closed.
### Pull Requests Merged
#### Bugs fixed
* [PR 39](https://github.com/pytroll/pyorbital/pull/39) - Bugfix python3
* [PR 35](https://github.com/pytroll/pyorbital/pull/35) - Use Scipy brentq method instead of secant method to perform root-finding ([34](https://github.com/pytroll/pyorbital/issues/34))
#### Features added
* [PR 37](https://github.com/pytroll/pyorbital/pull/37) - Switch to versioneer
* [PR 33](https://github.com/pytroll/pyorbital/pull/33) - Remove Develop branch
In this release 4 pull requests were closed.
......@@ -3,3 +3,5 @@ recursive-include doc/source *
include LICENSE.txt
include MANIFEST.in
include README
include versioneer.py
include pyorbital/version.py
# Releasing Pyorbital
prerequisites: `pip install setuptools twine`
1. checkout master
2. pull from repo
3. run the unittests
4. run `loghub` and update the `CHANGELOG.md` file:
```
loghub pytroll/pyorbital -u <username> -st v0.8.0 -plg bug "Bugs fixed" -plg enhancement "Features added" -plg documentation "Documentation changes"
```
Don't forget to commit!
5. Create a tag with the new version number, starting with a 'v', eg:
```
git tag v0.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.3.1-2) UNRELEASED; urgency=medium
pyorbital (1.4.0-1) unstable; urgency=medium
* Team upload.
[ Bas Couwenberg ]
* Drop ancient X-Python{,3}-Version fields.
* Bump Standards-Version to 4.2.1, no changes.
* Update watch file to limit matches to archive path.
-- Bas Couwenberg <sebastic@debian.org> Sun, 06 May 2018 09:16:37 +0200
[ Antonio Valentino ]
* New upstream release.
* Update copyright file.
* debian/control
- add dependency from scipy
- recommend dask and xarray
* debian/rules
- duild sphinx doc using Python 3
* debian/patches
- refresh all patches.
- new 0002-Skip-tests-using-on-xarray-or-dask-if-they-are-not-a.patch.
Skip tests using dask or xarray if they are not available.
-- Antonio Valentino <antonio.valentino@tiscali.it> Sun, 11 Nov 2018 10:21:51 +0000
pyorbital (1.3.1-1) unstable; urgency=medium
......
......@@ -11,8 +11,12 @@ Build-Depends: debhelper (>= 11),
python3-all,
python-numpy,
python3-numpy,
python-scipy,
python3-scipy,
python-sphinx,
python3-sphinx
python3-sphinx,
python3-dask,
python3-xarray
Standards-Version: 4.2.1
Vcs-Browser: https://salsa.debian.org/debian-gis-team/pyorbital
Vcs-Git: https://salsa.debian.org/debian-gis-team/pyorbital.git
......@@ -23,7 +27,8 @@ Architecture: all
Depends: ${shlibs:Depends},
${python:Depends},
${misc:Depends},
python-numpy
python-numpy,
python-scipy
Suggests: python-pyorbital-doc
Description: Orbital and astronomy computations in Python 2
Python package for computing orbital parameters from TLE
......@@ -38,7 +43,10 @@ Architecture: all
Depends: ${shlibs:Depends},
${python3:Depends},
${misc:Depends},
python3-numpy
python3-numpy,
python3-scipy
Recommends: python3-dask,
python3-xarray
Suggests: python-pyorbital-doc
Description: Orbital and astronomy computations in Python 3
Python package for computing orbital parameters from TLE
......
......@@ -3,15 +3,20 @@ Upstream-Name: pyorbital
Source: https://github.com/pytroll/pyorbital
Files: *
Copyright: 2011-2015, 2017, Esben S. Nielsen <esn@dmi.dk>
2011-2015, Panu Lahtinen <panu.lahtinen@fmi.fi
Copyright: 2013-2018, PyTroll Community
2011-2018, Esben S. Nielsen <esn@dmi.dk>
2011-2018, Panu Lahtinen <panu.lahtinen@fmi.fi
2011, 2014, SMHI
2012-2015, Adam Dybbroe <adam.dybbroe@smhi.se>
2012-2015, 2017, Martin Raspaud <martin.raspaud@smhi.se>
2011-2018, Martin Raspaud <martin.raspaud@smhi.se>
2012-2014, The Pytroll crew
2013-2015, 2017, Mikhail Itkin <itkin.m@gmail.com>
License: GPL-3+
Files: versioneer.py
Copyright: 2018, Brian Warner
License: CC0-1.0
Files: debian/*
Copyright: 2014, Antonio Valentino <antonio.valentino@tiscali.it>
License: GPL-3+
......@@ -32,3 +37,15 @@ License: GPL-3+
.
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
License: CC0-1.0
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
.
You should have received a copy of the CC0 Public Domain Dedication along with
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
.
On Debian systems, the complete text of the CC0 1.0 Universal license can be
found in ‘/usr/share/common-licenses/CC0-1.0’.
......@@ -7,16 +7,16 @@ Subject: install test sub-package
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index 41ab292..c3747b9 100644
index a5410ef..7575249 100644
--- a/setup.py
+++ b/setup.py
@@ -41,7 +41,8 @@ setup(name='pyorbital',
url="https://github.com/mraspaud/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.6.0,!=1.14.0'],
install_requires=['numpy>=1.11.0,!=1.14.0', 'scipy'],
zip_safe=False,
)
From: Antonio Valentino <antonio.valentino@tiscali.it>
Date: Sun, 11 Nov 2018 11:06:11 +0100
Subject: Skip tests using on xarray or dask if they are not available
---
pyorbital/tests/test_orbital.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/pyorbital/tests/test_orbital.py b/pyorbital/tests/test_orbital.py
index 2ed1a24..0762eea 100644
--- a/pyorbital/tests/test_orbital.py
+++ b/pyorbital/tests/test_orbital.py
@@ -177,6 +177,7 @@ class TestGetObserverLook(unittest.TestCase):
np.testing.assert_allclose(azi, self.exp_azi)
np.testing.assert_allclose(elev, self.exp_elev)
+ @unittest.skipIf(not orbital.has_dask, 'dask not available')
def test_basic_dask(self):
"""Test with dask array inputs"""
from pyorbital import orbital
@@ -193,6 +194,7 @@ class TestGetObserverLook(unittest.TestCase):
np.testing.assert_allclose(azi.compute(), self.exp_azi)
np.testing.assert_allclose(elev.compute(), self.exp_elev)
+ @unittest.skipIf(not orbital.has_xarray, 'xarray not available')
def test_xarray_with_numpy(self):
"""Test with xarray DataArray with numpy array as inputs"""
from pyorbital import orbital
@@ -212,6 +214,8 @@ class TestGetObserverLook(unittest.TestCase):
np.testing.assert_allclose(azi.data, self.exp_azi)
np.testing.assert_allclose(elev.data, self.exp_elev)
+ @unittest.skipIf(not orbital.has_xarray or not orbital.has_dask,
+ 'xarray and/or dask not available')
def test_xarray_with_dask(self):
"""Test with xarray DataArray with dask array as inputs"""
from pyorbital import orbital
0001-install-test-sub-package.patch
0002-Skip-tests-using-on-xarray-or-dask-if-they-are-not-a.patch
......@@ -12,10 +12,12 @@ export PYBUILD_NAME=pyorbital
dh $@ --with python2,python3,sphinxdoc --buildsystem=pybuild
override_dh_auto_build: export http_proxy=127.0.0.1:9
override_dh_auto_build: export https_proxy=127.0.0.1:9
override_dh_auto_build:
dh_auto_build --buildsystem=pybuild
ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
$(MAKE) -C doc html
PYTHONPATH=. python3 -m sphinx -N -bhtml doc/source/ doc/build/html # HTML generator
endif
......
......@@ -17,10 +17,10 @@ import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('../../'))
sys.path.insert(0, os.path.abspath('../../pyorbital'))
from pyorbital.version import __version__
from pyorbital import __version__ # noqa
# -- General configuration -----------------------------------------------------
......@@ -45,16 +45,16 @@ master_doc = 'index'
# General information about the project.
project = u'pyorbital'
copyright = u'2012-2015, The Pytroll crew'
copyright = u'2012-2015, 2018, The Pytroll crew'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = __version__.split('+')[0]
# The full version, including alpha/beta/rc tags.
release = __version__
# The short X.Y version.
version = ".".join(release.split(".")[:2])
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......
......@@ -28,8 +28,8 @@ Pyorbital has a module for parsing NORAD TLE-files
If no path is given pyorbital tries to read the earth observation TLE-files from celestrak.com
Computing satellite postion
---------------------------
Computing satellite position
----------------------------
The orbital module enables computation of satellite position and velocity at a specific time:
>>> from pyorbital.orbital import Orbital
......@@ -56,7 +56,7 @@ Use actual TLEs to increase accuracy
>>> orb.get_lonlatalt(dtobj)
(152.11564698762811, 20.475251739329622, 829.37355785502211)
But since we are interesting knowing the position of the Suomi-NPP more than
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:
......
......@@ -20,6 +20,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
from .version import get_versions
__version__ = get_versions()['version']
del get_versions
def dt2np(utc_time):
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2013, 2014, 2015, 2017 Martin Raspaud
# Copyright (c) 2013 - 2018 PyTroll Community
# Author(s):
# Martin Raspaud <martin.raspaud@smhi.se>
# Mikhail Itkin <itkin.m@gmail.com>
# Adam Dybbroe <adam.dybbroe@smhi.se>
# 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
......@@ -141,15 +142,21 @@ def avhrr_40_geom(scans_nb):
def viirs(scans_nb, scan_indices=slice(0, None),
chn_pixels=6400, scan_lines=32):
chn_pixels=6400, scan_lines=32, scan_step=1):
"""Describe VIIRS instrument geometry, I-band by default.
VIIRS scans several lines simultaneously (there are 16 detectors for each
M-band, 32 detectors for each I-band) so the scan angles (and times) are
two-dimensional arrays, contrary to AVHRR for example.
scan_step: The increment in number of scans. E.g. if scan_step is 100 and
the number of scans (scans_nb) is 10 then these 10 scans are
distributed over the swath so that between each scan there are
99 emtpy (excluded) scans
"""
entire_width = np.arange(chn_pixels)
scan_points = entire_width[scan_indices]
scan_points = entire_width[scan_indices.astype('int')]
scan_pixels = len(scan_points)
''' initial angle 55.84 deg replaced with 56.28 deg found in
......@@ -167,9 +174,10 @@ def viirs(scans_nb, scan_indices=slice(0, None),
npp = np.tile(scan, [scans_nb, 1]).T
# from the timestamp in the filenames, a granule takes 1:25.400 to record
# (85.4 seconds) so 1.779166667 would be the duration of 1 scanline
# dividing the duration of a single scan by a width of 6400 pixels results
# in 0.0002779947917 seconds for each column of 32 pixels in the scanline
# (85.4 seconds) so 1.779166667 would be the duration of 1 scanline (48
# scans per granule) dividing the duration of a single scan by a width of
# 6400 pixels results in 0.0002779947917 seconds for each column of 32
# pixels in the scanline
# the individual times per pixel are probably wrong, unless the scanning
# behaves the same as for AVHRR, The VIIRS sensor rotates to allow internal
......@@ -177,10 +185,13 @@ def viirs(scans_nb, scan_indices=slice(0, None),
# always moves in the same direction. more info @
# http://www.eoportal.org/directory/pres_NPOESSNationalPolarorbitingOperationalEnvironmentalSatelliteSystem.html
offset = np.arange(scans_nb) * 1.779166667
times = (np.tile(scan_points * 0.0002779947917,
[np.int(scan_lines), np.int(scans_nb)])
+ np.expand_dims(offset, 1))
SEC_EACH_SCANCOLUMN = 0.0002779947917
sec_scan_duration = 1.779166667
times = np.tile(scan_points * SEC_EACH_SCANCOLUMN,
[np.int(scans_nb*scan_lines), 1])
offset = np.repeat(np.arange(scans_nb) *
sec_scan_duration*scan_step, scan_lines)
times += np.expand_dims(offset, 1)
# build the scan geometry object
return ScanGeometry(npp, times)
......@@ -403,3 +414,85 @@ def atms(scans_nb, edges_only=False):
def atms_edge_geom(scans_nb):
# we take only edge pixels
return atms(scans_nb, edges_only=True)
################################################################
#
# OLCI
#
################################################################
def olci(scans_nb, scan_points=None):
"""Definition of the OLCI instrument.
Source: Sentinel-3 OLCI Coverage
https://sentinel.esa.int/web/sentinel/user-guides/sentinel-3-olci/coverage
"""
if scan_points is None:
scan_len = 4000 # samples per scan
scan_points = np.arange(4000)
else:
scan_len = len(scan_points)
# scan_rate = 0.044 # single scan, seconds
scan_angle_west = 46.5 # swath, degrees
scan_angle_east = -22.1 # swath, degrees
# sampling_interval = 18e-3 # single view, seconds
# build the olci instrument scan line angles
scanline_angles = np.linspace(np.deg2rad(scan_angle_west),
np.deg2rad(scan_angle_east), scan_len)
inst = np.vstack((scanline_angles, np.zeros(scan_len,)))
inst = np.tile(inst[:, np.newaxis, :], [1, np.int(scans_nb), 1])
# building the corresponding times array
# times = (np.tile(scan_points * 0.000025 + 0.0025415, [scans_nb, 1])
# + np.expand_dims(offset, 1))
times = np.tile(np.zeros_like(scanline_angles), [np.int(scans_nb), 1])
# if apply_offset:
# offset = np.arange(np.int(scans_nb)) * frequency
# times += np.expand_dims(offset, 1)
return ScanGeometry(inst, times)
def ascat(scan_nb, scan_points=None):
"""ASCAT make two scans one to the left and one to the right of the
sub-satellite track.
"""
if scan_points is None:
scan_len = 42 # samples per scan
scan_points = np.arange(42)
else:
scan_len = len(scan_points)
scan_angle_inner = -25.0 # swath, degrees
scan_angle_outer = -53.0 # swath, degrees
scan_rate = 3.74747474747 # single scan, seconds
if scan_len < 2:
raise ValueError("Need at least two scan points!")
sampling_interval = scan_rate / float(np.max(scan_points) + 1)
# build the Metop/ascat instrument scan line angles
scanline_angles_one = np.linspace(-np.deg2rad(scan_angle_outer),
-np.deg2rad(scan_angle_inner), 21)
scanline_angles_two = np.linspace(np.deg2rad(scan_angle_inner),
np.deg2rad(scan_angle_outer), 21)
scan_angles = np.concatenate(
[scanline_angles_one, scanline_angles_two])[scan_points]
inst = np.vstack((scan_angles, np.zeros(scan_len * 1,)))
inst = np.tile(inst[:, np.newaxis, :], [1, np.int(scan_nb), 1])
# building the corresponding times array
offset = np.arange(scan_nb) * scan_rate
times = (np.tile(scan_points * sampling_interval,
[np.int(scan_nb), 1]) + np.expand_dims(offset, 1))
return ScanGeometry(inst, times)
......@@ -28,10 +28,25 @@
import warnings
from datetime import datetime, timedelta
import numpy as np
from scipy import optimize
import numpy as np
from pyorbital import astronomy, dt2np, tlefile
try:
import dask.array as da
has_dask = True
except ImportError:
da = None
has_dask = False
try:
import xarray as xr
has_xarray = True
except ImportError:
xr = None
has_xarray = False
ECC_EPS = 1.0e-6 # Too low for computing further drops.
ECC_LIMIT_LOW = -1.0e-3
ECC_LIMIT_HIGH = 1.0 - ECC_EPS # Too close to 1
......@@ -111,14 +126,22 @@ def get_observer_look(sat_lon, sat_lat, sat_alt, utc_time, lon, lat, alt):
az_ = np.arctan(-top_e / top_s)
if hasattr(az_, 'chunks'):
# dask array
import dask.array as da
az_ = da.where(top_s > 0, az_ + np.pi, az_)
az_ = da.where(az_ < 0, az_ + 2 * np.pi, az_)
if has_xarray and isinstance(az_, xr.DataArray):
az_data = az_.data
else:
az_data = az_
if has_dask and isinstance(az_data, da.Array):
az_data = da.where(top_s > 0, az_data + np.pi, az_data)
az_data = da.where(az_data < 0, az_data + 2 * np.pi, az_data)
else:
az_[top_s > 0] += np.pi
az_[az_ < 0] += 2 * np.pi
az_data[np.where(top_s > 0)] += np.pi
az_data[np.where(az_data < 0)] += 2 * np.pi
if has_xarray and isinstance(az_, xr.DataArray):
az_.data = az_data
else:
az_ = az_data
rg_ = np.sqrt(rx * rx + ry * ry + rz * rz)
el_ = np.arcsin(top_z / rg_)
......@@ -131,7 +154,7 @@ class Orbital(object):
"""Class for orbital computations.
The *satellite* parameter is the name of the satellite to work on and is
used to retreive the right TLE data for internet or from *tle_file* in case
used to retrieve the right TLE data for internet or from *tle_file* in case
it is provided.
"""
......@@ -337,8 +360,8 @@ class Orbital(object):
"""Compute the inverse of elevation."""
return -elevation(minutes)
def get_root_secant(fun, start, end, tol=0.01):
"""Secant method."""
def get_root(fun, start, end, tol=0.01):
"""Root finding scheme"""
x_0 = end
x_1 = start
fx_0 = fun(end)
......@@ -346,11 +369,9 @@ class Orbital(object):
if abs(fx_0) < abs(fx_1):
fx_0, fx_1 = fx_1, fx_0
x_0, x_1 = x_1, x_0
while abs(x_0 - x_1) > tol:
x_n = x_1 - fx_1 * ((x_1 - x_0) / (fx_1 - fx_0))
x_0, x_1 = x_1, x_n
fx_0, fx_1 = fx_1, fun(x_n)
return x_1
x_n = optimize.brentq(fun, x_0, x_1)
return x_n
def get_max_parab(fun, start, end, tol=0.01):
"""Successive parabolic interpolation."""
......@@ -385,7 +406,7 @@ class Orbital(object):
risetime = None
falltime = None
for guess in zcs:
horizon_mins = get_root_secant(
horizon_mins = get_root(
elevation, guess, guess + 1.0, tol=tol / 60.0)
horizon_time = utc_time + timedelta(minutes=horizon_mins)
if elev[guess] < 0:
......