[pyorbital] 01/02: Imported Upstream version 0.3.2

Antonio Valentino a_valentino-guest at moszumanska.debian.org
Sun Jun 22 08:56:47 UTC 2014


This is an automated email from the git hooks/post-receive script.

a_valentino-guest pushed a commit to branch master
in repository pyorbital.

commit f8a2e436492cdbe445efca076b60cc4eb39630e9
Author: Antonio Valentino <antonio.valentino at tiscali.it>
Date:   Sun Jun 22 08:55:45 2014 +0000

    Imported Upstream version 0.3.2
---
 .gitignore                                 |  42 ++
 .travis.yml                                |  17 +
 LICENSE.txt                                | 674 ++++++++++++++++++++++++
 MANIFEST.in                                |   5 +
 README                                     |   5 +
 doc/Makefile                               | 130 +++++
 doc/source/conf.py                         | 219 ++++++++
 doc/source/index.rst                       |  84 +++
 pyorbital/__init__.py                      |   0
 pyorbital/astronomy.py                     | 200 ++++++++
 pyorbital/geoloc.py                        | 296 +++++++++++
 pyorbital/geoloc_example.py                |  79 +++
 pyorbital/geoloc_instrument_definitions.py | 187 +++++++
 pyorbital/orbital.py                       | 789 +++++++++++++++++++++++++++++
 pyorbital/tests/SGP4-VER.TLE               | 110 ++++
 pyorbital/tests/__init__.py                |  46 ++
 pyorbital/tests/aiaa_results               | 548 ++++++++++++++++++++
 pyorbital/tests/test_aiaa.py               | 147 ++++++
 pyorbital/tests/test_astronomy.py          |  65 +++
 pyorbital/tests/test_geoloc.py             | 170 +++++++
 pyorbital/tests/test_orbital.py            | 110 ++++
 pyorbital/tests/test_tlefile.py            | 102 ++++
 pyorbital/tlefile.py                       | 162 ++++++
 pyorbital/version.py                       |  30 ++
 setup.py                                   |  48 ++
 25 files changed, 4265 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8e5bea2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,42 @@
+*.py[~cod]
+
+# emacs
+*~
+
+# C extensions
+*.so
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+__pycache__
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+nosetests.xml
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# rope
+.ropeproject
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..e312646
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+language: python
+python:
+- '2.6'
+- '2.7'
+install:
+- pip install .
+- pip install coveralls
+script: coverage run --source=pyorbital setup.py test
+after_success: coveralls
+deploy:
+  provider: pypi
+  user: Martin.Raspaud
+  password:
+    secure: P3WiHVzDAJyZmiIfSF3PhY7Xqp3P3pSHhogla8u3KOw4Sy5Ye6IWwMX1+pupAyhdXgo8ZgGT4+wOn9dBejaLEA0RGIRLMHXd1QxP9BbPD5te/k5aTpzHILx786g5R6G4yw/8s/sftQC6lJT+0jJd2OJjQJsnNUJJTG8OC2uwq3Y=
+  on:
+    tags: true
+    repo: mraspaud/pyorbital
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..367a290
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,5 @@
+include doc/Makefile
+recursive-include doc/source *
+include LICENSE.txt
+include MANIFEST.in
+include README
diff --git a/README b/README
new file mode 100644
index 0000000..50d19b8
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+This is pyorbital, python package for computing orbital parameters from tle
+files, and making diverse astronomical computations.
+
+It is part of the pytroll project:
+http://pytroll.org
\ No newline at end of file
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..a8a1618
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,130 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyorbital.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyorbital.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/pyorbital"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyorbital"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	make -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/doc/source/conf.py b/doc/source/conf.py
new file mode 100644
index 0000000..5a15784
--- /dev/null
+++ b/doc/source/conf.py
@@ -0,0 +1,219 @@
+# -*- coding: utf-8 -*-
+#
+# pyorbital documentation build configuration file, created by
+# sphinx-quickstart on Mon Oct  3 08:48:29 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, 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__, __major__, __minor__
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.coverage']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['.templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'pyorbital'
+copyright = u'2012-2014, 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 = "v" + ".".join([__major__, __minor__])
+# The full version, including alpha/beta/rc tags.
+release = __version__
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'pyorbitaldoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'pyorbital.tex', u'pyorbital Documentation',
+   u'The Pytroll crew', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'pyorbital', u'pyorbital Documentation',
+     [u'The Pytroll crew'], 1)
+]
diff --git a/doc/source/index.rst b/doc/source/index.rst
new file mode 100644
index 0000000..a330d7d
--- /dev/null
+++ b/doc/source/index.rst
@@ -0,0 +1,84 @@
+.. pyorbital documentation master file, created by
+   sphinx-quickstart on Mon Oct  3 08:48:29 2011.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Pyorbital
+=========
+
+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.
+
+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 postion
+---------------------------
+The orbital module enables computation of satellite position and velocity at a specific time:
+
+    >>> from pyorbital.orbital import Orbital
+    >>> from datetime import datetime
+    >>> orb = Orbital("noaa 18")
+    >>> now = datetime.utcnow()
+    >>> # Get normalized position and velocity of the satellite:
+    >>> orb.get_position(now)
+    ([0.57529384846822862, 0.77384005228105424, 0.59301408257897559],
+    [0.031846489698768146, 0.021287993461926374, -0.05854106186659274])
+    >>> # Get longitude, latitude and altitude of the satellite:
+    >>> orb.get_lonlatalt(now)
+    (-1.1625895579622014, 0.55402132517640568, 847.89381184656702)
+
+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`
+
diff --git a/pyorbital/__init__.py b/pyorbital/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pyorbital/astronomy.py b/pyorbital/astronomy.py
new file mode 100644
index 0000000..3f76efb
--- /dev/null
+++ b/pyorbital/astronomy.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011, 2013
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Astronomy module.
+Parts taken from http://www.geoastro.de/elevaz/basics/index.htm
+"""
+
+import datetime
+import numpy as np
+
+
+F = 1 / 298.257223563 # Earth flattening WGS-84
+A = 6378.137 # WGS84 Equatorial radius
+MFACTOR = 7.292115E-5 
+
+def jdays2000(utc_time):
+    """Get the days since year 2000.
+    """
+    return _days(utc_time - datetime.datetime(2000, 1, 1, 12, 0))
+    
+
+def jdays(utc_time):
+    """Get the julian day of *utc_time*.
+    """
+    return jdays2000(utc_time) + 2451545
+
+def _fdays(dt):
+    """Get the days (floating point) from *d_t*.
+    """
+    return (dt.days +
+            (dt.seconds +
+             dt.microseconds / (1000000.0)) / (24 * 3600.0))
+
+_vdays = np.vectorize(_fdays)
+
+def _days(dt):
+    """Get the days (floating point) from *d_t*.
+    """
+    try:
+        return _fdays(dt)
+    except AttributeError:
+        return _vdays(dt)
+
+
+def gmst(utc_time):
+    """Greenwich mean sidereal utc_time, in radians.
+    
+    As defined in the AIAA 2006 implementation:
+    http://www.celestrak.com/publications/AIAA/2006-6753/
+    """
+    ut1 = jdays2000(utc_time) / 36525.0
+    theta = 67310.54841 + ut1 * (876600 * 3600 + 8640184.812866 + ut1 *
+                                 (0.093104 - ut1 * 6.2 * 10e-6))
+    return np.deg2rad(theta / 240.0) % (2 * np.pi)
+
+
+def _lmst(utc_time, longitude):
+    """Local mean sidereal time, computed from *utc_time* and *longitude*.
+    In radians.
+    """
+    return gmst(utc_time) + longitude
+
+
+def sun_ecliptic_longitude(utc_time):
+    """Ecliptic longitude of the sun at *utc_time*.
+    """
+    jdate = jdays2000(utc_time) / 36525.0
+    # mean anomaly, rad
+    m_a = np.deg2rad(357.52910 +
+                     35999.05030*jdate -
+                     0.0001559*jdate*jdate -
+                     0.00000048*jdate*jdate*jdate)
+    # mean longitude, deg
+    l_0 = 280.46645 + 36000.76983*jdate + 0.0003032*jdate*jdate
+    d_l = ((1.914600 - 0.004817*jdate - 0.000014*jdate*jdate)*np.sin(m_a) +
+           (0.019993 - 0.000101*jdate)*np.sin(2*m_a) + 0.000290*np.sin(3*m_a))
+    # true longitude, deg
+    l__ = l_0 + d_l
+    return np.deg2rad(l__)
+
+def sun_ra_dec(utc_time):
+    """Right ascension and declination of the sun at *utc_time*.
+    """
+    jdate = jdays2000(utc_time) / 36525.0
+    eps = np.deg2rad(23.0 + 26.0/60.0 + 21.448/3600.0 -
+                     (46.8150*jdate + 0.00059*jdate*jdate -
+                      0.001813*jdate*jdate*jdate) / 3600)
+    eclon = sun_ecliptic_longitude(utc_time)
+    x__ = np.cos(eclon)
+    y__ = np.cos(eps) * np.sin(eclon)
+    z__ = np.sin(eps) * np.sin(eclon)
+    r__ = np.sqrt(1.0 - z__ * z__)
+    # sun declination
+    declination = np.arctan2(z__, r__)
+    # right ascension
+    right_ascension = 2 * np.arctan2(y__, (x__ + r__))
+    return right_ascension, declination
+
+def _local_hour_angle(utc_time, longitude, right_ascension):
+    """Hour angle at *utc_time* for the given *longitude* and
+    *right_ascension*
+    longitude in radians
+    """
+    return _lmst(utc_time, longitude) - right_ascension
+
+def get_alt_az(utc_time, lon, lat):
+    """Return sun altitude and azimuth from *utc_time*, *lon*, and *lat*.
+    lon,lat in degrees
+    What is the unit of the returned angles and heights!? FIXME!
+    """
+    lon = np.deg2rad(lon)
+    lat = np.deg2rad(lat)
+
+    ra_, dec = sun_ra_dec(utc_time)
+    h__ = _local_hour_angle(utc_time, lon, ra_)
+    return (np.arcsin(np.sin(lat)*np.sin(dec) +
+                      np.cos(lat) * np.cos(dec) * np.cos(h__)),
+            np.arctan2(-np.sin(h__), (np.cos(lat)*np.tan(dec) -
+                                    np.sin(lat)*np.cos(h__))))
+
+def cos_zen(utc_time, lon, lat):
+    """Cosine of the sun-zenith angle for *lon*, *lat* at *utc_time*.
+    utc_time: datetime.datetime instance of the UTC time
+    lon and lat in degrees.
+    """
+    lon = np.deg2rad(lon)
+    lat = np.deg2rad(lat)
+
+    r_a, dec = sun_ra_dec(utc_time)
+    h__ = _local_hour_angle(utc_time, lon, r_a)
+    return (np.sin(lat)*np.sin(dec) + np.cos(lat) * np.cos(dec) * np.cos(h__))
+
+def sun_zenith_angle(utc_time, lon, lat):
+    """Sun-zenith angle for *lon*, *lat* at *utc_time*.
+    lon,lat in degrees.
+    The angle returned is given in degrees
+    """
+    return np.rad2deg(np.arccos(cos_zen(utc_time, lon, lat)))
+
+def sun_earth_distance_correction(utc_time):
+    """Calculate the sun earth distance correction, relative to 1 AU.
+    """
+    year = 365.256363004
+    # This is computed from
+    # http://curious.astro.cornell.edu/question.php?number=582
+    # AU = 149597870700.0
+    # a = 149598261000.0
+    # theta = (jdays2000(utc_time) - 2) * (2 * np.pi) / year
+    # e = 0.01671123
+    # r = a*(1-e*e)/(1+e * np.cos(theta))
+    # corr_me = (r / AU) ** 2
+
+    # from known software.
+    corr = 1 - 0.0334 * np.cos(2 * np.pi * (jdays2000(utc_time) - 2) / year) 
+
+    return corr
+
+def observer_position(time, lon, lat, alt):
+    """Calculate observer ECI position.
+
+    http://celestrak.com/columns/v02n03/
+    """
+    
+    lon = np.deg2rad(lon)
+    lat = np.deg2rad(lat)
+    
+    theta = (gmst(time) + lon) % (2 * np.pi)
+    c = 1 / np.sqrt(1 + F * (F - 2) * np.sin(lat)**2)
+    sq = c * (1 - F)**2
+
+    achcp = (A * c + alt) * np.cos(lat)
+    x = achcp * np.cos(theta)  # kilometers
+    y = achcp * np.sin(theta)
+    z = (A * sq + alt) * np.sin(lat)
+
+    vx = -MFACTOR*y  # kilometers/second
+    vy = MFACTOR*x
+    vz = 0
+
+    return (x, y, z), (vx, vy, vz)
+    
diff --git a/pyorbital/geoloc.py b/pyorbital/geoloc.py
new file mode 100644
index 0000000..c543e6a
--- /dev/null
+++ b/pyorbital/geoloc.py
@@ -0,0 +1,296 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011, 2012, 2013, 2014.
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Module to compute geolocalization of a satellite scene.
+"""
+
+# TODO:
+# - Attitude correction
+# - project on an ellipsoid instead of a sphere
+# - optimize !!!
+# - test !!!
+
+import numpy as np
+from numpy import cos, sin, sqrt
+from datetime import timedelta
+from pyorbital.orbital import Orbital
+
+a = 6378.137 # km
+b = 6356.75231414 # km, GRS80
+#b = 6356.752314245 # km, WGS84
+
+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)
+
+    geod_lat = geoc_lat
+    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)
+        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*.
+    """
+    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)
+
+    return np.vstack([nx_, ny_, nz_])
+    
+
+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
+    talk about scanlines of course. *times* is the time of viewing of each
+    angle relative to the start of the scanning, so it should have the same
+    size as the *fovs*. *attitude* is the attitude correction to apply.
+    """
+
+    def __init__(self,
+                 fovs,
+                 times,
+                 attitude=(0, 0, 0)):
+        self.fovs = np.array(fovs)
+        self._times = np.array(times)
+        self.attitude = attitude
+
+    def vectors(self, pos, vel, roll=0.0, pitch=0.0, yaw=0.0):
+        """Get unit vectors pointing to the different pixels.
+
+        *pos* and *vel* are column vectors, or matrices of column
+        vectors. Returns vectors as stacked rows.
+        """
+        # TODO: yaw steering mode !
+        
+        
+        # Fake nadir: This is the intersection point between the satellite
+        # looking down at the centre of the ellipsoid and the surface of the
+        # ellipsoid. Nadir on the other hand is the point which vertical goes
+        # through the satellite...
+        #nadir = -pos / vnorm(pos)
+
+        nadir = subpoint(-pos)
+        nadir /= vnorm(nadir)
+        
+        # x is along track (roll)
+        x = vel / vnorm(vel)
+
+        # y is cross track (pitch)
+        y = np.cross(nadir, vel, 0, 0, 0)
+        y /= vnorm(y)
+
+        # rotate first around x
+        x_rotated = qrotate(nadir, x, self.fovs[:, 0] + roll)
+        # then around y
+        xy_rotated = qrotate(x_rotated, y, self.fovs[:, 1] + pitch)
+        # then around z
+        return qrotate(xy_rotated, nadir, yaw)
+
+    def times(self, start_of_scan):
+        tds = [timedelta(seconds=i) for i in self._times]
+        return np.array(tds) + start_of_scan
+
+class Quaternion(object):
+
+    def __init__(self, scalar, vector):
+        self.__x, self.__y, self.__z = vector
+        self.__w = scalar
+
+    def rotation_matrix(self):
+        x, y, z, w = self.__x, self.__y, self.__z, self.__w
+        zero = np.zeros_like(x)
+        return np.array(
+            ((w**2 + x**2 - y**2 - z**2,
+              2*x*y + 2*z*w,
+              2*x*z - 2*y*w,
+              zero),
+             (2*x*y - 2*z*w,
+              w**2 - x**2 + y**2 - z**2,
+              2*y*z + 2*x*w,
+              zero),
+             (2*x*z + 2*y*w,
+              2*y*z - 2*x*w,
+              w**2 - x**2 - y**2 + z**2,
+              zero),
+             (zero, zero, zero, w**2 + x**2 + y**2 + z**2)))
+
+def qrotate(vector, axis, angle):
+    """Rotate *vector* around *axis* by *angle* (in radians).
+
+    *vector* is a matrix of column vectors, as is *axis*.
+    This function uses quaternion rotation.
+    """
+    n_axis = axis / vnorm(axis)
+    sin_angle = np.expand_dims(sin(angle/2), 0)
+    if np.rank(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__)
+    return np.einsum("kj, ikj->ij",
+                     vector,
+                     q__.rotation_matrix()[:3, :3])
+
+
+
+### 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 *
+
+def get_lonlatalt(pos, utc_time):
+    """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.where(lon > np.pi, lon - np.pi * 2, lon)
+    lon = np.where(lon <= -np.pi, lon + np.pi *2, lon)
+
+    r = np.sqrt(pos_x ** 2 + pos_y ** 2)
+    lat = np.arctan2(pos_z, r)
+    e2 = F * (2 - F)
+
+    while True:
+        lat2 = lat
+        c = 1/(np.sqrt(1 - e2 * (np.sin(lat2) ** 2)))
+        lat = np.arctan2(pos_z + c * e2 *np.sin(lat2), r)
+        if np.all(abs(lat - lat2) < 1e-10):
+            break
+    alt = r / np.cos(lat)- c
+    alt *= A
+    return np.rad2deg(lon), np.rad2deg(lat), alt
+
+### END OF DIRTY STUFF
+def compute_pixels((tle1, tle2), sgeom, times, rpy=(0.0, 0.0, 0.0)):
+    """Compute cartesian coordinates of the pixels in instrument scan.
+    """
+    orb = Orbital("mysatellite", line1=tle1, line2=tle2)
+
+    # get position and velocity for each time of each pixel
+    pos, vel = orb.get_position(times, normalize=False)
+
+    # now, get the vectors pointing to each pixel
+    vectors = sgeom.vectors(pos, vel, *rpy)
+
+    ## compute intersection of lines (directed by vectors and passing through
+    ## (0, 0, 0)) and ellipsoid. Derived from:
+    ## http://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection
+    
+
+    # do the computation between line and ellipsoid (WGS 84)
+    # NB: AAPP uses GRS 80...
+    centre = -pos
+    a__ = 6378.137 # km
+    #b__ = 6356.75231414 # km, GRS80
+    b__ = 6356.752314245 # km, WGS84
+    radius = np.array([[1/a__, 1/a__, 1/b__]]).T
+    xr_ = vectors * radius
+    cr_ = centre * radius
+    ldotc = np.einsum("ij,ij->j", xr_, cr_)
+    lsq = np.einsum("ij,ij->j", xr_, xr_)
+    csq = np.einsum("ij,ij->j", cr_, cr_)
+
+    d1_ = (ldotc - np.sqrt(ldotc ** 2 - csq * lsq + lsq)) / lsq
+
+
+    # return the actual pixel positions
+    return vectors * d1_ - centre
+
+    
+def norm(v):
+    return np.sqrt(np.dot(v, v.conj()))
+
+def mnorm(m, axis=None):
+    """norm of a matrix of vectors stacked along the *axis* dimension.
+    """
+    if axis is None:
+        axis = np.rank(m) - 1
+    return np.sqrt((m**2).sum(axis))
+
+def vnorm(m):
+    """norms of a matrix of column vectors.
+    """
+    return np.sqrt((m**2).sum(0))
+def hnorm(m):
+    """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
+    #2 28654  99.0096 235.8581 0014859 135.4286 224.8087 14.11526826329313
+    
+    
+    noaa18_tle1 = "1 28654U 05018A   11284.35271227  .00000478  00000-0  28778-3 0  9246"
+    noaa18_tle2 = "2 28654  99.0096 235.8581 0014859 135.4286 224.8087 14.11526826329313"
+
+    from datetime import datetime
+    t = datetime(2011, 10, 12, 13, 45)
+
+    ## edge and centre of an avhrr scanline
+    #sgeom = ScanGeometry([(-0.9664123687741623, 0),
+    #                      (0, 0)],
+    #                     [0, 0.0, ])
+    #print compute_pixels((noaa18_tle1, noaa18_tle2), sgeom, t)
+
+
+    ## avhrr swath
+    scanline_nb = 1
+
+    # building the avhrr angles, 2048 pixels from +55.37 to -55.37 degrees
+    avhrr = np.vstack(((np.arange(2048) - 1023.5) / 1024 * np.deg2rad(-55.37),
+                       np.zeros((2048,)))).transpose()
+    avhrr = np.tile(avhrr, [scanline_nb, 1])
+    # building the corresponding times array
+    offset = np.arange(scanline_nb) * 0.1667
+    times = (np.tile(np.arange(2048) * 0.000025 + 0.0025415, [scanline_nb, 1])
+             + np.expand_dims(offset, 1))
+    # build the scan geometry object
+    sgeom = ScanGeometry(avhrr, times.ravel())
+
+    # print the lonlats for the pixel positions
+    s_times = sgeom.times(t)
+    pixels_pos = compute_pixels((noaa18_tle1, noaa18_tle2), sgeom, s_times)
+    print get_lonlatalt(pixels_pos, s_times)
diff --git a/pyorbital/geoloc_example.py b/pyorbital/geoloc_example.py
new file mode 100644
index 0000000..1200374
--- /dev/null
+++ b/pyorbital/geoloc_example.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2013 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Simple usage for geoloc.
+"""
+
+import numpy as np
+from datetime import datetime
+from pyorbital.geoloc import ScanGeometry, compute_pixels, get_lonlatalt
+
+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"
+
+t = datetime(2012, 12, 12, 4, 16, 1, 575000)
+
+scanline_nb = 351
+
+# we take only every 40th point for plotting clarity
+scan_points = np.arange(24, 2048, 40)
+
+
+# build the avhrr instrument (scan angles)
+avhrr = np.vstack(((scan_points - 1023.5) / 1024 * np.deg2rad(-55.37),
+                   np.zeros((len(scan_points),)))).transpose()
+avhrr = np.tile(avhrr, [scanline_nb, 1])
+
+# building the corresponding times array
+offset = np.arange(scanline_nb) * 0.1666667
+times = (np.tile(scan_points * 0.000025 + 0.0025415, [scanline_nb, 1])
+         + np.expand_dims(offset, 1))
+
+# build the scan geometry object
+sgeom = ScanGeometry(avhrr, times.ravel())
+
+# roll, pitch, yaw in radians
+rpy = (0, 0, 0)
+
+# print the lonlats for the pixel positions
+s_times = sgeom.times(t)
+pixels_pos = compute_pixels((tle1, tle2), sgeom, s_times, rpy)
+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')
+
+
+# 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)
+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)
+
+plt.show()
diff --git a/pyorbital/geoloc_instrument_definitions.py b/pyorbital/geoloc_instrument_definitions.py
new file mode 100644
index 0000000..c7070c4
--- /dev/null
+++ b/pyorbital/geoloc_instrument_definitions.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2013, 2014 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at smhi.se>
+#   Mikhail Itkin <itkin.m at gmail.com>
+
+# 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/>.
+
+"""Some instrument definitions to use with geoloc.
+
+To define an instrument, one must first define the scan angles (in radians)
+around x (along-track vector) and y (cross-track vector). the y scan angles are
+just 0 in the case of scanline based instruments (like avhrr), but can be
+different if the instrument is forward and/or backward scanning (e.g. viirs or
+modis).
+
+For the instrument to be defined completely, one must also provide the
+observation times (in seconds, respective to the nominal scan time) for the
+different pixels.
+
+Both scan angles and scan times are then combined into a ScanGeometry object.
+"""
+
+import numpy as np
+from pyorbital.geoloc import ScanGeometry
+
+# number of instrument scans to use.
+scans_nb = 10
+
+################################################################
+#
+#   AVHRR
+#
+################################################################
+
+def avhrr(scans_nb, scan_points, scan_angle=55.37, decimate=1):
+    """Definition of the avhrr instrument.
+
+    Source: NOAA KLM User's Guide, Appendix J
+    http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/j/app-j.htm
+    """
+    # build the avhrr instrument (scan angles)
+    avhrr_inst = np.vstack(((scan_points / 1023.5 - 1)
+                            * np.deg2rad(-scan_angle),
+                            np.zeros((len(scan_points),)))).transpose()
+    avhrr_inst = np.tile(avhrr_inst, [scans_nb, 1])
+
+    # building the corresponding times array
+    offset = np.arange(scans_nb) * decimate / 6.0
+    #times = (np.tile(scan_points * 0.000025 + 0.0025415, [scans_nb, 1])
+    #         + np.expand_dims(offset, 1))
+    times = (np.tile(scan_points * 0.000025, [scans_nb, 1])
+             + np.expand_dims(offset, 1))
+
+    return ScanGeometry(avhrr_inst, times.ravel())
+
+################################################################
+#### avhrr, all pixels
+
+# we take all pixels
+scan_points = np.arange(2048)
+
+# build the scan geometry object
+avhrr_all_geom = avhrr(scans_nb, scan_points)
+
+################################################################
+#### avhrr, edge pixels
+
+# we take only edge pixels
+scan_points = np.array([0, 2047])
+
+
+# build the scan geometry object
+avhrr_edge_geom = avhrr(scans_nb, scan_points)
+
+################################################################
+#### avhrr, every 40th pixel from the 24th (aapp style)
+
+# we take only every 40th pixel
+scan_points = np.arange(24, 2048, 40)
+
+# build the scan geometry object
+avhrr_40_geom = avhrr(scans_nb, scan_points)
+
+################################################################
+#
+#   VIIRS
+#
+################################################################
+
+def viirs(scans_nb, scan_indices=slice(0, None)):
+    """Describe VIIRS instrument geometry, I-band.
+
+    """
+
+    entire_width = np.arange(6400)
+    scan_points = entire_width[scan_indices]
+    
+    across_track = (scan_points / 3199.5 - 1) * np.deg2rad(-55.84)
+    y_max_angle = np.arctan2(11.87/2, 824.0)
+    along_track = np.array([-y_max_angle, 0, y_max_angle])
+
+    scan_pixels = len(scan_points)
+
+    scan = np.vstack((np.tile(across_track, scan_pixels),
+                      np.repeat(along_track, 6400))).T
+    
+    npp = np.tile(scan, [scans_nb, 1])
+    
+    # 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
+
+    # the individual times per pixel are probably wrong, unless the scanning
+    # behaves the same as for AVHRR, The VIIRS sensor rotates to allow internal
+    # calibration before each scanline. This would imply that the scanline
+    # 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, [scans_nb, scan_pixels])
+             + np.expand_dims(offset, 1))
+
+    # build the scan geometry object
+    return ScanGeometry(npp, times.ravel())
+
+
+################################################################
+#
+#   AMSU-A
+#
+################################################################
+
+def amsua(scans_nb, edges_only=False):
+    """ Describe AMSU-A instrument geometry
+    
+    Parameters:
+       scans_nb | int -  number of scan lines
+     
+     Keywords:
+     * edges_only - use only edge pixels
+
+    Returns:
+       pyorbital.geoloc.ScanGeometry object
+    
+    """
+
+    scan_len  = 30 # 30 samples per scan
+    scan_rate = 8 # single scan, seconds
+    scan_angle = -48.3 # swath, degrees
+    sampling_interval = 0.2 # single view, seconds
+    sync_time = 0.00355 # delay before the actual scan starts
+
+    if edges_only:
+        scan_points = np.array([0, scan_len - 1])
+    else:
+        scan_points = np.arange(0, scan_len)
+
+    # build the instrument (scan angles)
+    samples = np.vstack(((scan_points / (scan_len*0.5-0.5) - 1)
+                         * np.deg2rad(scan_angle),
+                         np.zeros((len(scan_points),)))).transpose()
+    samples = np.tile(samples, [scans_nb, 1])
+
+    # building the corresponding times array
+    offset = np.arange(scans_nb) * scan_rate
+    times = (np.tile(scan_points * sampling_interval + sync_time, [scans_nb, 1])
+	         + np.expand_dims(offset, 1))
+
+    # build the scan geometry object
+    return ScanGeometry(samples, times.ravel())
diff --git a/pyorbital/orbital.py b/pyorbital/orbital.py
new file mode 100644
index 0000000..5409579
--- /dev/null
+++ b/pyorbital/orbital.py
@@ -0,0 +1,789 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011, 2012, 2013, 2014.
+
+# Author(s):
+
+#   Esben S. Nielsen <esn at dmi.dk>
+#   Adam Dybbroe <adam.dybbroe at smhi.se>
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Module for computing the orbital parameters of satellites.
+"""
+
+from datetime import datetime, timedelta
+import numpy as np
+from pyorbital import tlefile
+from pyorbital import astronomy
+import warnings
+
+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
+ECC_ALL = 1.0e-4
+
+EPS_COS = 1.5e-12
+
+NR_EPS = 1.0e-12
+
+CK2 = 5.413080e-4
+CK4 = 0.62098875e-6
+E6A = 1.0e-6
+QOMS2T = 1.88027916e-9
+S = 1.01222928
+S0 = 78.0
+XJ3 = -0.253881e-5
+XKE = 0.743669161e-1
+XKMPER = 6378.135
+XMNPDA = 1440.0
+#MFACTOR = 7.292115E-5
+AE = 1.0
+SECDAY = 8.6400E4
+
+F = 1 / 298.257223563 # Earth flattening WGS-84
+A = 6378.137 # WGS84 Equatorial radius
+
+
+SGDP4_ZERO_ECC = 0
+SGDP4_DEEP_NORM = 1
+SGDP4_NEAR_SIMP = 2
+SGDP4_NEAR_NORM = 3
+
+KS = AE * (1.0 + S0 / XKMPER)
+A3OVK2 = (-XJ3 / CK2) * AE**3
+
+class OrbitalError(Exception):
+    pass
+
+
+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
+    it is provided.
+    """
+
+    def __init__(self, satellite, tle_file=None, line1=None, line2=None):
+        satellite = satellite.upper()
+        self.satellite_name = satellite
+        self.tle = tlefile.read(satellite, tle_file=tle_file,
+                                line1=line1, line2=line2)
+        self.orbit_elements = OrbitElements(self.tle)
+        self._sgdp4 = _SGDP4(self.orbit_elements)
+
+    def __str__(self):
+        return self.satellite_name + " " + str(self.tle)
+
+    def get_last_an_time(self, utc_time):
+        """Calculate time of last ascending node relative to the
+        specified time
+        """
+
+        # Propagate backwards to ascending node
+        dt = timedelta(minutes=10)
+        t_old = utc_time
+        t_new = t_old - dt
+        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
+            t_old = t_new
+            t_new = t_old - dt
+            pos1, vel1 = self.get_position(t_new, normalize=False)
+
+        # Return if z within 1 km of an
+        if np.abs(pos0[2]) < 1:
+            return t_old
+        elif np.abs(pos1[2]) < 1:
+            return t_new
+
+        # Bisect to z within 1 km
+        while np.abs(pos1[2]) > 1:
+            pos0, vel0 = pos1, vel1
+            dt = (t_old - t_new) / 2
+            t_mid = t_old - dt
+            pos1, vel1 = self.get_position(t_mid, normalize=False)
+            if pos1[2] > 0:
+                t_old = t_mid
+            else:
+                t_new = t_mid
+
+        return t_mid
+
+    def get_position(self, utc_time, normalize=True):
+        """Get the cartesian position and velocity from the satellite.
+        """
+
+        kep = self._sgdp4.propagate(utc_time)
+        pos, vel = kep2xyz(kep)
+
+        if normalize:
+            pos /= XKMPER
+            vel /= XKMPER * XMNPDA / SECDAY
+
+        return pos, vel
+
+
+    def get_lonlatalt(self, utc_time):
+        """Calculate sublon, sublat and altitude of satellite.
+        http://celestrak.com/columns/v02n03/
+        """
+        (pos_x, pos_y, pos_z), (vel_x, vel_y, vel_z) = self.get_position(utc_time, normalize=True)
+
+        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)
+
+        r = np.sqrt(pos_x ** 2 + pos_y ** 2)
+        lat = np.arctan2(pos_z, r)
+        e2 = F * (2 - F)
+        while True:
+            lat2 = lat
+            c = 1/(np.sqrt(1 - e2 * (np.sin(lat2) ** 2)))
+            lat = np.arctan2(pos_z + c * e2 *np.sin(lat2), r)
+            if np.all(abs(lat - lat2) < 1e-10):
+                break
+        alt = r / np.cos(lat)- c;
+        alt *= A
+        return np.rad2deg(lon), np.rad2deg(lat), alt
+
+    def find_aos(self, utc_time, lon, lat):
+        pass
+
+    def find_aol(self, utc_time, lon, lat):
+        pass
+
+    def get_observer_look(self, utc_time, lon, lat, alt):
+        """Calculate observers look angle to a satellite.
+        http://celestrak.com/columns/v02n02/
+
+        utc_time: Observation time (datetime object)
+        lon: Longitude of observer position on ground
+        lat: Latitude of observer position on ground
+        alt: Altitude above sea-level (geoid) of observer position on ground
+
+        Return: (Azimuth, Elevation)
+        """
+        (pos_x, pos_y, pos_z), (vel_x, vel_y, vel_z) = self.get_position(utc_time, normalize=False)
+        (opos_x, opos_y, opos_z), (ovel_x, ovel_y, ovel_z) = \
+                                    astronomy.observer_position(utc_time, lon, lat, alt)
+
+        lon = np.deg2rad(lon)
+        lat = np.deg2rad(lat)
+
+        theta = (astronomy.gmst(utc_time) + lon) % (2 * np.pi)
+
+        rx = pos_x - opos_x
+        ry = pos_y - opos_y
+        rz = pos_z - opos_z
+
+        sin_lat = np.sin(lat)
+        cos_lat = np.cos(lat)
+        sin_theta = np.sin(theta)
+        cos_theta = np.cos(theta)
+
+        top_s = sin_lat * cos_theta * rx + sin_lat * sin_theta * ry - cos_lat * rz
+        top_e = -sin_theta * rx + cos_theta * ry
+        top_z = cos_lat * cos_theta * rx + cos_lat * sin_theta * ry + sin_lat * rz
+
+        az_ = np.arctan(-top_e / top_s)
+
+        az_ = np.where(top_s > 0, az_ + np.pi, az_)
+        az_ = np.where(az_ < 0, az_ + 2 * np.pi, az_)
+
+        rg_ = np.sqrt(rx * rx + ry * ry + rz * rz)
+        el_ = np.arcsin(top_z / rg_)
+
+        return np.rad2deg(az_), np.rad2deg(el_)
+
+    def get_orbit_number(self, utc_time, tbus_style=False):
+        """Calculate orbit number at specified time.
+        Optionally use TBUS-style orbit numbering (TLE orbit number + 1)
+        """
+        try:
+            dt = astronomy._days(utc_time - self.orbit_elements.an_time)
+            orbit_period = astronomy._days(self.orbit_elements.an_period)
+        except AttributeError:
+            pos_epoch, vel_epoch = self.get_position(self.tle.epoch,
+                                                 normalize=False)
+            if np.abs(pos_epoch[2]) > 1 or not vel_epoch[2] > 0:
+                # Epoch not at ascending node
+                self.orbit_elements.an_time = self.get_last_an_time(self.tle.epoch)
+            else:
+                # Epoch at ascending node (z < 1 km) and positive v_z
+                self.orbit_elements.an_time = self.tle.epoch
+
+            self.orbit_elements.an_period = self.orbit_elements.an_time - \
+                                            self.get_last_an_time(self.orbit_elements.an_time
+                                                                  - timedelta(minutes=10))
+
+            dt = astronomy._days(utc_time - self.orbit_elements.an_time)
+            orbit_period = astronomy._days(self.orbit_elements.an_period)
+
+
+        orbit = int(self.tle.orbit + dt / orbit_period +
+                 self.tle.mean_motion_derivative * dt**2 +
+                 self.tle.mean_motion_sec_derivative * dt**3)
+
+        if tbus_style:
+            orbit += 1
+        return orbit
+
+    def get_next_passes(self, utc_time, length, lon, lat, alt, tol=0.001):
+        """Calculate passes for the next hours for a given start time and a
+        given observer.
+
+        Original by Martin.
+
+        utc_time: Observation time (datetime object)
+        length: Number of hours to find passes (int)
+        lon: Longitude of observer position on ground (float)
+        lat: Latitude of observer position on ground (float)
+        alt: Altitude above sea-level (geoid) of observer position on ground (float)
+        tol: precision of the result in seconds
+
+        Return: [(rise-time, fall-time, max-elevation-time), ...]
+        """
+
+        def elevation(minutes):
+            """elevation
+            """
+            return self.get_observer_look(utc_time +
+                                          timedelta(minutes=minutes),
+                                          lon, lat, alt)[1]
+        def elevation_inv(minutes):
+            """inverse of elevation
+            """
+            return -elevation(minutes)
+
+        def get_root_secant(fun, start, end, tol=0.01):
+            """Secant method
+            """
+            x_0 = end
+            x_1 = start
+            fx_0 = fun(end)
+            fx_1 = fun(start)
+            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
+
+        def get_max_parab(fun, start, end, tol=0.01):
+            """Successive parabolic interpolation
+            """
+
+            a = start
+            c = end
+            b = (a + c) / 2.0
+            x = b
+
+            f_a = fun(a)
+            f_b = fun(b)
+            f_c = fun(c)
+
+            while abs(c - a) > tol:
+                x = b - 0.5 * (((b - a) ** 2 * (f_b - f_c)
+                                - (b - c) ** 2 * (f_b - f_a)) /
+                               ((b - a) * (f_b - f_c)  - (b - c) * (f_b - f_a)))
+                f_x = fun(x)
+                if x > b:
+                    a, b, c = b, x, c
+                    f_a, f_b, f_c = f_b, f_x, f_c
+                else:
+                    a, b, c = a, x, b
+                    f_a, f_b, f_c = f_a, f_x, f_b
+
+            return x
+
+        times = utc_time + np.array([timedelta(minutes=minutes)
+                                    for minutes in range(length * 60)])
+        elev = self.get_observer_look(times, lon, lat, alt)[1]
+        zcs = np.where(np.diff(np.sign(elev)))[0]
+
+        res = []
+        risetime = None
+        falltime = None
+        for guess in zcs:
+            horizon_mins = get_root_secant(elevation, guess, guess + 1.0, tol=tol/60.0)
+            horizon_time = utc_time + timedelta(minutes=horizon_mins)
+            if elev[guess] < 0:
+                risetime = horizon_time
+                risemins = horizon_mins
+                falltime = None
+            else:
+                falltime = horizon_time
+                fallmins = horizon_mins
+                if risetime:
+                    middle = (risemins + fallmins) / 2.0
+                    highest = utc_time + \
+                        timedelta(minutes=get_max_parab(
+                        elevation_inv,
+                        middle - 0.1, middle + 0.1,
+                        tol=tol/60.0
+                        ))
+                    res += [(risetime, falltime, highest)]
+                risetime = None
+        return res
+
+    def _get_time_at_horizon(self, utc_time, obslon, obslat, **kwargs):
+        """Get the time closest in time to *utc_time* when the
+        satellite is at the horizon relative to the position of an observer on
+        ground (altitude = 0)
+
+        Note: This is considered deprecated and it's functionality is currently
+        replaced by 'get_next_passes'.
+        """
+        warnings.warn("_get_time_at_horizon is replaced with get_next_passes",
+                      DeprecationWarning)
+        if "precision" in kwargs:
+            precision = kwargs['precision']
+        else:
+            precision = timedelta(seconds=0.001)
+        if "max_iterations" in kwargs:
+            nmax_iter = kwargs["max_iterations"]
+        else:
+            nmax_iter = 100
+
+        sec_step = 0.5
+        t_step = timedelta(seconds=sec_step/2.0)
+
+        # Local derivative:
+        def fprime(timex):
+            el0 = self.get_observer_look(timex - t_step,
+                                         obslon, obslat, 0.0)[1]
+            el1 = self.get_observer_look(timex + t_step,
+                                         obslon, obslat, 0.0)[1]
+            return el0, (abs(el1) - abs(el0)) / sec_step
+
+        tx0 = utc_time - timedelta(seconds=1.0)
+        tx1 = utc_time
+        idx = 0
+        #eps = 500.
+        eps = 100.
+        while abs(tx1 - tx0) > precision and idx < nmax_iter:
+            tx0 = tx1
+            fpr = fprime(tx0)
+            # When the elevation is high the scale is high, and when
+            # the elevation is low the scale is low
+            #var_scale = np.abs(np.sin(fpr[0] * np.pi/180.))
+            #var_scale = np.sqrt(var_scale)
+            var_scale = np.abs(fpr[0])
+            tx1 = tx0 - timedelta(seconds = (eps * var_scale * fpr[1]))
+            idx = idx + 1
+            #print idx, tx0, tx1, var_scale, fpr
+            if abs(tx1 - utc_time) < precision and idx < 2:
+                tx1 = tx1 + timedelta(seconds=1.0)
+
+        if abs(tx1 - tx0) <= precision and idx < nmax_iter:
+            return tx1
+        else:
+            return None
+
+class OrbitElements(object):
+    """Class holding the orbital elements.
+    """
+
+    def __init__(self, tle):
+        self.epoch = tle.epoch
+        self.excentricity = tle.excentricity
+        self.inclination = np.deg2rad(tle.inclination)
+        self.right_ascension = np.deg2rad(tle.right_ascension)
+        self.arg_perigee = np.deg2rad(tle.arg_perigee)
+        self.mean_anomaly = np.deg2rad(tle.mean_anomaly)
+
+        self.mean_motion = tle.mean_motion * (np.pi * 2 / XMNPDA)
+        self.mean_motion_derivative = tle.mean_motion_derivative * np.pi * 2 / XMNPDA ** 2
+        self.mean_motion_sec_derivative = tle.mean_motion_sec_derivative * np.pi * 2 / XMNPDA ** 3
+        self.bstar = tle.bstar * AE
+
+        n_0 = self.mean_motion
+        k_e = XKE
+        k_2 = CK2
+        i_0 = self.inclination
+        e_0 = self.excentricity
+
+        a_1 = (k_e / n_0) ** (2.0/3)
+        delta_1 = ((3/2.0) * (k_2 / a_1**2) * ((3 * np.cos(i_0)**2 - 1) /
+                                              (1 - e_0**2)**(2.0/3)))
+
+        a_0 = a_1 * (1 - delta_1/3 - delta_1**2 - (134.0/81) * delta_1**3)
+
+        delta_0 = ((3/2.0) * (k_2 / a_0**2) * ((3 * np.cos(i_0)**2 - 1) /
+                                              (1 - e_0**2)**(2.0/3)))
+
+        # original mean motion
+        n_0pp = n_0 / (1 + delta_0)
+        self.original_mean_motion = n_0pp
+
+        # semi major axis
+        a_0pp = a_0 / (1 - delta_0)
+        self.semi_major_axis = a_0pp
+
+        self.period = np.pi * 2 / n_0pp
+
+        self.perigee = (a_0pp * (1 - e_0) / AE - AE) * XKMPER
+
+        self.right_ascension_lon = (self.right_ascension
+                                           - astronomy.gmst(self.epoch))
+
+        if self.right_ascension_lon > np.pi:
+            self.right_ascension_lon -= 2 * np.pi
+
+
+class _SGDP4(object):
+    """Class for the SGDP4 computations.
+    """
+
+    def __init__(self, orbit_elements):
+        self.mode = None
+
+        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
+        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
+
+        if not(0 < self.eo < ECC_LIMIT_HIGH):
+            raise OrbitalError('Eccentricity out of range: %e' % self.eo)
+        elif not((0.0035 * 2 * np.pi / XMNPDA) < self.xn_0 < (18 * 2 * np.pi / XMNPDA)):
+            raise OrbitalError('Mean motion out of range: %e' % self.xn_0)
+        elif not(0 < self.xincl < np.pi):
+            raise OrbitalError('Inclination out of range: %e' % self.xincl)
+
+        if self.eo < 0:
+            self.mode = self.SGDP4_ZERO_ECC
+            return
+
+        self.cosIO = np.cos(self.xincl)
+        self.sinIO = np.sin(self.xincl)
+        theta2 = self.cosIO**2
+        theta4 = theta2 ** 2
+        self.x3thm1 = 3.0 * theta2 - 1.0
+        self.x1mth2 = 1.0 - theta2
+        self.x7thm1 = 7.0 * theta2 - 1.0
+
+        a1 = (XKE / self.xn_0) ** (2. / 3)
+        betao2 = 1.0 - self.eo**2
+        betao = np.sqrt(betao2)
+        temp0 = 1.5 * CK2 * self.x3thm1 / (betao * betao2)
+        del1 = temp0 / (a1**2)
+        a0 = a1 * (1.0 - del1 * (1.0 / 3.0 + del1 * (1.0 + del1 * 134.0 / 81.0)))
+        del0 = temp0 / (a0**2)
+        self.xnodp = self.xn_0 / (1.0 + del0)
+        self.aodp = (a0 / (1.0 - del0))
+        self.perigee = (self.aodp * (1.0 - self.eo) - AE) * XKMPER
+        self.apogee = (self.aodp * (1.0 + self.eo) - AE) * XKMPER
+        self.period = (2 * np.pi * 1440.0 / XMNPDA) / self.xnodp
+
+        if self.period >= 225:
+            # Deep-Space model
+            self.mode = SGDP4_DEEP_NORM
+        elif self.perigee < 220:
+            # Near-space, simplified equations
+            self.mode = SGDP4_NEAR_SIMP
+        else:
+            # Near-space, normal equations
+            self.mode = SGDP4_NEAR_NORM
+
+        if self.perigee < 156:
+            s4 = self.perigee - 78
+            if s4 < 20:
+                s4 = 20
+
+            qoms24 = ((120 - s4) * (AE / XKMPER))**4
+            s4 = (s4 / XKMPER + AE)
+        else:
+            s4 = KS
+            qoms24 = QOMS2T
+
+        pinvsq = 1.0 / (self.aodp**2 * betao2**2)
+        tsi = 1.0 / (self.aodp - s4)
+        self.eta = self.aodp * self.eo * tsi
+        etasq = self.eta**2
+        eeta = self.eo * self.eta
+        psisq = np.abs(1.0 - etasq)
+        coef = qoms24 * tsi**4
+        coef_1 = coef / psisq**3.5
+
+        self.c2 = (coef_1 * self.xnodp * (self.aodp *
+             (1.0 + 1.5 * etasq + eeta * (4.0 + etasq)) +
+             (0.75 * CK2) * tsi / psisq * self.x3thm1 *
+             (8.0 + 3.0 * etasq * (8.0 + etasq))))
+
+        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.c5, self.c3, self.omgcof = 0.0, 0.0, 0.0
+
+
+        if self.mode == SGDP4_NEAR_NORM:
+            self.c5 = (2.0 * coef_1 * self.aodp * betao2 *
+             (1.0 + 2.75 * (etasq + eeta) + eeta * etasq))
+            if self.eo > ECC_ALL:
+                self.c3 = coef * tsi * A3OVK2 * self.xnodp * AE * self.sinIO / self.eo
+            self.omgcof = self.bstar * self.c3 * np.cos(self.omegao)
+
+        temp1 = 3.0 * CK2 * pinvsq * self.xnodp
+        temp2 = temp1 * CK2 * pinvsq
+        temp3 = 1.25 * CK4 * pinvsq**2 * self.xnodp
+
+        self.xmdot = (self.xnodp + (0.5 * temp1 * betao * self.x3thm1 + 0.0625 *
+                temp2 * betao * (13.0 - 78.0 * theta2 +
+                137.0 * theta4)))
+
+        x1m5th = 1.0 - 5.0 * theta2
+
+        self.omgdot = (-0.5 * temp1 * x1m5th + 0.0625 * temp2 *
+                 (7.0 - 114.0 * theta2 + 395.0 * theta4) +
+                 temp3 * (3.0 - 36.0 * theta2 + 49.0 * theta4))
+
+        xhdot1 = -temp1 * self.cosIO
+        self.xnodot = (xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * theta2) +
+                 2.0 * temp3 * (3.0 - 7.0 * theta2)) * self.cosIO)
+
+        if self.eo > ECC_ALL:
+            self.xmcof = (-(2. / 3) * AE) * coef * self.bstar / eeta
+        else:
+            self.xmcof = 0.0
+
+        self.xnodcf = 3.5 * betao2 * xhdot1 * self.c1
+        self.t2cof = 1.5 * self.c1
+
+        # Check for possible divide-by-zero for X/(1+cos(xincl)) when calculating xlcof */
+    	temp0 = 1.0 + self.cosIO
+    	if np.abs(temp0) < EPS_COS:
+    	    temp0 = np.sign(temp0) * EPS_COS
+
+    	self.xlcof = 0.125 * A3OVK2 * self.sinIO * (3.0 + 5.0 * self.cosIO) / temp0
+
+        self.aycof = 0.25 * A3OVK2 * self.sinIO
+
+        self.cosXMO = np.cos(self.xmo)
+        self.sinXMO = np.sin(self.xmo)
+        self.delmo = (1.0 + self.eta * self.cosXMO)**3
+
+        if self.mode == SGDP4_NEAR_NORM:
+            c1sq = self.c1**2
+            self.d2 = 4.0 * self.aodp * tsi * c1sq
+            temp0 = self.d2 * tsi * self.c1 / 3.0
+            self.d3 = (17.0 * self.aodp + s4) * temp0
+            self.d4 = 0.5 * temp0 * self.aodp * tsi * (221.0 * self.aodp + 31.0 * s4) * self.c1
+            self.t3cof = self.d2 + 2.0 * c1sq
+            self.t4cof = 0.25 * (3.0 * self.d3 + self.c1 * (12.0 * self.d2 + 10.0 * c1sq))
+            self.t5cof = (0.2 * (3.0 * self.d4 + 12.0 * self.c1 * self.d3 + 6.0 * self.d2**2 +
+                    15.0 * c1sq * (2.0 * self.d2 + c1sq)))
+
+        elif self.mode == SGDP4_DEEP_NORM:
+            raise NotImplementedError('Deep space calculations not supported')
+
+    def propagate(self, utc_time):
+        kep = {}
+
+        ts = astronomy._days(utc_time - self.t_0) * XMNPDA
+
+        em = self.eo
+        xinc = self.xincl
+
+        xmp   = self.xmo + self.xmdot * ts
+        xnode = self.xnodeo + ts * (self.xnodot + ts * self.xnodcf)
+        omega = self.omegao + self.omgdot * ts
+
+        if self.mode == SGDP4_ZERO_ECC:
+            raise NotImplementedError('Mode SGDP4_ZERO_ECC not implemented')
+        elif self.mode == SGDP4_NEAR_SIMP:
+            raise NotImplementedError('Mode "Near-space, simplified equations"'
+                                      ' not implemented')
+        elif self.mode == SGDP4_NEAR_NORM:
+            delm  = self.xmcof * ((1.0 + self.eta * np.cos(xmp))**3 - self.delmo)
+            temp0 = ts * self.omgcof + delm
+            xmp += temp0
+            omega -= temp0
+            tempa = 1.0 - (ts * (self.c1 + ts * (self.d2 + ts * (self.d3 + ts * self.d4))))
+            tempe = self.bstar * (self.c4 * ts + self.c5 * (np.sin(xmp) - self.sinXMO))
+            templ = ts * ts * (self.t2cof + ts * (self.t3cof + ts * (self.t4cof + ts * self.t5cof)))
+            a = self.aodp * tempa**2
+            e = em - tempe
+            xl = xmp + omega + xnode + self.xnodp * templ
+
+        else:
+            raise  NotImplementedError('Deep space calculations not supported')
+
+        if np.any(a < 1):
+            raise Exception('Satellite crased at time %s', utc_time)
+        elif np.any(e < ECC_LIMIT_LOW):
+            raise ValueError('Satellite modified eccentricity to low: %e < %e'
+                             % (e, ECC_LIMIT_LOW))
+
+        e = np.where(e < ECC_EPS, ECC_EPS, e)
+        e = np.where(e > ECC_LIMIT_HIGH, ECC_LIMIT_HIGH, e)
+
+        beta2 = 1.0 - e**2
+
+        # Long period periodics
+        sinOMG = np.sin(omega)
+        cosOMG = np.cos(omega)
+
+        temp0 = 1.0 / (a * beta2)
+        axn = e * cosOMG
+        ayn = e * sinOMG + temp0 * self.aycof
+        xlt = xl + temp0 * self.xlcof * axn
+
+        elsq = axn**2 + ayn**2
+
+        if np.any(elsq >= 1):
+            raise Exception('e**2 >= 1 at %s', utc_time)
+
+        kep['ecc'] = np.sqrt(elsq)
+
+        epw = np.fmod(xlt - xnode, 2 * np.pi)
+        # needs a copy in case of an array
+        capu = np.array(epw)
+        maxnr = kep['ecc']
+        for i in range(10):
+            sinEPW = np.sin(epw)
+            cosEPW = np.cos(epw)
+
+            ecosE = axn * cosEPW + ayn * sinEPW
+            esinE = axn * sinEPW - ayn * cosEPW
+            f = capu - epw + esinE
+            if np.all(np.abs(f) < NR_EPS):
+                break
+
+            df = 1.0 - ecosE
+
+            # 1st order Newton-Raphson correction.
+            nr = f / df
+
+            # 2nd order Newton-Raphson correction.
+            nr = np.where(np.logical_and(i == 0, np.abs(nr) > 1.25 * maxnr),
+                          np.sign(nr) * maxnr,
+                          f / (df + 0.5*esinE*nr))
+            epw += nr
+
+        # Short period preliminary quantities
+        temp0 = 1.0 - elsq
+        betal = np.sqrt(temp0)
+        pl = a * temp0
+        r = a * (1.0 - ecosE)
+        invR = 1.0 / r
+        temp2 = a * invR
+        temp3 = 1.0 / (1.0 + betal)
+        cosu = temp2 * (cosEPW - axn + ayn * esinE * temp3)
+        sinu = temp2 * (sinEPW - ayn - axn * esinE * temp3)
+        u = np.arctan2(sinu, cosu)
+        sin2u = 2.0 * sinu * cosu
+        cos2u = 2.0 * cosu**2 - 1.0
+        temp0 = 1.0 / pl
+        temp1 = CK2 * temp0
+        temp2 = temp1 * temp0
+
+        # Update for short term periodics to position terms.
+
+        rk = r * (1.0 - 1.5 * temp2 * betal * self.x3thm1) + 0.5 * temp1 * self.x1mth2 * cos2u
+        uk = u - 0.25 * temp2 * self.x7thm1 * sin2u
+        xnodek = xnode + 1.5 * temp2 * self.cosIO * sin2u
+        xinck = xinc + 1.5 * temp2 * self.cosIO * self.sinIO * cos2u
+
+        if np.any(rk < 1):
+            raise Exception('Satellite crased at time %s', utc_time)
+
+        temp0 = np.sqrt(a)
+        temp2 = XKE / (a * temp0)
+        rdotk = ((XKE * temp0 * esinE * invR -temp2 * temp1 * self.x1mth2 * sin2u) *
+                 (XKMPER / AE * XMNPDA / 86400.0))
+        rfdotk = ((XKE * np.sqrt(pl) * invR + temp2 * temp1 *
+                  (self.x1mth2 * cos2u + 1.5 * self.x3thm1)) *
+                  (XKMPER / AE * XMNPDA / 86400.0))
+
+        kep['radius'] = rk * XKMPER / AE
+        kep['theta'] = uk
+        kep['eqinc'] = xinck
+        kep['ascn'] = xnodek
+        kep['argp'] = omega
+        kep['smjaxs'] = a * XKMPER / AE
+        kep['rdotk'] = rdotk
+        kep['rfdotk'] = rfdotk
+
+        return kep
+
+
+def kep2xyz(kep):
+    sinT = np.sin(kep['theta'])
+    cosT = np.cos(kep['theta'])
+    sinI = np.sin(kep['eqinc'])
+    cosI = np.cos(kep['eqinc'])
+    sinS = np.sin(kep['ascn'])
+    cosS = np.cos(kep['ascn'])
+
+    xmx = -sinS * cosI
+    xmy = cosS * cosI
+
+    ux = xmx * sinT + cosS * cosT
+    uy = xmy * sinT + sinS * cosT
+    uz = sinI * sinT
+
+    x = kep['radius'] * ux
+    y = kep['radius'] * uy
+    z = kep['radius'] * uz
+
+    vx = xmx * cosT - cosS * sinT
+    vy = xmy * cosT - sinS * sinT
+    vz = sinI * cosT
+
+    v_x = kep['rdotk'] * ux + kep['rfdotk'] * vx
+    v_y = kep['rdotk'] * uy + kep['rfdotk'] * vy
+    v_z = kep['rdotk'] * uz + kep['rfdotk'] * vz
+
+    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
+    o = Orbital(satellite="METOP-B")
+
+    t_start = datetime.now()
+    t_stop = t_start + timedelta(minutes=20)
+    t = t_start
+    while t < t_stop:
+        t += timedelta(seconds=15)
+        lon, lat, alt = o.get_lonlatalt(t)
+        lon, lat = np.rad2deg((lon, lat))
+        az, el = o.get_observer_look(t, obs_lon, obs_lat, obs_alt)
+        ob = o.get_orbit_number(t, tbus_style=True)
+        print az, el, ob
diff --git a/pyorbital/tests/SGP4-VER.TLE b/pyorbital/tests/SGP4-VER.TLE
new file mode 100644
index 0000000..cfa3133
--- /dev/null
+++ b/pyorbital/tests/SGP4-VER.TLE
@@ -0,0 +1,110 @@
+#   ------------------ Verification test cases ----------------------
+#                       # TEME example
+1 00005U 58002B   00179.78495062  .00000023  00000-0  28098-4 0  4753
+2 00005  34.2682 348.7242 1859667 331.7664  19.3264 10.82419157413667     0.00      4320.0        360.00
+#                       ## fig show lyddane fix error with gsfc ver
+1 04632U 70093B   04031.91070959 -.00000084  00000-0  10000-3 0  9955
+2 04632  11.4628 273.1101 1450506 207.6000 143.9350  1.20231981 44145  -5184.0     -4896.0        120.00
+#   DELTA 1 DEB         # near earth normal drag equation
+#                       # perigee = 377.26km, so moderate drag case
+1 06251U 62025E   06176.82412014  .00008885  00000-0  12808-3 0  3985
+2 06251  58.0579  54.0425 0030035 139.1568 221.1854 15.56387291  6774      0.0      2880.0        120.00
+#   MOLNIYA 2-14              # 12h resonant ecc in 0.65 to 0.7 range
+1 08195U 75081A   06176.33215444  .00000099  00000-0  11873-3 0   813
+2 08195  64.1586 279.0717 6877146 264.7651  20.2257  2.00491383225656      0.0      2880.0        120.00
+#   MOLNIYA 1-36              ## fig 12h resonant ecc in 0.7 to 0.715 range
+1 09880U 77021A   06176.56157475  .00000421  00000-0  10000-3 0  9814
+2 09880  64.5968 349.3786 7069051 270.0229  16.3320  2.00813614112380      0.0      2880.0        120.00
+#   SMS 1 AKM           # show the integrator problem with gsfc ver
+1 09998U 74033F   05148.79417928 -.00000112  00000-0  00000+0 0  4480
+2 09998   9.4958 313.1750 0270971 327.5225  30.8097  1.16186785 45878  -1440.0      -720.00         60.0
+#                       # Original STR#3 SDP4 test
+1 11801U          80230.29629788  .01431103  00000-0  14311-1      13
+2 11801  46.7916 230.4354 7318036  47.4722  10.4117  2.28537848    13      0.0      1440.0        360.00
+#   EUTELSAT 1-F1 (ECS1)## fig lyddane choice in GSFC at 2080 min
+1 14128U 83058A   06176.02844893 -.00000158  00000-0  10000-3 0  9627
+2 14128  11.4384  35.2134 0011562  26.4582 333.5652  0.98870114 46093      0.0      2880.0        120.00
+#   SL-6 R/B(2)         # Deep space, perigee = 82.48 (<98) for
+#                       # s4 > 20 mod
+1 16925U 86065D   06151.67415771  .02550794 -30915-6  18784-3 0  4486
+2 16925  62.0906 295.0239 5596327 245.1593  47.9690  4.88511875148616      0.0      1440.0        120.00
+#   SL-12 R/B           # Shows Lyddane choice at 1860 and 4700 min
+1 20413U 83020D   05363.79166667  .00000000  00000-0  00000+0 0  7041
+2 20413  12.3514 187.4253 7864447 196.3027 356.5478  0.24690082  7978   1440.0      4320.0        120.00
+#   MOLNIYA 1-83                # 12h resonant, ecc > 0.715 (negative BSTAR)
+1 21897U 92011A   06176.02341244 -.00001273  00000-0 -13525-3 0  3044
+2 21897  62.1749 198.0096 7421690 253.0462  20.1561  2.01269994104880      0.0      2880.0        120.00
+#   SL-6 R/B(2)         # last tle given, decayed 2006-04-04, day 94
+1 22312U 93002D   06094.46235912  .99999999  81888-5  49949-3 0  3953
+2 22312  62.1486  77.4698 0308723 267.9229  88.7392 15.95744531 98783  54.2028672   1440.0         20.00
+#   SL-6 R/B(2)         # 12h resonant ecc in the > 0.715 range
+1 22674U 93035D   06176.55909107  .00002121  00000-0  29868-3 0  6569
+2 22674  63.5035 354.4452 7541712 253.3264  18.7754  1.96679808 93877      0.0      2880.0        120.00
+#   ARIANE 44L+ R/B     # Lyddane bug at <= 70 min for atan2(),
+#                       # no quadrant fix
+1 23177U 94040C   06175.45752052  .00000386  00000-0  76590-3 0    95
+2 23177   7.0496 179.8238 7258491 296.0482   8.3061  2.25906668 97438      0.0      1440.0        120.00
+#   WIND                        # STR#3 Kepler failes past about 200 min
+1 23333U 94071A   94305.49999999 -.00172956  26967-3  10000-3 0    15
+2 23333  28.7490   2.3720 9728298  30.4360   1.3500  0.07309491    70      0.0      1600.0        120.00
+#   ARIANE 42P+3 R/B    ## fig Lyddane bug at > 280.5 min for AcTan()
+1 23599U 95029B   06171.76535463  .00085586  12891-6  12956-2 0  2905
+2 23599   6.9327   0.2849 5782022 274.4436  25.2425  4.47796565123555      0.0       720.0         20.00
+#   ITALSAT 2           # 24h resonant GEO, inclination > 3 deg
+1 24208U 96044A   06177.04061740 -.00000094  00000-0  10000-3 0  1600
+2 24208   3.8536  80.0121 0026640 311.0977  48.3000  1.00778054 36119      0.0      1440.0        120.00
+#   AMC-4               ## fig low incl, show incl shift with
+#                       ## gsfc version from 240 to 1440 min
+1 25954U 99060A   04039.68057285 -.00000108  00000-0  00000-0 0  6847
+2 25954   0.0004 243.8136 0001765  15.5294  22.7134  1.00271289 15615  -1440.0      1440.0        120.00
+#   INTELSAT 902                # negative incl at 9313 min then
+#                       # 270 deg Lyddane bug at 37606 min
+1 26900U 01039A   06106.74503247  .00000045  00000-0  10000-3 0  8290
+2 26900   0.0164 266.5378 0003319  86.1794 182.2590  1.00273847 16981   9300.00     9400.00        60.00
+#   COSMOS 1024 DEB     # 12h resonant ecc in 0.5 to 0.65 range
+1 26975U 78066F   06174.85818871  .00000620  00000-0  10000-3 0  6809
+2 26975  68.4714 236.1303 5602877 123.7484 302.5767  2.05657553 67521      0.0      2880.0        120.00
+#   CBERS 2                     # Near Earth, ecc = 8.84E-5 (< 1.0e-4)
+#                       # drop certain normal drag terms
+1 28057U 03049A   06177.78615833  .00000060  00000-0  35940-4 0  1836
+2 28057  98.4283 247.6961 0000884  88.1964 271.9322 14.35478080140550      0.0      2880.0        120.00
+#   NAVSTAR 53 (USA 175)# 12h non-resonant GPS (ecc < 0.5 ecc)
+1 28129U 03058A   06175.57071136 -.00000104  00000-0  10000-3 0   459
+2 28129  54.7298 324.8098 0048506 266.2640  93.1663  2.00562768 18443      0.0      1440.0        120.00
+#   COSMOS 2405         # Near Earth, perigee = 127.20 (< 156) s4 mod
+1 28350U 04020A   06167.21788666  .16154492  76267-5  18678-3 0  8894
+2 28350  64.9977 345.6130 0024870 260.7578  99.9590 16.47856722116490      0.0      2880.0        120.00
+#   H-2 R/B                   # Deep space, perigee = 135.75 (<156) s4 mod
+1 28623U 05006B   06177.81079184  .00637644  69054-6  96390-3 0  6000
+2 28623  28.5200 114.9834 6249053 170.2550 212.8965  3.79477162 12753      0.0      1440.0        120.00
+#   XM-3                      # 24h resonant geo, incl < 3 deg goes
+#                       # negative around 1130 min
+1 28626U 05008A   06176.46683397 -.00000205  00000-0  10000-3 0  2190
+2 28626   0.0019 286.9433 0000335  13.7918  55.6504  1.00270176  4891      0.0      1440.0        120.00
+#   MINOTAUR R/B        # Sub-orbital case - Decayed 2005-11-29
+#                       #(perigee = -51km), lost in 50 minutes
+1 28872U 05037B   05333.02012661  .25992681  00000-0  24476-3 0  1534
+2 28872  96.4736 157.9986 0303955 244.0492 110.6523 16.46015938 10708      0.0        60.0          5.00
+#   SL-14 DEB           # Last stage of decay - lost in under 420 min
+1 29141U 85108AA  06170.26783845  .99999999  00000-0  13519-0 0   718
+2 29141  82.4288 273.4882 0015848 277.2124  83.9133 15.93343074  6828      0.0       440.0         20.00
+#   SL-12 DEB           # Near Earth, perigee = 212.24 < 220
+#                       # simplified drag eq
+1 29238U 06022G   06177.28732010  .00766286  10823-4  13334-2 0   101
+2 29238  51.5595 213.7903 0202579  95.2503 267.9010 15.73823839  1061      0.0      1440.0        120.00
+#                       # Original STR#3 SGP4 test
+1 88888U          80275.98708465  .00073094  13844-3  66816-4 0    87
+2 88888  72.8435 115.9689 0086731  52.6988 110.5714 16.05824518  1058      0.0      1440.0        120.00
+#
+#                       # check error code 4
+1 33333U 05037B   05333.02012661  .25992681  00000-0  24476-3 0  1534
+2 33333  96.4736 157.9986 9950000 244.0492 110.6523  4.00004038 10708      0.0       150.0          5.00
+#                       # try and check error code 2 but this 
+1 33334U 78066F   06174.85818871  .00000620  00000-0  10000-3 0  6809
+2 33334  68.4714 236.1303 5602877 123.7484 302.5767  0.00001000 67521      0.0      1440.0         1.00
+#                       # try to check error code 3 looks like ep never goes below zero, tied close to ecc
+1 33335U 05008A   06176.46683397 -.00000205  00000-0  10000-3 0  2190
+2 33335   0.0019 286.9433 0000004  13.7918  55.6504  1.00270176  4891      0.0      1440.0         20.00
+#   SL-12 R/B           # Shows Lyddane choice at 1860 and 4700 min
+1 20413U 83020D   05363.79166667  .00000000  00000-0  00000+0 0  7041
+2 20413  12.3514 187.4253 7864447 196.3027 356.5478  0.24690082  7978  1844000     1845100          5.00
diff --git a/pyorbital/tests/__init__.py b/pyorbital/tests/__init__.py
new file mode 100644
index 0000000..fb67767
--- /dev/null
+++ b/pyorbital/tests/__init__.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2014 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""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.
+    """
+    mysuite = unittest.TestSuite()
+    # Test the documentation strings
+    #mysuite.addTests(doctest.DocTestSuite(image))
+    # Use the unittests also
+    mysuite.addTests(test_aiaa.suite())
+    mysuite.addTests(test_tlefile.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())
diff --git a/pyorbital/tests/aiaa_results b/pyorbital/tests/aiaa_results
new file mode 100644
index 0000000..c79823e
--- /dev/null
+++ b/pyorbital/tests/aiaa_results
@@ -0,0 +1,548 @@
+# Min from epoch position x km position y km position z km vel km/s vel km/s vel km/s year mon day hr min sec
+5 xx
+0.00000000 7022.46529266 -1400.08296755 0.03995155 1.893841015 6.405893759 4.534807250
+360.00000000 -7154.03120202 -3783.17682504 -3536.19412294 4.741887409 -4.151817765 -2.093935425 2000 6 28 0:50:19.733571
+720.00000000 -7134.59340119 6531.68641334 3260.27186483 -4.113793027 -2.911922039 -2.557327851 2000 6 28 6:50:19.733571
+1080.00000000 5568.53901181 4492.06992591 3863.87641983 -4.209106476 5.159719888 2.744852980 2000 6 28 12:50:19.733571
+1440.00000000 -938.55923943 -6268.18748831 -4294.02924751 7.536105209 -0.427127707 0.989878080 2000 6 28 18:50:19.733571
+1800.00000000 -9680.56121728 2802.47771354 124.10688038 -0.905874102 -4.659467970 -3.227347517 2000 6 29 0:50:19.733571
+2160.00000000 190.19796988 7746.96653614 5110.00675412 -6.112325142 1.527008184 -0.139152358 2000 6 29 6:50:19.733571
+2520.00000000 5579.55640116 -3995.61396789 -1518.82108966 4.767927483 5.123185301 4.276837355 2000 6 29 12:50:19.733571
+2880.00000000 -8650.73082219 -1914.93811525 -3007.03603443 3.067165127 -4.828384068 -2.515322836 2000 6 29 18:50:19.733571
+3240.00000000 -5429.79204164 7574.36493792 3747.39305236 -4.999442110 -1.800561422 -2.229392830 2000 6 30 0:50:19.733571
+3600.00000000 6759.04583722 2001.58198220 2783.55192533 -2.180993947 6.402085603 3.644723952 2000 6 30 6:50:19.733571
+3960.00000000 -3791.44531559 -5712.95617894 -4533.48630714 6.668817493 -2.516382327 -0.082384354 2000 6 30 12:50:19.733571
+4320.00000000 -9060.47373569 4658.70952502 813.68673153 -2.232832783 -4.110453490 -3.157345433 2000 6 30 18:50:19.733571
+4632 xx
+0.00000000 2334.11450085 -41920.44035349 -0.03867437 2.826321032 -0.065091664 0.570936053
+-5184.00000000 -29020.02587128 13819.84419063 -5713.33679183 -1.768068390 -3.235371192 -0.395206135 2004 1 28 7:27:25.308584
+-5064.00000000 -32982.56870101 -11125.54996609 -6803.28472771 0.617446996 -3.379240041 0.085954707 2004 1 28 9:27:25.308597
+-4944.00000000 -22097.68730513 -31583.13829284 -4836.34329328 2.230597499 -2.166594667 0.426443070 2004 1 28 11:27:25.308611
+-4896.00000000 -15129.94694545 -36907.74526221 -3487.56256701 2.581167187 -1.524204737 0.504805763 2004 1 28 12:15:25.308600
+6251 xx
+0.00000000 3988.31022699 5498.96657235 0.90055879 -3.290032738 2.357652820 6.496623475
+120.00000000 -3935.69800083 409.10980837 5471.33577327 -3.374784183 -6.635211043 -1.942056221 2006 6 25 21:46:43.980124
+240.00000000 -1675.12766915 -5683.30432352 -3286.21510937 5.282496925 1.508674259 -5.354872978 2006 6 25 23:46:43.980097
+360.00000000 4993.62642836 2890.54969900 -3600.40145627 0.347333429 5.707031557 5.070699638 2006 6 26 1:46:43.980111
+480.00000000 -1115.07959514 4015.11691491 5326.99727718 -5.524279443 -4.765738774 2.402255961 2006 6 26 3:46:43.980124
+600.00000000 -4329.10008198 -5176.70287935 409.65313857 2.858408303 -2.933091792 -6.509690397 2006 6 26 5:46:43.980097
+720.00000000 3692.60030028 -976.24265255 -5623.36447493 3.897257243 6.415554948 1.429112190 2006 6 26 7:46:43.980111
+840.00000000 2301.83510037 5723.92394553 2814.61514580 -5.110924966 -0.764510559 5.662120145 2006 6 26 9:46:43.980124
+960.00000000 -4990.91637950 -2303.42547880 3920.86335598 -0.993439372 -5.967458360 -4.759110856 2006 6 26 11:46:43.980097
+1080.00000000 642.27769977 -4332.89821901 -5183.31523910 5.720542579 4.216573838 -2.846576139 2006 6 26 13:46:43.980111
+1200.00000000 4719.78335752 4798.06938996 -943.58851062 -2.294860662 3.492499389 6.408334723 2006 6 26 15:46:43.980124
+1320.00000000 -3299.16993602 1576.83168320 5678.67840638 -4.460347074 -6.202025196 -0.885874586 2006 6 26 17:46:43.980097
+1440.00000000 -2777.14682335 -5663.16031708 -2462.54889123 4.915493146 0.123328992 -5.896495091 2006 6 26 19:46:43.980111
+1560.00000000 4992.31573893 1716.62356770 -4287.86065581 1.640717189 6.071570434 4.338797931 2006 6 26 21:46:43.980124
+1680.00000000 -8.22384755 4662.21521668 4905.66411857 -5.891011274 -3.593173872 3.365100460 2006 6 26 23:46:43.980097
+1800.00000000 -4966.20137963 -4379.59155037 1349.33347502 1.763172581 -3.981456387 -6.343279443 2006 6 27 1:46:43.980111
+1920.00000000 2954.49390331 -2080.65984650 -5754.75038057 4.895893306 5.858184322 0.375474825 2006 6 27 3:46:43.980124
+2040.00000000 3363.28794321 5559.55841180 1956.05542266 -4.587378863 0.591943403 6.107838605 2006 6 27 5:46:43.980097
+2160.00000000 -4856.66780070 -1107.03450192 4557.21258241 -2.304158557 -6.186437070 -3.956549542 2006 6 27 7:46:43.980111
+2280.00000000 -497.84480071 -4863.46005312 -4700.81211217 5.960065407 2.996683369 -3.767123329 2006 6 27 9:46:43.980124
+2400.00000000 5241.61936096 3910.75960683 -1857.93473952 -1.124834806 4.406213160 6.148161299 2006 6 27 11:46:43.980097
+2520.00000000 -2451.38045953 2610.60463261 5729.79022069 -5.366560525 -5.500855666 0.187958716 2006 6 27 13:46:43.980111
+2640.00000000 -3791.87520638 -5378.82851382 -1575.82737930 4.266273592 -1.199162551 -6.276154080 2006 6 27 15:46:43.980124
+2760.00000000 4730.53958356 524.05006433 -4857.29369725 2.918056288 6.135412849 3.495115636 2006 6 27 17:46:43.980097
+2880.00000000 1159.27802897 5056.60175495 4353.49418579 -5.968060341 -2.314790406 4.230722669 2006 6 27 19:46:43.980111
+8195 xx
+0.00000000 2349.89483350 -14785.93811562 0.02119378 2.721488096 -3.256811655 4.498416672
+120.00000000 15223.91713658 -17852.95881713 25280.39558224 1.079041732 0.875187372 2.485682813 2006 6 25 9:58:18.143649
+240.00000000 19752.78050009 -8600.07130962 37522.72921090 0.238105279 1.546110924 0.986410447 2006 6 25 11:58:18.143622
+360.00000000 19089.29762968 3107.89495018 39958.14661370 -0.410308034 1.640332277 -0.306873818 2006 6 25 13:58:18.143636
+480.00000000 13829.66070574 13977.39999817 32736.32082508 -1.065096849 1.279983299 -1.760166075 2006 6 25 15:58:18.143649
+600.00000000 3333.05838525 18395.31728674 12738.25031238 -1.882432221 -0.611623333 -4.039586549 2006 6 25 17:58:18.143622
+720.00000000 2622.13222207 -15125.15464924 474.51048398 2.688287199 -3.078426664 4.494979530 2006 6 25 19:58:18.143636
+840.00000000 15320.56770017 -17777.32564586 25539.53198382 1.064346229 0.892184771 2.459822414 2006 6 25 21:58:18.143649
+960.00000000 19769.70267785 -8458.65104454 37624.20130236 0.229304396 1.550363884 0.966993056 2006 6 25 23:58:18.143622
+1080.00000000 19048.56201523 3260.43223119 39923.39143967 -0.418015536 1.639346953 -0.326094840 2006 6 26 1:58:18.143636
+1200.00000000 13729.19205837 14097.70014810 32547.52799890 -1.074511043 1.270505211 -1.785099927 2006 6 26 3:58:18.143649
+1320.00000000 3148.86165643 18323.19841703 12305.75195578 -1.895271701 -0.678343847 -4.086577951 2006 6 26 5:58:18.143622
+1440.00000000 2890.80638268 -15446.43952300 948.77010176 2.654407490 -2.909344895 4.486437362 2006 6 26 7:58:18.143636
+1560.00000000 15415.98410712 -17699.90714437 25796.19644689 1.049818334 0.908822332 2.434107329 2006 6 26 9:58:18.143649
+1680.00000000 19786.00618538 -8316.74570581 37723.74539119 0.220539813 1.554518900 0.947601047 2006 6 26 11:58:18.143622
+1800.00000000 19007.28688729 3412.85948715 39886.66579255 -0.425733568 1.638276809 -0.345353807 2006 6 26 13:58:18.143636
+1920.00000000 13627.93015254 14216.95401307 32356.13706868 -1.083991976 1.260802347 -1.810193903 2006 6 26 15:58:18.143649
+2040.00000000 2963.26486560 18243.85063641 11868.25797486 -1.908015447 -0.747870342 -4.134004492 2006 6 26 17:58:18.143622
+2160.00000000 3155.85126036 -15750.70393364 1422.32496953 2.620085624 -2.748990396 4.473527039 2006 6 26 19:58:18.143636
+2280.00000000 15510.15191770 -17620.71002219 26050.43525345 1.035454678 0.925111006 2.408534465 2006 6 26 21:58:18.143649
+2400.00000000 19801.67198812 -8174.33337167 37821.38577439 0.211812700 1.558576937 0.928231880 2006 6 26 23:58:18.143622
+2520.00000000 18965.46529379 3565.19666242 39847.97510998 -0.433459945 1.637120585 -0.364653213 2006 6 27 1:58:18.143636
+2640.00000000 13525.88227400 14335.15978787 32162.13236536 -1.093537945 1.250868256 -1.835451681 2006 6 27 3:58:18.143649
+2760.00000000 2776.30574260 18156.98538451 11425.73046481 -1.920632199 -0.820370733 -4.181839232 2006 6 27 5:58:18.143622
+2880.00000000 3417.20931587 -16038.79510665 1894.74934058 2.585515864 -2.596818146 4.456882556 2006 6 27 7:58:18.143636
+9880 xx
+0.00000000 13020.06750784 -2449.07193500 1.15896030 4.247363935 1.597178501 4.956708611
+120.00000000 19190.32482476 9249.01266902 26596.71345328 -0.624960193 1.324550562 2.495697637 2006 6 25 15:28:40.058423
+240.00000000 11332.67806218 16517.99124008 38569.78482991 -1.400974747 0.710947006 0.923935636 2006 6 25 17:28:40.058396
+360.00000000 328.74217398 19554.92047380 40558.26246145 -1.593281066 0.126772913 -0.359627307 2006 6 25 19:28:40.058410
+480.00000000 -10684.90590680 18057.15728839 33158.75253886 -1.383205997 -0.582328999 -1.744412556 2006 6 25 21:28:40.058423
+600.00000000 -17069.78000550 9944.86797897 13885.91649059 0.044133354 -1.853448464 -3.815303117 2006 6 25 23:28:40.058396
+720.00000000 13725.09398980 -2180.70877090 863.29684523 3.878478111 1.656846496 4.944867241 2006 6 26 1:28:40.058410
+840.00000000 19089.63879226 9456.29670247 27026.79562883 -0.656614299 1.309112636 2.449371941 2006 6 26 3:28:40.058423
+960.00000000 11106.41248373 16627.60874079 38727.35140296 -1.409722680 0.698582526 0.891383535 2006 6 26 5:28:40.058396
+1080.00000000 72.40958621 19575.08054144 40492.12544001 -1.593394604 0.113655142 -0.390556063 2006 6 26 7:28:40.058410
+1200.00000000 -10905.89252576 17965.41205111 32850.07298244 -1.371396120 -0.601706604 -1.782817058 2006 6 26 9:28:40.058423
+1320.00000000 -17044.61207568 9635.48491849 13212.59462953 0.129244030 -1.903551430 -3.884569098 2006 6 26 11:28:40.058396
+1440.00000000 14369.90303735 -1903.85601062 1722.15319853 3.543393116 1.701687176 4.913881358 2006 6 26 13:28:40.058410
+1560.00000000 18983.96210441 9661.12233804 27448.99557732 -0.687189304 1.293808870 2.403630759 2006 6 26 15:28:40.058423
+1680.00000000 10878.79336704 16735.31433954 38879.23434264 -1.418239666 0.686235750 0.858951848 2006 6 26 17:28:40.058396
+1800.00000000 -184.03743100 19593.09371709 40420.40606889 -1.593348925 0.100448697 -0.421571993 2006 6 26 19:28:40.058410
+1920.00000000 -11125.12138631 17870.19488928 32534.21521208 -1.359116236 -0.621413776 -1.821629856 2006 6 26 21:28:40.058423
+2040.00000000 -17004.43272827 9316.53926351 12526.11883812 0.220330736 -1.955594322 -3.955058575 2006 6 26 23:28:40.058396
+2160.00000000 14960.06492693 -1620.68430805 2574.96359381 3.238634028 1.734723385 4.868880331 2006 6 27 1:28:40.058410
+2280.00000000 18873.46347257 9863.57004586 27863.46574735 -0.716736981 1.278632817 2.358448535 2006 6 27 3:28:40.058423
+2400.00000000 10649.86857581 16841.14172669 39025.48035006 -1.426527152 0.673901057 0.826632332 2006 6 27 5:28:40.058396
+2520.00000000 -440.53459323 19608.95524423 40343.10675451 -1.593138597 0.087147884 -0.452680559 2006 6 27 7:28:40.058410
+2640.00000000 -11342.45028909 17771.44223942 32211.12535721 -1.346344015 -0.641464291 -1.860864234 2006 6 27 9:28:40.058423
+2760.00000000 -16948.06005711 8987.64254880 11826.28284367 0.318007297 -2.009693492 -4.026726648 2006 6 27 11:28:40.058396
+2880.00000000 15500.53445068 -1332.90981042 3419.72315308 2.960917974 1.758331634 4.813698638 2006 6 27 13:28:40.058410
+9998 xx
+0.00000000 25532.98947267 -27244.26327953 -1.11572421 2.410283885 2.194175683 0.545888526
+-1440.00000000 -11362.18265118 -35117.55867813 -5413.62537994 3.137861261 -1.011678260 0.267510059 2005 5 27 19:03:37.089777
+-1380.00000000 309.25349929 -36960.43090143 -4198.48007670 3.292429375 -0.002166046 0.402111628 2005 5 27 20:03:37.089763
+-1320.00000000 11949.04009077 -35127.37816804 -2565.89806468 3.119942784 1.012096444 0.497284100 2005 5 27 21:03:37.089790
+-1260.00000000 22400.45329336 -29798.63236321 -677.91515122 2.638533344 1.922477736 0.542792913 2005 5 27 22:03:37.089777
+-1200.00000000 30640.84752458 -21525.02340201 1277.34808722 1.903464941 2.634294312 0.534540934 2005 5 27 23:03:37.089763
+-1140.00000000 35899.56788035 -11152.71158138 3108.72535238 0.997393045 3.079858548 0.474873291 2005 5 28 0:03:37.089790
+-1080.00000000 37732.45438600 288.18821054 4643.87587495 0.016652226 3.225184410 0.371669746 2005 5 28 1:03:37.089777
+-1020.00000000 36045.92961699 11706.61816230 5746.32646574 -0.942409065 3.069888941 0.236662980 2005 5 28 2:03:37.089763
+-960.00000000 31076.77273609 22063.44379776 6325.93403705 -1.794027976 2.642072476 0.083556127 2005 5 28 3:03:37.089790
+-900.00000000 23341.26015320 30460.88002531 6342.91707895 -2.469409743 1.990861658 -0.073612096 2005 5 28 4:03:37.089777
+-840.00000000 13568.39733054 36204.45930900 5806.79548733 -2.919354203 1.178920217 -0.221646814 2005 5 28 5:03:37.089763
+-780.00000000 2628.58762420 38840.10855897 4771.91979854 -3.114400514 0.276239109 -0.348926401 2005 5 28 6:03:37.089790
+-720.00000000 -8535.81598158 38171.79073851 3331.00311285 -3.043839958 -0.644462527 -0.445808894 2005 5 28 7:03:37.089777
+11801 xx
+0.00000000 7473.37102491 428.94748312 5828.74846783 5.107155391 6.444680305 -0.186133297
+360.00000000 -3305.22148694 32410.84323331 -24697.16974954 -1.301137319 -1.151315600 -0.283335823 1980 8 17 13:06:40.136822
+720.00000000 14271.29083858 24110.44309009 -4725.76320143 -0.320504528 2.679841539 -2.084054355 1980 8 17 19:06:40.136822
+1080.00000000 -9990.05800009 22717.34212448 -23616.88515553 -1.016674392 -2.290267981 0.728923337 1980 8 18 1:06:40.136822
+1440.00000000 9787.87836256 33753.32249667 -15030.79874625 -1.094251553 0.923589906 -1.522311008 1980 8 18 7:06:40.136822
+14128 xx
+0.00000000 34747.57932696 24502.37114079 -1.32832986 -1.731642662 2.452772615 0.608510081
+120.00000000 18263.33439094 38159.96004751 4186.18304085 -2.744396611 1.255583260 0.528558932 2006 6 25 2:40:57.987566
+240.00000000 -3023.38840703 41783.13186459 7273.03412906 -3.035574793 -0.271656544 0.309645251 2006 6 25 4:40:57.987539
+360.00000000 -23516.34391907 34424.42065671 8448.49867693 -2.529120477 -1.726186020 0.009582303 2006 6 25 6:40:57.987553
+480.00000000 -37837.46699511 18028.39727170 7406.25540271 -1.360069525 -2.725794686 -0.292555349 2006 6 25 8:40:57.987566
+600.00000000 -42243.58460661 -3093.72887774 4422.91711801 0.163110919 -3.009980598 -0.517584362 2006 6 25 10:40:57.987539
+720.00000000 -35597.57919549 -23407.91145393 282.09554383 1.641405246 -2.506773678 -0.606963478 2006 6 25 12:40:57.987553
+840.00000000 -19649.19834455 -37606.11623860 -3932.71525948 2.689647056 -1.349150016 -0.537710698 2006 6 25 14:40:57.987566
+960.00000000 1431.30912160 -41982.04949668 -7120.45467057 3.035263353 0.160882945 -0.327993994 2006 6 25 16:40:57.987539
+1080.00000000 22136.97605384 -35388.19823762 -8447.62393401 2.587624889 1.630097136 -0.032349004 2006 6 25 18:40:57.987553
+1200.00000000 37050.15790219 -19537.23321425 -7564.83463543 1.461844494 2.674654256 0.272202191 2006 6 25 20:40:57.987566
+1320.00000000 42253.81760945 1431.81867593 -4699.87621174 -0.049247334 3.019518960 0.505890058 2006 6 25 22:40:57.987539
+1440.00000000 36366.59147396 22023.54245720 -601.47121821 -1.549681546 2.571788981 0.607057418 2006 6 26 0:40:57.987553
+1560.00000000 20922.12287985 36826.33975981 3654.91125886 -2.644070068 1.447521216 0.548722983 2006 6 26 2:40:57.987566
+1680.00000000 -23.77224182 41945.51688402 6950.29891751 -3.043358385 -0.057417440 0.346112094 2006 6 26 4:40:57.987539
+1800.00000000 -20964.17821076 36039.06206172 8418.91984963 -2.642795221 -1.546099886 0.052725852 2006 6 26 6:40:57.987553
+1920.00000000 -36401.63863057 20669.75286162 7677.19769359 -1.549488154 -2.627052310 -0.254079652 2006 6 26 8:40:57.987566
+2040.00000000 -42298.30327543 -119.03351118 4922.96388841 -0.052232768 -3.018152669 -0.493827331 2006 6 26 10:40:57.987539
+2160.00000000 -37125.62383511 -20879.63058368 879.86971348 1.456499841 -2.619358421 -0.604081694 2006 6 26 12:40:57.987553
+2280.00000000 -22250.12320553 -36182.74736487 -3393.15365183 2.583161226 -1.536647628 -0.556404555 2006 6 26 14:40:57.987566
+2400.00000000 -1563.06258654 -42035.43179159 -6780.02161760 3.034917506 -0.052702046 -0.363395654 2006 6 26 16:40:57.987539
+2520.00000000 19531.64069587 -36905.65470956 -8395.46892032 2.693682199 1.446079999 -0.075256054 2006 6 26 18:40:57.987553
+2640.00000000 35516.53506142 -22123.71916638 -7815.04516935 1.646882125 2.568416058 0.232985912 2006 6 26 20:40:57.987566
+2760.00000000 42196.03535976 -1547.32646751 -5187.39401981 0.166491841 3.019211549 0.480665780 2006 6 26 22:40:57.987539
+2880.00000000 37802.25393045 19433.57330019 -1198.66634226 -1.359930580 2.677830903 0.602507466 2006 6 27 0:40:57.987553
+16925 xx
+0.00000000 5559.11686836 -11941.04090781 -19.41235206 3.392116762 -1.946985124 4.250755852
+120.00000000 12339.83273749 -2771.14447871 18904.57603433 -0.871247614 2.600917693 0.581560002 2006 5 31 18:10:47.226141
+240.00000000 -3385.00215658 7538.13955729 200.59008616 -2.023512865 -4.261808344 -6.856385787 2006 5 31 20:10:47.226115
+360.00000000 12805.22442200 -10258.94667177 13780.16486738 0.619279224 1.821510542 2.507365975 2006 5 31 22:10:47.226128
+480.00000000 5682.46556318 7199.30270473 15437.67134070 -2.474365406 2.087897336 -2.583767460 2006 6 1 0:10:47.226141
+600.00000000 7628.94243982 -12852.72097492 2902.87208981 2.748131081 -0.740084579 4.125307943 2006 6 1 2:10:47.226115
+720.00000000 11531.64866625 -858.27542736 19086.85993771 -1.170071901 2.660311986 0.096005705 2006 6 1 4:10:47.226128
+840.00000000 -3866.98069515 2603.73442786 -4577.36484577 1.157257298 -8.453281164 -4.683959407 2006 6 1 6:10:47.226141
+960.00000000 13054.77732721 -8707.92757730 15537.63259903 0.229846748 2.119467054 2.063396852 2006 6 1 8:10:47.226115
+1080.00000000 3496.91064652 8712.83919778 12845.81838327 -2.782184997 1.552950644 -3.554436131 2006 6 1 10:10:47.226128
+1200.00000000 9593.07424729 -13023.75963608 6250.46484931 2.072666376 0.278735334 3.778111073 2006 6 1 12:10:47.226141
+1320.00000000 10284.79205084 1487.89914169 18824.37381327 -1.530335053 2.663107730 -0.542205966 2006 6 1 14:10:47.226115
+1440.00000000 -984.62035146 -5187.03480813 -5745.59594144 4.340271916 -7.266811354 1.777668888 2006 6 1 16:10:47.226128
+20413 xx
+0.00000000 25123.29290741 -13225.49966286 3249.40351869 0.488683419 4.797897593 -0.961119693
+1440.00000000 -151669.05280515 -5645.20454550 -2198.51592118 -0.869182889 -0.870759872 0.156508219 2005 12 30 19:00:00.000268
+1560.00000000 -157497.71657495 -11884.99595074 -1061.44439402 -0.749657961 -0.864016715 0.157766101 2005 12 30 21:00:00.000282
+1680.00000000 -162498.32255577 -18062.99733167 81.00915253 -0.638980378 -0.853687105 0.158098992 2005 12 30 23:00:00.000255
+1800.00000000 -166728.76010920 -24155.99648299 1222.84128677 -0.535600687 -0.840455444 0.157680857 2005 12 31 1:00:00.000268
+1920.00000000 -169935.81924592 -31767.29787964 2749.01540345 -0.430050431 -0.828904183 0.157812340 2005 12 31 3:00:00.000282
+2040.00000000 -172703.07831815 -37662.95639336 3883.60052579 -0.338004891 -0.810277487 0.156020035 2005 12 31 5:00:00.000255
+2160.00000000 -174823.19337404 -43417.55605219 5003.26312809 -0.250258622 -0.789828672 0.153764903 2005 12 31 7:00:00.000268
+2280.00000000 -176324.63925775 -49018.51958648 6104.85025002 -0.166136613 -0.767706262 0.151092242 2005 12 31 9:00:00.000282
+2400.00000000 -177231.42142458 -54454.12699497 7185.48661607 -0.085067854 -0.744001567 0.148033403 2005 12 31 11:00:00.000255
+2520.00000000 -177563.73583232 -59713.14859144 8242.48472591 -0.006561730 -0.718760309 0.144608676 2005 12 31 13:00:00.000267
+2640.00000000 -177338.48026483 -64784.54644698 9273.27220003 0.069809946 -0.691990238 0.140829236 2005 12 31 15:00:00.000281
+2760.00000000 -176569.65151461 -69657.21976255 10275.33063459 0.144426878 -0.663665876 0.136698419 2005 12 31 17:00:00.000254
+2880.00000000 -175268.65299073 -74319.77625463 11246.14177160 0.217631370 -0.633731091 0.132212491 2005 12 31 19:00:00.000267
+3000.00000000 -173444.53039609 -78760.31560396 12183.13775212 0.289737325 -0.602099929 0.127361017 2005 12 31 21:00:00.000281
+3120.00000000 -171104.14813653 -82966.21323591 13083.65278381 0.361037779 -0.568655903 0.122126889 2005 12 31 23:00:00.000254
+3240.00000000 -168252.31543803 -86923.89363433 13944.87382716 0.431811396 -0.533249797 0.116486022 2006 1 1 0:59:59.000268
+3360.00000000 -164891.86832887 -90618.58225954 14763.78794247 0.502328269 -0.495695896 0.110406725 2006 1 1 2:59:59.000282
+3480.00000000 -161023.71139825 -94034.02398835 15537.12375729 0.572855321 -0.455766412 0.103848688 2006 1 1 4:59:59.000255
+3600.00000000 -156646.82136726 -97152.15370791 16261.28409305 0.643661538 -0.413183688 0.096761524 2006 1 1 6:59:59.000268
+3720.00000000 -151758.21285737 -99952.70098346 16932.26607548 0.715023254 -0.367609561 0.089082727 2006 1 1 8:59:59.000282
+3840.00000000 -146352.86521283 -102412.70506284 17545.56394158 0.787229695 -0.318630913 0.080734873 2006 1 1 10:59:59.000255
+3960.00000000 -140423.60777444 -104505.90799734 18096.04807097 0.860588979 -0.265739987 0.071621768 2006 1 1 12:59:59.000268
+4080.00000000 -133960.95961851 -106201.98091318 18577.81121953 0.935434758 -0.208307307 0.061623110 2006 1 1 14:59:59.000282
+4200.00000000 -126952.91860010 -107465.51906186 18983.96903112 1.012133628 -0.145543878 0.050587007 2006 1 1 16:59:59.000255
+4320.00000000 -119384.69396454 -108254.71115372 19306.39581892 1.091093313 -0.076447479 0.038319282 2006 1 1 18:59:59.000268
+21897 xx
+0.00000000 -14464.72135182 -4699.19517587 0.06681686 -3.249312013 -3.281032707 4.007046940
+120.00000000 -19410.46286123 -19143.03318969 23114.05522619 0.508602237 -1.156882269 2.379923455 2006 6 25 2:33:42.834827
+240.00000000 -12686.06129708 -23853.75335645 35529.81733588 1.231633829 -0.221718202 1.118440291 2006 6 25 4:33:42.834800
+360.00000000 -2775.46649359 -22839.64574119 39494.64689967 1.468963405 0.489481769 -0.023972788 2006 6 25 6:33:42.834814
+480.00000000 7679.87883570 -16780.50760106 34686.21815555 1.364171080 1.211183897 -1.385151371 2006 6 25 8:33:42.834827
+600.00000000 14552.40023028 -4819.50121461 17154.70672449 0.109201591 2.176124494 -3.854856805 2006 6 25 10:33:42.834800
+720.00000000 -15302.38845375 -5556.43440300 1095.95088753 -2.838224312 -3.134231137 3.992596326 2006 6 25 12:33:42.834814
+840.00000000 -19289.20066748 -19427.04851118 23759.45685636 0.552495087 -1.112499437 2.325112654 2006 6 25 14:33:42.834827
+960.00000000 -12376.21976437 -23893.38020018 35831.33691892 1.246701529 -0.194294048 1.074867282 2006 6 25 16:33:42.834800
+1080.00000000 -2400.55677665 -22698.62264640 39482.75964390 1.472582922 0.513555654 -0.069306561 2006 6 25 18:33:42.834814
+1200.00000000 8031.66819252 -16455.77592085 34298.94391742 1.351357426 1.239633234 -1.448195324 2006 6 25 20:33:42.834827
+1320.00000000 14559.48780372 -4238.43773813 16079.23154704 -0.026409655 2.218938770 -4.012628896 2006 6 25 22:33:42.834800
+1440.00000000 -16036.04980660 -6372.51406468 2183.44834232 -2.485113443 -2.994994355 3.955891272 2006 6 26 0:33:42.834814
+1560.00000000 -19156.71583814 -19698.89059957 24389.29473934 0.594278133 -1.069418599 2.271152044 2006 6 26 2:33:42.834827
+1680.00000000 -12062.72925552 -23925.82362911 36120.66680667 1.261238798 -0.167201856 1.031478939 2006 6 26 4:33:42.834800
+1800.00000000 -2024.96136966 -22551.56626703 39458.50085787 1.475816889 0.537615764 -0.114887472 2006 6 26 6:33:42.834814
+1920.00000000 8379.80916204 -16123.95878459 33894.75123231 1.337468254 1.268432783 -1.512473301 2006 6 26 8:33:42.834827
+2040.00000000 14527.86748873 -3646.33817120 14960.74306518 -0.180035839 2.261273515 -4.179355590 2006 6 26 10:33:42.834800
+2160.00000000 -16680.12147335 -7149.80800425 3257.64227208 -2.178897351 -2.863927095 3.904876943 2006 6 26 12:33:42.834814
+2280.00000000 -19013.58793448 -19958.93766022 25003.81778666 0.634100431 -1.027559823 2.218002685 2006 6 26 14:33:42.834827
+2400.00000000 -11745.76155818 -23951.19438627 36397.87676581 1.275261813 -0.140425132 0.988259441 2006 6 26 16:33:42.834800
+2520.00000000 -1648.81945070 -22398.50594576 39421.83273890 1.478660174 0.561671519 -0.160733093 2006 6 26 18:33:42.834814
+2640.00000000 8723.97652795 -15784.99406275 33473.35215527 1.322433593 1.297602497 -1.578055493 2006 6 26 20:33:42.834827
+2760.00000000 14452.25571587 -3043.42332645 13796.84870805 -0.355190169 2.302485443 -4.355767077 2006 6 26 22:33:42.834800
+2880.00000000 -17246.31075678 -7890.72601508 4315.39410307 -1.910968458 -2.740945672 3.844722726 2006 6 27 0:33:42.834814
+22312 xx
+0.00000000 1442.10132912 6510.23625449 8.83145885 -3.475714837 0.997262768 6.835860345
+54.20286720 306.10478453 -5816.45655525 -2979.55846068 3.950663855 3.415332543 -5.879974329 2006 4 4 12:00:00.000000
+74.20286720 3282.82085464 2077.46972905 -5189.17988770 0.097342701 7.375135692 2.900196702 2006 4 4 12:20:00.000009
+94.20286720 530.82729176 6426.20790003 1712.37076793 -3.837120395 -1.252430637 6.561602577 2006 4 4 12:40:00.000018
+114.20286720 -3191.69170212 170.27219912 5956.29807775 -1.394956872 -7.438073471 -0.557553115 2006 4 4 13:00:00.000027
+134.20286720 -1818.99222465 -6322.45146616 681.95247154 3.349795173 -1.530140265 -6.831522765 2006 4 4 13:19:59.999996
+154.20286720 2515.66448634 -2158.83091224 -5552.13320544 2.571979660 7.311930509 -1.639865620 2006 4 4 13:40:00.000004
+174.20286720 2414.52833210 5749.10150922 -1998.59693165 -2.681032960 3.527589301 6.452951429 2006 4 4 14:00:00.000013
+194.20286720 -1877.98944331 3862.27848302 5112.48435863 -3.261489804 -6.026859137 3.433254768 2006 4 4 14:20:00.000022
+214.20286720 -3117.36584395 -4419.74773864 3840.85960912 1.545479182 -5.475416581 -5.207913748 2006 4 4 14:40:00.000031
+234.20286720 815.32034678 -5231.67692249 -3760.04690354 3.870864200 4.455588552 -5.211082191 2006 4 4 15:00:00.000000
+254.20286720 3269.54341810 3029.00081083 -4704.67969713 -0.526711345 6.812157950 3.929825087 2006 4 4 15:20:00.000009
+274.20286720 -10.18099756 6026.23341453 2643.50518407 -3.953623254 -2.616070012 6.145637500 2006 4 4 15:40:00.000018
+294.20286720 -3320.58819584 -1248.42679945 5563.06017927 -0.637046974 -7.417786044 -2.076120187 2006 4 4 16:00:00.000027
+314.20286720 -1025.48974616 -6366.98945782 -911.23559153 3.811771909 0.438071490 -6.829260617 2006 4 4 16:19:59.999996
+334.20286720 3003.75996128 -413.85708003 -5706.15591435 1.674350083 7.694169068 0.316915204 2006 4 4 16:40:00.000004
+354.20286720 1731.42816980 6258.27676925 -409.32527982 -3.400497806 1.447945424 6.904010052 2006 4 4 17:00:00.000013
+374.20286720 -2582.52111460 2024.19020680 5647.55650268 -2.530348121 -7.221719393 1.438141553 2006 4 4 17:20:00.000022
+394.20286720 -2440.56848578 -5702.77311877 1934.81094689 2.731792947 -3.350576075 -6.527773339 2006 4 4 17:40:00.000031
+414.20286720 1951.22934391 -3423.59443045 -5121.67808201 3.249039133 6.465974362 -3.069806659 2006 4 4 18:00:00.000000
+434.20286720 2886.50939356 4888.68626216 -3096.29885989 -1.973162139 4.877039020 5.832414910 2006 4 4 18:20:00.000009
+454.20286720 -1276.55532182 4553.26898463 4406.19787375 -3.715146421 -5.320176914 4.418210777 2006 4 4 18:40:00.000018
+474.20286720 -3181.54698042 -3831.29976506 4096.80242787 1.114159970 -6.104773578 -4.829967400 2006 4 4 19:00:00.000027
+22674 xx
+0.00000000 14712.22023280 -1443.81061850 0.83497888 4.418965470 1.629592098 4.115531802
+120.00000000 25418.88807860 9342.60307989 23611.46690798 0.051284086 1.213127306 2.429004159 2006 6 25 15:25:05.468479
+240.00000000 21619.59550749 16125.24978864 36396.79365831 -0.963604380 0.685454965 1.177181937 2006 6 25 17:25:05.468452
+360.00000000 12721.50543331 19258.96193362 40898.47648359 -1.457448565 0.179955469 0.071502601 2006 6 25 19:25:05.468465
+480.00000000 1272.80760054 18458.41971897 37044.74742696 -1.674863386 -0.436454983 -1.201040990 2006 6 25 21:25:05.468479
+600.00000000 -10058.43188619 11906.60764454 21739.62097733 -1.245829683 -1.543789125 -3.324449221 2006 6 25 23:25:05.468452
+720.00000000 10924.40116466 -2571.92414170 -2956.34856294 6.071727751 1.349579102 3.898430260 2006 6 26 1:25:05.468465
+840.00000000 25332.14851525 8398.91099924 21783.90654357 0.222320754 1.272214306 2.580527192 2006 6 26 3:25:05.468479
+960.00000000 22317.71926039 15574.82086129 35495.77144092 -0.892750056 0.737383381 1.291738834 2006 6 26 5:25:05.468452
+1080.00000000 13795.68675885 19088.83051008 40803.69584385 -1.420277669 0.235599456 0.185517056 2006 6 26 7:25:05.468465
+1200.00000000 2515.17145049 18746.63776282 37864.58088636 -1.668016053 -0.360431458 -1.052854596 2006 6 26 9:25:05.468479
+1320.00000000 -9084.48602106 12982.62608646 24045.63900249 -1.378032363 -1.373184736 -3.013963835 2006 6 26 11:25:05.468452
+1440.00000000 5647.00909495 -3293.90518693 -5425.85235063 8.507977176 0.414560797 2.543322806 2006 6 26 13:25:05.468465
+1560.00000000 25111.63372210 7412.55109488 19844.25781729 0.416496290 1.332106006 2.739301737 2006 6 26 15:25:05.468479
+1680.00000000 22961.47461641 14985.74459578 34511.09257381 -0.816711048 0.789391108 1.407901804 2006 6 26 17:25:05.468452
+1800.00000000 14841.15301459 18876.91439870 40626.25901619 -1.380403341 0.290228810 0.298258120 2006 6 26 19:25:05.468465
+1920.00000000 3750.70174081 18978.57939698 38578.11783220 -1.656939412 -0.287930881 -0.910825599 2006 6 26 21:25:05.468479
+2040.00000000 -8027.30219489 13939.54436955 26136.49045637 -1.474476061 -1.222693624 -2.737178731 2006 6 26 23:25:05.468452
+2160.00000000 -1296.95657092 -2813.69369768 -5871.09587258 9.881929371 -1.978467207 -1.922261005 2006 6 27 1:25:05.468465
+2280.00000000 24738.60364819 6383.41644019 17787.27631900 0.639556952 1.392554379 2.906206324 2006 6 27 3:25:05.468479
+2400.00000000 23546.85388669 14358.15602832 33441.67679479 -0.734895006 0.841564851 1.526009909 2006 6 27 5:25:05.468452
+2520.00000000 15855.87696303 18624.05633582 40367.13420574 -1.337753546 0.343969522 0.410018472 2006 6 27 7:25:05.468465
+2640.00000000 4976.44933591 19156.75504042 39189.68603184 -1.642084365 -0.218525096 -0.774148204 2006 6 27 9:25:05.468479
+2760.00000000 -6909.20746210 14790.44707042 28034.46732222 -1.545152610 -1.088119523 -2.487447214 2006 6 27 11:25:05.468452
+2880.00000000 -7331.65006707 -604.17323419 -2723.51014575 6.168997265 -3.634011554 -5.963531682 2006 6 27 13:25:05.468465
+23177 xx
+0.00000000 -8801.60046706 -0.03357557 -0.44522743 -3.835279101 -7.662552175 0.944561323
+120.00000000 -1684.34352858 -31555.95196340 3888.99944319 2.023055719 -2.151306405 0.265065778 2006 6 24 12:58:49.772928
+240.00000000 12325.51410155 -38982.15046244 4802.88832275 1.763224157 -0.102514446 0.012397139 2006 6 24 14:58:49.772902
+360.00000000 22773.66831936 -34348.02176606 4228.77407391 1.067616787 1.352427865 -0.166956367 2006 6 24 16:58:49.772915
+480.00000000 26194.40441089 -19482.94203672 2393.84774063 -0.313732186 2.808771328 -0.346204118 2006 6 24 18:58:49.772928
+600.00000000 8893.50573448 5763.38890561 -713.69884164 -7.037399220 3.022613131 -0.370272416 2006 6 24 20:58:49.772902
+720.00000000 -6028.75686537 -25648.99913786 3164.37107274 1.883159288 -3.177051976 0.390793162 2006 6 24 22:58:49.772915
+840.00000000 8313.57299056 -38146.45710922 4697.80777535 1.905002133 -0.625883074 0.076098187 2006 6 25 0:58:49.772928
+960.00000000 20181.29108622 -36842.60674073 4529.12568218 1.326244476 0.921916487 -0.114527455 2006 6 25 2:58:49.772902
+1080.00000000 26302.61794569 -25173.39539436 3084.65309986 0.245398835 2.329974347 -0.287495880 2006 6 25 4:58:49.772915
+1200.00000000 19365.07045602 -2700.00490122 317.42727417 -3.009733018 3.902496058 -0.478928582 2006 6 25 6:58:49.772928
+1320.00000000 -9667.81878780 -16930.19112642 2095.87469034 1.279288285 -4.736005905 0.582878255 2006 6 25 8:58:49.772902
+1440.00000000 4021.31438583 -36066.09209609 4442.91587411 2.007322354 -1.227461376 0.149383897 2006 6 25 10:58:49.772915
+23333 xx
+0.00000000 -9301.24542292 3326.10200382 2318.36441127 -8.729303005 -0.828225037 -0.122314827
+120.00000000 -44672.91239680 -6213.11996581 -1738.80131727 -3.719475070 -1.336673022 -0.621888261 1994 11 1 13:59:59.999169
+240.00000000 -67053.08885388 -14994.69685946 -5897.99072793 -2.860576613 -1.183771565 -0.568473909 1994 11 1 15:59:59.999142
+360.00000000 -85227.84253168 -22897.08484471 -9722.59184564 -2.426469823 -1.078592475 -0.525341431 1994 11 1 17:59:59.999155
+480.00000000 -100986.00419136 -30171.19698695 -13283.77044765 -2.147108978 -1.000530827 -0.491587582 1994 11 1 19:59:59.999169
+600.00000000 -115093.00686387 -36962.56316477 -16634.15682929 -1.945446188 -0.938947736 -0.464199202 1994 11 1 21:59:59.999142
+720.00000000 -127965.80064891 -43363.32967165 -19809.90480432 -1.789652016 -0.888278463 -0.441254468 1994 11 1 23:59:59.999155
+840.00000000 -139863.28332207 -49436.45704153 -22836.80438139 -1.663762568 -0.845315913 -0.421548627 1994 11 2 1:59:59.999169
+960.00000000 -150960.22978259 -55227.45413896 -25734.01408879 -1.558730986 -0.808061065 -0.404293846 1994 11 2 3:59:59.999142
+1080.00000000 -161381.71414630 -60770.64040903 -28516.26290017 -1.468977174 -0.775190459 -0.388951810 1994 11 2 5:59:59.999155
+1200.00000000 -171221.18736947 -66092.76474442 -31195.19847387 -1.390837596 -0.745785633 -0.375140398 1994 11 2 7:59:59.999169
+1320.00000000 -180550.82888746 -71215.23290630 -33780.24938270 -1.321788672 -0.719184752 -0.362579495 1994 11 2 9:59:59.999142
+1440.00000000 -189427.87533074 -76155.54943344 -36279.19882816 -1.260024473 -0.694896053 -0.351058133 1994 11 2 11:59:59.999155
+1560.00000000 -197898.69401409 -80928.29015181 -38698.57972447 -1.204211888 -0.672544709 -0.340413731 1994 11 2 13:59:59.999169
+1600.00000000 -200638.82986236 -82484.14969882 -39488.34331447 -1.186748462 -0.665472422 -0.337037582 1994 11 2 14:39:59.999146
+23599 xx
+0.00000000 9892.63794341 35.76144969 -1.08228838 3.556643237 6.456009375 0.783610890
+20.00000000 11931.95642997 7340.74973750 886.46365987 0.308329116 5.532328972 0.672887281 2006 6 20 18:42:06.640047
+40.00000000 11321.71039205 13222.84749156 1602.40119049 -1.151973982 4.285810871 0.521919425 2006 6 20 19:02:06.640056
+60.00000000 9438.29395675 17688.05450261 2146.59293402 -1.907904054 3.179955046 0.387692479 2006 6 20 19:22:06.640025
+80.00000000 6872.08634639 20910.11016811 2539.79945034 -2.323995367 2.207398462 0.269506121 2006 6 20 19:42:06.640034
+100.00000000 3933.37509798 23024.07662542 2798.25966746 -2.542860616 1.327134966 0.162450076 2006 6 20 20:02:06.640043
+120.00000000 816.64091546 24118.98675475 2932.69459428 -2.626838010 0.504502763 0.062344306 2006 6 20 20:22:06.640052
+140.00000000 -2334.41705804 24246.86096326 2949.36448841 -2.602259646 -0.288058266 -0.034145135 2006 6 20 20:42:06.640020
+160.00000000 -5394.31798039 23429.42716149 2850.86832586 -2.474434068 -1.074055982 -0.129868366 2006 6 20 21:02:06.640029
+180.00000000 -8233.35130237 21661.24480883 2636.51456118 -2.230845533 -1.875742344 -0.227528603 2006 6 20 21:22:06.640038
+200.00000000 -10693.96497348 18909.88168891 2302.33707548 -1.835912433 -2.716169865 -0.329931880 2006 6 20 21:42:06.640047
+220.00000000 -12553.89669904 15114.63990716 1840.93573231 -1.212478879 -3.619036996 -0.439970633 2006 6 20 22:02:06.640056
+240.00000000 -13450.20591864 10190.57904289 1241.95958736 -0.189082511 -4.596701971 -0.559173899 2006 6 20 22:22:06.640025
+260.00000000 -12686.60437121 4079.31106161 498.27078614 1.664498211 -5.559889865 -0.676747779 2006 6 20 22:42:06.640034
+280.00000000 -8672.55867753 -2827.56823315 -342.59644716 5.515079852 -5.551222962 -0.676360044 2006 6 20 23:02:06.640043
+300.00000000 1153.31498060 -6411.98692060 -779.87288941 9.689818102 1.388598425 0.167868798 2006 6 20 23:22:06.640052
+320.00000000 9542.79201056 -533.71253081 -65.73165428 3.926947087 6.459583539 0.785686755 2006 6 20 23:42:06.640020
+340.00000000 11868.80960100 6861.59590848 833.72780602 0.452957852 5.632811328 0.685262323 2006 6 21 0:02:06.640029
+360.00000000 11376.23941678 12858.97121366 1563.40660172 -1.087665695 4.374693347 0.532207051 2006 6 21 0:22:06.640038
+380.00000000 9547.70300782 17421.48570758 2118.56907515 -1.876540262 3.253891728 0.395810243 2006 6 21 0:42:06.640047
+400.00000000 7008.51470263 20725.47471227 2520.56064289 -2.308703599 2.270724438 0.276138613 2006 6 21 1:02:06.640056
+420.00000000 4083.18551180 22910.88306802 2786.35642660 -2.536610941 1.383768875 0.168165414 2006 6 21 1:22:06.640025
+440.00000000 970.13107533 24071.19896282 2927.30875440 -2.626673095 0.557274717 0.067549303 2006 6 21 1:42:06.640034
+460.00000000 -2183.75499348 24261.30188126 2950.09189560 -2.607082241 -0.236785937 -0.029112844 2006 6 21 2:02:06.640043
+480.00000000 -5252.49066783 23505.58108388 2857.68628654 -2.484465059 -1.022158411 -0.124702643 2006 6 21 2:22:06.640052
+500.00000000 -8107.41437587 21801.13395060 2649.76852683 -2.247669530 -1.821071275 -0.221914939 2006 6 21 2:42:06.640020
+520.00000000 -10594.01813094 19118.22269010 2322.77197767 -1.863224062 -2.656353699 -0.323512642 2006 6 21 3:02:06.640029
+540.00000000 -12496.70758499 15399.13096351 1869.75958053 -1.258272118 -3.551534022 -0.432332913 2006 6 21 3:22:06.640038
+560.00000000 -13467.50382653 10561.43040038 1280.84842178 -0.272050695 -4.520503543 -0.550014833 2006 6 21 3:42:06.640047
+580.00000000 -12848.00717497 4541.72432009 548.59976478 1.493938056 -5.489644146 -0.667479244 2006 6 21 4:02:06.640056
+600.00000000 -9152.79920397 -2343.88902799 -287.93741332 5.127695273 -5.650584983 -0.686013644 2006 6 21 4:22:06.640025
+620.00000000 280.12478642 -6500.11368508 -790.36236302 9.779642904 0.581430120 0.074124421 2006 6 21 4:42:06.640034
+640.00000000 9166.21406115 -1093.48756223 -129.53833135 4.316926785 6.438465969 0.785095966 2006 6 21 5:02:06.640043
+660.00000000 11794.74563870 6381.74484842 780.82775971 0.604642523 5.731705440 0.697571522 2006 6 21 5:22:06.640052
+680.00000000 11424.80363789 12493.80833338 1524.27683836 -1.021148661 4.463489406 0.542537702 2006 6 21 5:42:06.640020
+700.00000000 9652.78920084 17153.46470428 2090.43413681 -1.844382696 3.327595388 0.403924198 2006 6 21 6:02:06.640029
+720.00000000 7141.24742526 20538.97115158 2501.18059966 -2.293079623 2.333598993 0.282727441 2006 6 21 6:22:06.640038
+24208 xx
+0.00000000 7534.10987189 41266.39266843 -0.10801028 -3.027168008 0.558848996 0.207982755
+120.00000000 -14289.19940414 39469.05530051 1428.62838591 -2.893205245 -1.045447840 0.179634249 2006 6 26 2:58:29.343360
+240.00000000 -32222.92014955 26916.25425799 2468.59996594 -1.973007929 -2.359335071 0.102539376 2006 6 26 4:58:29.343334
+360.00000000 -41413.95109398 7055.51656639 2838.90906671 -0.521665080 -3.029172207 -0.002066843 2006 6 26 6:58:29.343347
+480.00000000 -39402.72251896 -14716.42475223 2441.32678358 1.066928187 -2.878714619 -0.105865729 2006 6 26 8:58:29.343360
+600.00000000 -26751.08889828 -32515.13982431 1384.38865570 2.366228869 -1.951032799 -0.181018498 2006 6 26 10:58:29.343334
+720.00000000 -6874.77975542 -41530.38329422 -46.60245459 3.027415087 -0.494671177 -0.207337260 2006 6 26 12:58:29.343347
+840.00000000 14859.52039042 -39302.58907247 -1465.02482524 2.869609883 1.100123969 -0.177514425 2006 6 26 14:58:29.343360
+960.00000000 32553.14863770 -26398.88401807 -2485.45866002 1.930064459 2.401574539 -0.099250520 2006 6 26 16:58:29.343334
+1080.00000000 41365.67576837 -6298.09965811 -2828.05254033 0.459741276 3.051680214 0.006431872 2006 6 26 18:58:29.343347
+1200.00000000 38858.83295070 15523.39314924 -2396.86850752 -1.140211488 2.867567143 0.110637217 2006 6 26 20:58:29.343360
+1320.00000000 25701.46068162 33089.42617648 -1308.68556638 -2.428713821 1.897381431 0.184605907 2006 6 26 22:58:29.343334
+1440.00000000 5501.08137100 41590.27784405 138.32522930 -3.050691874 0.409203052 0.207958133 2006 6 27 0:58:29.343347
+25954 xx
+0.00000000 8827.15660472 -41223.00971237 3.63482963 3.007087319 0.643701323 0.000941663
+-1440.00000000 8118.18519221 -41368.40537378 4.11046687 3.017696741 0.591994297 0.000933016 2004 2 7 16:20:01.494254
+-1320.00000000 27766.34015328 -31724.97000557 9.93297846 2.314236153 2.024903193 0.000660861 2004 2 7 18:20:01.494268
+-1200.00000000 39932.57237973 -13532.60040454 13.12958252 0.987382819 2.911942843 0.000213298 2004 2 7 20:20:01.494241
+-1080.00000000 41341.01365441 8305.71681955 12.84988501 -0.605098224 3.014378268 -0.000291034 2004 2 7 22:20:01.494254
+-960.00000000 31614.99210558 27907.29155353 9.16618797 -2.034243523 2.305014102 -0.000718418 2004 2 8 0:20:01.494268
+-840.00000000 13375.75227587 39994.27017651 3.05416854 -2.915424366 0.975119874 -0.000955576 2004 2 8 2:20:01.494241
+-720.00000000 -8464.89963309 41312.93549892 -3.86622919 -3.011600615 -0.617275050 -0.000939664 2004 2 8 4:20:01.494254
+-600.00000000 -28026.23406158 31507.89995661 -9.76047869 -2.296840160 -2.043607595 -0.000674889 2004 2 8 6:20:01.494268
+-480.00000000 -40040.01314363 13218.00579413 -13.06594832 -0.963328772 -2.919827983 -0.000231414 2004 2 8 8:20:01.494241
+-360.00000000 -41268.43291976 -8632.06859693 -12.90661266 0.630042315 -3.009677376 0.000273163 2004 2 8 10:20:01.494254
+-240.00000000 -31377.85317015 -28156.13970334 -9.32605530 2.054021717 -2.288554158 0.000704959 2004 2 8 12:20:01.494268
+-120.00000000 -13031.41552688 -40092.33381029 -3.27636660 2.924657466 -0.950541167 0.000949381 2004 2 8 14:20:01.494241
+0.00000000 8827.15660472 -41223.00971237 3.63482963 3.007087319 0.643701323 0.000941663 2004 2 8 16:20:01.494254
+120.00000000 28306.85426674 -31243.80147394 9.57216891 2.279137743 2.064316875 0.000684127 2004 2 8 18:20:01.494268
+240.00000000 40159.05128805 -12845.39151157 12.96086316 0.937265422 2.928448287 0.000245505 2004 2 8 20:20:01.494241
+360.00000000 41192.55903455 9013.79606759 12.90495666 -0.656727442 3.003543458 -0.000257479 2004 2 8 22:20:01.494254
+480.00000000 31131.69755798 28445.55681731 9.42419238 -2.073484842 2.269770851 -0.000691233 2004 2 9 0:20:01.494268
+600.00000000 12687.81846530 40217.83324639 3.44726249 -2.931721827 0.924962230 -0.000940766 2004 2 9 2:20:01.494241
+720.00000000 -9172.23500245 41161.63475527 -3.43575757 -3.000571486 -0.668847508 -0.000940101 2004 2 9 4:20:01.494254
+840.00000000 -28562.51093192 31022.45987587 -9.39562161 -2.261449202 -2.082713897 -0.000689669 2004 2 9 6:20:01.494268
+960.00000000 -40260.77504549 12529.11484344 -12.84915105 -0.913097031 -2.935933528 -0.000256181 2004 2 9 8:20:01.494241
+1080.00000000 -41114.14376538 -9338.87194483 -12.87952404 0.681588815 -2.998432565 0.000245006 2004 2 9 10:20:01.494254
+1200.00000000 -30890.01512240 -28690.40750792 -9.48037212 2.092989805 -2.252978152 0.000680459 2004 2 9 12:20:01.494268
+1320.00000000 -12341.46194020 -40310.06316386 -3.55833201 2.940537098 -0.900219523 0.000934170 2004 2 9 14:20:01.494241
+1440.00000000 9533.27750818 -41065.52390214 3.30756482 2.995596171 0.695200236 0.000938525 2004 2 9 16:20:01.494254
+26900 xx
+0.00000000 -42014.83795787 3702.34357772 -26.67500257 -0.269775247 -3.061854393 0.000336726
+9300.00000000 40968.68133298 -9905.99156086 11.84946837 0.722756848 2.989645389 -0.000161261 2006 4 23 4:52:50.805439
+9360.00000000 42135.66858481 1072.99195618 10.83481752 -0.078150602 3.074772455 -0.000380063 2006 4 23 5:52:50.805426
+9400.00000000 41304.75156132 8398.27742944 9.74006214 -0.612515135 3.014117469 -0.000511575 2006 4 23 6:32:50.805444
+26975 xx
+0.00000000 -14506.92313768 -21613.56043281 10.05018894 2.212943308 1.159970892 3.020600202
+120.00000000 7309.62197950 6076.00713664 6800.08705263 1.300543383 5.322579615 -4.788746312 2006 6 23 22:35:47.504573
+240.00000000 -3882.62933791 11960.00543452 -25088.14383845 -2.146773699 -1.372461491 -2.579382089 2006 6 24 0:35:47.504546
+360.00000000 -16785.45507465 -734.79159704 -34300.57085853 -1.386528125 -1.907762641 -0.220949641 2006 6 24 2:35:47.504559
+480.00000000 -23524.16689356 -13629.45124622 -30246.27899200 -0.462846784 -1.586139830 1.269293624 2006 6 24 4:35:47.504573
+600.00000000 -22890.23597092 -22209.35900155 -16769.91946116 0.704351342 -0.671112594 2.432433851 2006 6 24 6:35:47.504546
+720.00000000 -11646.39698980 -19855.44222106 3574.00109607 2.626712727 1.815887329 2.960883901 2006 6 24 8:35:47.504559
+840.00000000 7665.76124241 11159.78946577 345.93813117 -0.584818007 3.193514161 -5.750338922 2006 6 24 10:35:47.504573
+960.00000000 -6369.35388112 10204.80073022 -27844.52150384 -2.050573276 -1.582940542 -2.076075232 2006 6 24 12:35:47.504546
+1080.00000000 -18345.64763145 -2977.76684430 -34394.90760612 -1.243589864 -1.892050757 0.060372061 2006 6 24 14:35:47.504559
+1200.00000000 -23979.74839255 -15436.44139571 -28616.50540218 -0.294973425 -1.482987916 1.478255628 2006 6 24 16:35:47.504573
+1320.00000000 -21921.97167880 -22852.45147658 -13784.85308485 0.945455629 -0.428940995 2.596964378 2006 6 24 18:35:47.504546
+1440.00000000 -8266.43821031 -17210.74590112 6967.95546070 3.082244069 2.665881872 2.712555075 2006 6 24 20:35:47.504559
+1560.00000000 6286.85464535 13809.56328971 -6321.60663781 -1.615964016 1.383135377 -5.358719132 2006 6 24 22:35:47.504573
+1680.00000000 -8730.87526788 8244.63344365 -30039.92372791 -1.935622871 -1.724162072 -1.631224738 2006 6 25 0:35:47.504546
+1800.00000000 -19735.81883249 -5191.76593007 -34166.14974143 -1.097835530 -1.860148418 0.324401050 2006 6 25 2:35:47.504559
+1920.00000000 -24232.73847703 -17112.08243255 -26742.88893252 -0.119786184 -1.364365317 1.680220468 2006 6 25 4:35:47.504573
+2040.00000000 -20654.45640708 -23184.54386047 -10611.55144716 1.209238113 -0.144169639 2.748054938 2006 6 25 6:35:47.504546
+2160.00000000 -4337.15988957 -13410.46817244 9870.45949215 3.532753095 3.772236461 2.088424247 2006 6 25 8:35:47.504559
+2280.00000000 4074.62263523 14698.07548285 -12248.65327973 -2.053824693 0.203325817 -4.607867718 2006 6 25 10:35:47.504573
+2400.00000000 -10950.23438984 6148.66879447 -31736.65532865 -1.809875605 -1.816179062 -1.233364913 2006 6 25 12:35:47.504546
+2520.00000000 -20952.40702045 -7358.71507895 -33633.06643074 -0.948973031 -1.813594137 0.573893078 2006 6 25 14:35:47.504559
+2640.00000000 -24273.48944134 -18637.15546906 -24633.27702390 0.064161440 -1.228537560 1.875728935 2006 6 25 16:35:47.504573
+2760.00000000 -19057.55468077 -23148.29322082 -7269.38614178 1.500802809 0.195383037 2.879031237 2006 6 25 18:35:47.504546
+2880.00000000 43.69305308 -8145.90299207 11634.57079913 3.780661682 5.105315423 0.714401345 2006 6 25 20:35:47.504559
+28057 xx
+0.00000000 -2715.28237486 -6619.26436889 -0.01341443 -1.008587273 0.422782003 7.385272942
+120.00000000 -1816.87920942 -1835.78762132 6661.07926465 2.325140071 6.655669329 2.463394512 2006 6 26 20:52:04.079709
+240.00000000 1483.17364291 5395.21248786 4448.65907172 2.560540387 4.039025766 -5.736648561 2006 6 26 22:52:04.079682
+360.00000000 2801.25607157 5455.03931333 -3692.12865695 -0.595095864 -3.951923117 -6.298799125 2006 6 27 0:52:04.079695
+480.00000000 411.09332812 -1728.99769152 -6935.45548810 -2.935970964 -6.684085058 1.492800886 2006 6 27 2:52:04.079709
+600.00000000 -2506.52558454 -6628.98655094 -988.07784497 -1.390577189 -0.556164143 7.312736468 2006 6 27 4:52:04.079682
+720.00000000 -2090.79884266 -2723.22832193 6266.13356576 1.992640665 6.337529519 3.411803080 2006 6 27 6:52:04.079695
+840.00000000 1091.80560222 4809.88229503 5172.42897894 2.717483546 4.805518977 -5.030019896 2006 6 27 8:52:04.079709
+960.00000000 2811.14062300 5950.65707171 -2813.23705389 -0.159662742 -3.121215491 -6.775341949 2006 6 27 10:52:04.079682
+1080.00000000 805.72698304 -812.16627907 -7067.58483968 -2.798936020 -6.889265977 0.472770873 2006 6 27 12:52:04.079695
+1200.00000000 -2249.59837532 -6505.84890714 -1956.72365062 -1.731234729 -1.528750230 7.096660885 2006 6 27 14:52:04.079709
+1320.00000000 -2311.57375797 -3560.99112891 5748.16749600 1.626569751 5.890482233 4.293545048 2006 6 27 16:52:04.079682
+1440.00000000 688.16056594 4124.87618964 5794.55994449 2.810973665 5.479585563 -4.224866316 2006 6 27 18:52:04.079695
+1560.00000000 2759.94088230 6329.87271798 -1879.19518331 0.266930672 -2.222670878 -7.119390567 2006 6 27 20:52:04.079709
+1680.00000000 1171.50677137 125.82053748 -7061.96626202 -2.605687852 -6.958489749 -0.556333225 2006 6 27 22:52:04.079682
+1800.00000000 -1951.43708472 -6251.71945820 -2886.95472355 -2.024131483 -2.475214272 6.741537478 2006 6 28 0:52:04.079695
+1920.00000000 -2475.70722288 -4331.90569958 5117.31234924 1.235823539 5.322743371 5.091281211 2006 6 28 2:52:04.079709
+2040.00000000 281.46097847 3353.51057102 6302.87900650 2.840647273 6.047222485 -3.337085992 2006 6 28 4:52:04.079682
+2160.00000000 2650.33118860 6584.33434851 -908.29027134 0.675457235 -1.274044972 -7.323921567 2006 6 28 6:52:04.079695
+2280.00000000 1501.17226597 1066.31132756 -6918.71472952 -2.361891904 -6.889669974 -1.574718619 2006 6 28 8:52:04.079709
+2400.00000000 -1619.73468334 -5871.14051991 -3760.56587071 -2.264093975 -3.376316601 6.254622256 2006 6 28 10:52:04.079682
+2520.00000000 -2581.04202505 -5020.05572531 4385.92329047 0.829668458 4.645048038 5.789262667 2006 6 28 12:52:04.079695
+2640.00000000 -119.22080628 2510.90620488 6687.45615459 2.807575712 6.496549689 -2.384136661 2006 6 28 14:52:04.079709
+2760.00000000 2486.23806726 6708.18210028 80.43349581 1.057274905 -0.294294027 -7.384689123 2006 6 28 16:52:04.079682
+2880.00000000 1788.42334580 1990.50530957 -6640.59337725 -2.074169091 -6.683381288 -2.562777776 2006 6 28 18:52:04.079695
+28129 xx
+0.00000000 21707.46412351 -15318.61752390 0.13551152 1.304029214 1.816904974 3.161919976
+120.00000000 18616.75971861 3166.15177043 18833.41523210 -2.076122016 2.838457575 1.586210535 2006 6 24 15:41:49.461504
+240.00000000 -3006.50596328 18522.20742011 18941.84078154 -3.375452789 1.032680773 -1.559324534 2006 6 24 17:41:49.461477
+360.00000000 -21607.02086957 15432.59962630 206.62470309 -1.306049851 -1.817011568 -3.163725018 2006 6 24 19:41:49.461491
+480.00000000 -18453.06134549 -3150.83256134 -18685.83030936 2.106017925 -2.860236337 -1.586151870 2006 6 24 21:41:49.461504
+600.00000000 3425.11742384 -18514.73232706 -18588.67200557 3.394666340 -1.003072030 1.610061295 2006 6 24 23:41:49.461477
+720.00000000 21858.23838148 -15101.51661554 387.34517048 1.247973967 1.856017403 3.161439948 2006 6 25 1:41:49.461491
+840.00000000 18360.69935796 3506.55256762 19024.81678979 -2.122684184 2.830618605 1.537510677 2006 6 25 3:41:49.461504
+960.00000000 -3412.84765409 18646.85269710 18748.00359987 -3.366815728 0.986039922 -1.607874972 2006 6 25 5:41:49.461477
+1080.00000000 -21758.08331586 15215.44829478 -180.82181406 -1.250144680 -1.856490448 -3.163774870 2006 6 25 7:41:49.461491
+1200.00000000 -18193.41290284 -3493.85876912 -18877.14757717 2.153326942 -2.852221264 -1.536617760 2006 6 25 9:41:49.461504
+1320.00000000 3833.57386848 -18635.77026711 -18388.68722885 3.384748179 -0.955363841 1.658785020 2006 6 25 11:41:49.461477
+1440.00000000 22002.20074562 -14879.72595593 774.32827099 1.191573619 1.894561165 3.159953047 2006 6 25 13:41:49.461491
+28350 xx
+0.00000000 6333.08123128 -1580.82852326 90.69355720 0.714634423 3.224246550 7.083128132
+120.00000000 -3990.93845855 3052.98341907 4155.32700629 -5.909006188 -0.876307966 -5.039131404 2006 6 16 7:13:45.407419
+240.00000000 -603.55232010 -2685.13474569 -5891.70274282 7.572519907 -1.975656726 0.121722605 2006 6 16 9:13:45.407392
+360.00000000 4788.22345627 782.56169214 4335.14284621 -4.954509026 3.683346464 4.804645839 2006 6 16 11:13:45.407405
+480.00000000 -6291.84601644 1547.82790772 -453.67116498 -0.308625588 -3.341538574 -7.082659115 2006 6 16 13:13:45.407419
+600.00000000 4480.74573428 -3028.55200374 -3586.94343641 5.320920857 1.199736275 5.626350481 2006 6 16 15:13:45.407392
+720.00000000 -446.42460916 2932.28872588 5759.19389757 -7.561000245 1.550975493 -1.374970885 2006 6 16 17:13:45.407405
+840.00000000 -3713.79581831 -1382.66125130 -5122.45131136 6.090931626 -3.512629733 -3.467571746 2006 6 16 19:13:45.407419
+960.00000000 6058.32017522 -827.47406722 2104.04678651 -1.798403024 3.787067272 6.641439744 2006 6 16 21:13:45.407392
+1080.00000000 -5631.73659006 2623.70953644 1766.49125084 -3.216401578 -2.309140959 -6.788609120 2006 6 16 23:13:45.407405
+1200.00000000 2776.84991560 -3255.36941953 -4837.19667790 6.748135564 -0.193044825 4.005718698 2006 6 17 1:13:45.407419
+1320.00000000 1148.04430837 2486.07343386 5826.34075913 -7.420162295 2.589456382 0.356350006 2006 6 17 3:13:45.407392
+1440.00000000 -4527.90871828 -723.29199041 -4527.44608319 5.121674217 -3.909895427 -4.500218556 2006 6 17 5:13:45.407405
+28623 xx
+0.00000000 -11665.70902324 24943.61433357 25.80543633 -1.596228621 -1.476127961 1.126059754
+120.00000000 -11645.35454950 979.37668356 5517.89500058 3.407743502 -5.183094988 -0.492983277 2006 6 26 21:27:32.414976
+240.00000000 5619.19252274 19651.44862280 -7261.38496765 -2.013634213 3.106842861 0.284235517 2006 6 26 23:27:32.414949
+360.00000000 -9708.68629714 26306.14553149 -1204.29478856 -1.824164290 -0.931909596 1.113419052 2006 6 27 1:27:32.414963
+480.00000000 -14394.03162892 6659.30765074 5593.38345858 1.556522911 -4.681657614 0.296912248 2006 6 27 3:27:32.414976
+600.00000000 7712.09476270 15565.72627434 -7342.40465571 -1.646800364 4.070313571 -0.109483081 2006 6 27 5:27:32.414949
+720.00000000 -7558.36739603 27035.11367962 -2385.12054184 -1.999583791 -0.393409283 1.078093515 2006 6 27 7:27:32.414963
+840.00000000 -15495.61862220 11550.15897828 5053.83178121 0.469277336 -4.029761073 0.679054742 2006 6 27 9:27:32.414976
+960.00000000 9167.02568222 10363.65204210 -6871.52576042 -0.881621027 5.223361510 -0.740696297 2006 6 27 11:27:32.414949
+1080.00000000 -5275.80272094 27151.78486008 -3494.50687216 -2.129609388 0.150196480 1.021038089 2006 6 27 13:27:32.414963
+1200.00000000 -15601.37656145 15641.29379850 4217.03266850 -0.249183123 -3.405238557 0.888214503 2006 6 27 15:27:32.414976
+1320.00000000 9301.05872300 3883.15265574 -5477.86477017 0.871447821 6.493677331 -1.885545282 2006 6 27 17:27:32.414949
+1440.00000000 -2914.31065828 26665.20392758 -4511.09814335 -2.216261909 0.710067769 0.940691824 2006 6 27 19:27:32.414963
+28626 xx
+0.00000000 42080.71852213 -2646.86387436 0.81851294 0.193105177 3.068688251 0.000438449
+120.00000000 37740.00085593 18802.76872802 3.45512584 -1.371035206 2.752105932 0.000336883 2006 6 25 13:12:14.455025
+240.00000000 23232.82515008 35187.33981802 4.98927428 -2.565776620 1.694193132 0.000163365 2006 6 25 15:12:14.454998
+360.00000000 2467.44290178 42093.60909959 5.15062987 -3.069341800 0.179976276 -0.000031739 2006 6 25 17:12:14.455012
+480.00000000 -18962.59052991 37661.66243819 4.04433258 -2.746151982 -1.382675777 -0.000197633 2006 6 25 19:12:14.455025
+600.00000000 -35285.00095313 23085.44402778 2.08711880 -1.683277908 -2.572893625 -0.000296282 2006 6 25 21:12:14.454998
+720.00000000 -42103.20138132 2291.06228893 -0.13274964 -0.166974816 -3.070104560 -0.000311007 2006 6 25 23:12:14.455012
+840.00000000 -37580.31858370 -19120.40485693 -2.02755702 1.394367848 -2.740341612 -0.000248591 2006 6 26 1:12:14.455025
+960.00000000 -22934.20761876 -35381.23870806 -3.16495932 2.580167539 -1.672360951 -0.000134907 2006 6 26 3:12:14.454998
+1080.00000000 -2109.90332389 -42110.71508198 -3.36507889 3.070935369 -0.153808390 -0.000005855 2006 6 26 5:12:14.455012
+1200.00000000 19282.77774728 -37495.59250598 -2.71861462 2.734400524 1.406220933 0.000103486 2006 6 26 7:12:14.455025
+1320.00000000 35480.60990600 -22779.03375285 -1.52841859 1.661210676 2.587414593 0.000168300 2006 6 26 9:12:14.454998
+1440.00000000 42119.96263499 -1925.77567263 -0.19827433 0.140521206 3.071541613 0.000179561 2006 6 26 11:12:14.455012
+28872 xx
+0.00000000 -6131.82730456 2446.52815528 -253.64211033 -0.144920228 0.995100963 7.658645067
+5.00000000 -5799.24256134 2589.14811119 2011.54515100 2.325207364 -0.047125672 7.296234071 2005 11 29 0:33:58.939092
+10.00000000 -4769.05061967 2420.46580562 4035.30855837 4.464585796 -1.060923209 6.070907874 2005 11 29 0:38:58.939114
+15.00000000 -3175.45157340 1965.98738086 5582.12569607 6.049639376 -1.935777558 4.148607019 2005 11 29 0:43:58.939096
+20.00000000 -1210.19024802 1281.54541294 6474.68172772 6.920746273 -2.580517337 1.748783868 2005 11 29 0:48:58.939118
+25.00000000 896.73799533 447.12357305 6607.22400507 6.983396282 -2.925846168 -0.872655207 2005 11 29 0:53:58.939101
+30.00000000 2896.99663534 -440.04738594 5954.92675486 6.211488246 -2.926949815 -3.433959806 2005 11 29 0:58:58.939123
+35.00000000 4545.78970167 -1273.55952872 4580.16512984 4.656984233 -2.568711513 -5.638510954 2005 11 29 1:03:58.939105
+40.00000000 5627.43299371 -1947.94282469 2634.16714930 2.464141047 -1.873985161 -7.195743032 2005 11 29 1:08:58.939127
+45.00000000 5984.72318534 -2371.37691609 349.87996209 -0.121276950 -0.911981546 -7.859613894 2005 11 29 1:13:58.939109
+50.00000000 5548.43325922 -2480.16469245 -1979.24314527 -2.763269534 0.199691915 -7.482796996 2005 11 29 1:18:58.939092
+29141 xx
+0.00000000 423.99295524 -6658.12256149 136.13040356 1.006373613 0.217309983 7.662587892
+20.00000000 931.80883587 -1017.17852239 6529.19244527 -0.298847918 7.613891977 1.226399480 2006 6 19 6:45:41.242102
+40.00000000 -83.44906141 6286.20208453 2223.49837161 -1.113515974 2.530970283 -7.219445568 2006 6 19 7:05:41.242111
+60.00000000 -958.57681221 3259.26005348 -5722.63732467 -0.101225813 -6.735338321 -3.804851872 2006 6 19 7:25:41.242079
+80.00000000 -255.25619985 -5132.59762974 -4221.27233118 1.077709303 -4.905938824 5.892521264 2006 6 19 7:45:41.242088
+100.00000000 867.44295097 -5038.40402933 4256.73810533 0.479447535 5.032326446 5.857126248 2006 6 19 8:05:41.242097
+120.00000000 559.16882013 3376.30587937 5699.22017391 -0.906749328 6.646149867 -3.852331832 2006 6 19 8:25:41.242106
+140.00000000 -669.85184205 6196.00229484 -2281.95741770 -0.795804092 -2.752114827 -7.202478520 2006 6 19 8:45:41.242075
+160.00000000 -784.20708019 -1278.53125553 -6449.19892596 0.636702380 -7.595425203 1.431090802 2006 6 19 9:05:41.242084
+180.00000000 406.15811659 -6607.03115799 148.33021477 1.009818575 0.231843765 7.692047844 2006 6 19 9:25:41.242093
+200.00000000 916.34911813 -884.08649248 6491.09810362 -0.302163049 7.669887109 1.084336909 2006 6 19 9:45:41.242102
+220.00000000 -104.02490970 6304.31821405 1960.08739882 -1.108873823 2.259522809 -7.351147710 2006 6 19 10:05:41.242111
+240.00000000 -944.61642849 2872.17248379 -5846.94103362 -0.051117686 -6.989747076 -3.413102600 2006 6 19 10:25:41.242079
+260.00000000 -187.16569888 -5404.86163467 -3731.97057618 1.094696706 -4.412110995 6.326060952 2006 6 19 10:45:41.242088
+280.00000000 884.59720467 -4465.74516163 4725.83632696 0.380656028 5.691554046 5.303910983 2006 6 19 11:05:41.242097
+300.00000000 446.40767236 4086.66839620 5093.05596650 -0.982424447 6.072965199 -4.791630682 2006 6 19 11:25:41.242106
+320.00000000 -752.24467495 5588.35473301 -3275.04092573 -0.661161370 -4.016290740 -6.676898026 2006 6 19 11:45:41.242075
+340.00000000 -643.72872525 -2585.02528560 -5923.01306608 0.807922142 -7.171597814 3.041115058 2006 6 19 12:05:41.242084
+360.00000000 584.40295819 -6202.35605817 1781.00536019 0.869250450 2.226927514 7.471676765 2006 6 19 12:25:41.242093
+380.00000000 779.59211765 1100.73728301 6311.59529480 -0.599552305 7.721032522 -1.275153027 2006 6 19 12:45:41.242102
+400.00000000 -403.03155588 6399.18000837 -364.12735875 -1.008861924 -0.516636615 -7.799812287 2006 6 19 13:05:41.242111
+420.00000000 -852.93910071 192.65232023 -6322.47054784 0.396006194 -7.882964919 -0.289331517 2006 6 19 13:25:41.242079
+29238 xx
+0.00000000 -5566.59512819 -3789.75991159 67.60382245 2.873759367 -3.825340523 6.023253926
+120.00000000 4474.27915495 -1447.72286142 4619.83927235 4.712595822 5.668306153 -2.701606741 2006 6 26 8:53:44.456634
+240.00000000 1922.17712474 5113.01138342 -4087.08470203 -6.490769651 -0.522350158 -3.896001154 2006 6 26 10:53:44.456607
+360.00000000 -6157.93546882 -2094.70798790 -1941.63730960 0.149900661 -5.175192523 5.604262034 2006 6 26 12:53:44.456620
+480.00000000 2482.64052411 -3268.45944555 5146.38006190 6.501814698 4.402848754 -0.350943511 2006 6 26 14:53:44.456634
+600.00000000 4036.26455287 4827.43347201 -2507.99063955 -5.184409515 1.772280695 -5.331390168 2006 6 26 16:53:44.456607
+720.00000000 -5776.81371622 -118.64155319 -3641.22052418 -2.539917207 -5.622701582 4.403125405 2006 6 26 18:53:44.456620
+840.00000000 67.98699487 -4456.49213473 4863.71794283 7.183809420 2.418917791 2.015642495 2006 6 26 20:53:44.456634
+960.00000000 5520.62207038 3782.38203554 -596.73193161 -3.027966069 3.754152525 -6.013506363 2006 6 26 22:53:44.456607
+1080.00000000 -4528.05104455 1808.46273329 -4816.99727762 -4.808419763 -5.185789345 2.642104494 2006 6 27 0:53:44.456620
+1200.00000000 -2356.61468078 -4852.51202272 3856.53816184 6.688446735 0.118520958 4.021854210 2006 6 27 2:53:44.456634
+1320.00000000 6149.65800134 2173.59423261 1369.29488732 -0.345832777 5.109857861 -5.842951828 2006 6 27 4:53:44.456607
+1440.00000000 -2629.55011449 3400.98040158 -5344.38217129 -6.368548448 -3.998963509 0.577253064 2006 6 27 6:53:44.456620
+88888 xx
+0.00000000 2328.96975262 -5995.22051338 1719.97297192 2.912073281 -0.983417956 -7.090816210
+120.00000000 1020.69234558 2286.56260634 -6191.55565927 -3.746543902 6.467532721 1.827985678 1980 10 2 1:41:24.113771
+240.00000000 -3226.54349155 3503.70977525 4532.80979343 1.000992116 -5.788042888 5.162585826 1980 10 2 3:41:24.113744
+360.00000000 2456.10706533 -6071.93855503 1222.89768554 2.679390040 -0.448290811 -7.228792155 1980 10 2 5:41:24.113757
+480.00000000 787.16457349 2719.91800946 -6043.86662024 -3.759883839 6.277439314 2.397897864 1980 10 2 7:41:24.113771
+600.00000000 -3110.97648029 3121.73026235 4878.15217035 1.244916056 -6.124880425 4.700576353 1980 10 2 9:41:24.113744
+720.00000000 2567.56229695 -6112.50383922 713.96374435 2.440245751 0.098109002 -7.319959258 1980 10 2 11:41:24.113757
+840.00000000 556.05661780 3144.52288201 -5855.34636178 -3.754660143 6.044752775 2.957941672 1980 10 2 13:41:24.113771
+960.00000000 -2982.47940539 2712.61663711 5192.32330472 1.475566773 -6.427737014 4.202420227 1980 10 2 15:41:24.113744
+1080.00000000 2663.08964352 -6115.48290885 196.40072866 2.196121564 0.652415093 -7.362824152 1980 10 2 17:41:24.113757
+1200.00000000 328.54999674 3557.09490552 -5626.21427211 -3.731193288 5.769341172 3.504058731 1980 10 2 19:41:24.113771
+1320.00000000 -2842.06876757 2278.42343492 5472.33437150 1.691852635 -6.693216335 3.671022712 1980 10 2 21:41:24.113744
+1440.00000000 2742.55398832 -6079.67009123 -326.39012649 1.948497651 1.211072678 -7.356193131 1980 10 2 23:41:24.113757
diff --git a/pyorbital/tests/test_aiaa.py b/pyorbital/tests/test_aiaa.py
new file mode 100644
index 0000000..40f47c2
--- /dev/null
+++ b/pyorbital/tests/test_aiaa.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011, 2014 SMHI
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Test cases from the AIAA article.
+"""
+
+# TODO: right formal unit tests.
+from __future__ import with_statement
+
+import os
+
+from pyorbital.orbital import Orbital, OrbitElements, _SGDP4
+from pyorbital.tlefile import ChecksumError
+from pyorbital import tlefile, astronomy
+import numpy as np
+from datetime import timedelta, datetime
+import unittest
+
+class LineOrbital(Orbital):
+    """Read TLE lines instead of file.
+    """
+    def __init__(self, satellite, line1, line2):
+        satellite = satellite.upper()
+        self.satellite_name = satellite
+        self.tle = tlefile.read(satellite, line1=line1, line2=line2)
+        self.orbit_elements = OrbitElements(self.tle)
+        self._sgdp4 = _SGDP4(self.orbit_elements)
+
+
+def get_results(satnumber, delay):
+    """Get expected results from result file.
+    """
+    path = os.path.dirname(os.path.abspath(__file__))
+    with open(os.path.join(path, "aiaa_results")) as f_2:
+        line = f_2.readline()
+        while(line):
+            if line.endswith(" xx\n") and int(line[:-3]) == satnumber:
+                line = f_2.readline()
+                while(not line.startswith("%.8f"%delay)):
+                    line = f_2.readline()
+                sline = line.split()
+                if delay == 0:
+                    utc_time = None
+                else:
+                    utc_time = datetime.strptime(sline[-1], "%H:%M:%S.%f")
+                    utc_time = utc_time.replace(year=int(sline[-4]),
+                                                month=int(sline[-3]),
+                                                day=int(sline[-2]))
+                return (float(sline[1]),
+                        float(sline[2]),
+                        float(sline[3]),
+                        float(sline[4]),
+                        float(sline[5]),
+                        float(sline[6]),
+                        utc_time)
+            line = f_2.readline()
+
+class AIAAIntegrationTest(unittest.TestCase):
+    """Test against the AIAA test cases.
+    """
+    
+    def test_aiaa(self):
+        """Do the tests against AIAA test cases.
+        """
+        path = os.path.dirname(os.path.abspath(__file__))
+        with open(os.path.join(path, "SGP4-VER.TLE")) as f__:
+            test_line = f__.readline()
+            while(test_line):
+                if test_line.startswith("#"):
+                    test_name = test_line
+                if test_line.startswith("1 "):
+                    line1 = test_line
+                if test_line.startswith("2 "):
+                    line2 = test_line[:69]
+                    times = str.split(test_line[69:])
+                    times = np.arange(float(times[0]),
+                                      float(times[1]) + 1,
+                                      float(times[2]))
+                    if test_name.startswith("#   SL-14 DEB"):
+                        # FIXME: we have to handle decaying satellites!
+                        test_line = f__.readline()
+                        continue
+
+                    try:
+                        o = LineOrbital("unknown", line1, line2)
+                    except NotImplementedError, e:
+                        test_line = f__.readline()
+                        continue
+                    except ChecksumError, e:
+                        self.assertTrue(test_line.split()[1] in ["33333", "33334", "33335"])
+                    for delay in times:
+                        try:
+                            test_time = timedelta(minutes=delay) + o.tle.epoch
+                            pos, vel = o.get_position(test_time, False)
+                            res = get_results(int(o.tle.satnumber), float(delay))
+                        except NotImplementedError:
+                            # Skipping deep-space
+                            break
+                        # except ValueError, e:
+                        #     from warnings import warn
+                        #     warn(test_name + ' ' + str(e))
+                        #     break
+                            
+                        delta_pos = 5e-6 # km =  5 mm
+                        delta_vel = 5e-9 # km/s = 5 um/s
+                        delta_time = 1e-3 # 1 milisecond
+                        self.assertTrue(abs(res[0] - pos[0]) < delta_pos)
+                        self.assertTrue(abs(res[1] - pos[1]) < delta_pos)
+                        self.assertTrue(abs(res[2] - pos[2]) < delta_pos)
+                        self.assertTrue(abs(res[3] - vel[0]) < delta_vel)
+                        self.assertTrue(abs(res[4] - vel[1]) < delta_vel)
+                        self.assertTrue(abs(res[5] - vel[2]) < delta_vel)
+                        if res[6] is not None:
+                            dt = astronomy._days(res[6] - test_time) * 24 * 60
+                            self.assertTrue(abs(dt) < delta_time)
+                        
+                test_line = f__.readline()
+        
+
+def suite():
+    """The suite for test_aiaa
+    """
+    loader = unittest.TestLoader()
+    mysuite = unittest.TestSuite()
+    mysuite.addTest(loader.loadTestsFromTestCase(AIAAIntegrationTest))
+    
+    return mysuite
+
diff --git a/pyorbital/tests/test_astronomy.py b/pyorbital/tests/test_astronomy.py
new file mode 100644
index 0000000..ae39d1c
--- /dev/null
+++ b/pyorbital/tests/test_astronomy.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2013, 2014 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+import unittest
+
+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.
+        """
+
+        t = datetime(2000, 1, 1, 12, 0)
+        self.assertEqual(astr.jdays(t), 2451545.0)
+        self.assertEqual(astr.jdays2000(t), 0)
+        t = datetime(2009, 10, 8, 14, 30)
+        self.assertEqual(astr.jdays(t), 2455113.1041666665)
+        self.assertEqual(astr.jdays2000(t), 3568.1041666666665)
+        
+    def test_sunangles(self):
+        """Test the sun-angle calculations:
+        """
+        lat, lon = 58.6167, 16.1833 # Norrkoping
+        time_slot = datetime(2011, 9, 23, 12, 0)
+        
+        sun_theta = astr.sun_zenith_angle(time_slot, lon, lat)
+        self.assertEqual(sun_theta, 60.371433482557833)
+        sun_theta = astr.sun_zenith_angle(time_slot, 0., 0.)
+        self.assertEqual(sun_theta, 1.8751916863323426)
+
+def suite():
+    """The suite for test_astronomy
+    """
+    loader = unittest.TestLoader()
+    mysuite = unittest.TestSuite()
+    mysuite.addTest(loader.loadTestsFromTestCase(TestAstronomy))
+    
+    return mysuite
+
diff --git a/pyorbital/tests/test_geoloc.py b/pyorbital/tests/test_geoloc.py
new file mode 100644
index 0000000..a2a69cc
--- /dev/null
+++ b/pyorbital/tests/test_geoloc.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2014 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Test the geoloc module.
+"""
+
+import unittest
+from pyorbital.geoloc_instrument_definitions import avhrr
+from pyorbital.geoloc import (ScanGeometry, qrotate,
+                              subpoint, geodetic_lat)
+import numpy as np
+from datetime import datetime, timedelta
+
+class TestQuaternion(unittest.TestCase):
+    """Test the quaternion rotation.
+    """
+
+    def test_qrotate(self):
+        """Test quaternion rotation
+        """
+        vector = np.array([[1, 0, 0]]).T
+        axis = np.array([[0, 1, 0]]).T
+        angle = np.deg2rad(90)
+        self.assertTrue(np.allclose(qrotate(vector, axis, angle),
+                                    np.array([[0, 0, 1]]).T))
+
+        axis = np.array([0, 1, 0])
+        self.assertTrue(np.allclose(qrotate(vector, axis, angle),
+                                    np.array([[0, 0, 1]]).T))
+
+        vector = np.array([[1, 0, 0],
+                           [0, 0, 1]]).T
+        axis = np.array([0, 1, 0])
+        angle = np.deg2rad(90)
+        self.assertTrue(np.allclose(qrotate(vector, axis, angle),
+                                    np.array([[0, 0, 1],
+                                              [-1, 0, 0]]).T))
+
+        axis = np.array([[0, 1, 0]]).T
+        self.assertTrue(np.allclose(qrotate(vector, axis, angle),
+                                    np.array([[0, 0, 1],
+                                              [-1, 0, 0]]).T))
+    
+
+class TestGeoloc(unittest.TestCase):
+    """Test for the core computing part.
+    """
+
+    def test_scan_geometry(self):
+        """Test the ScanGeometry object.
+        """
+        instrument = ScanGeometry(np.deg2rad(np.array([[10, 0],
+                                                       [0, 0],
+                                                       [-10, 0]])),
+                                  np.array([-0.1, 0, 0.1]))
+        self.assertTrue(np.allclose(np.rad2deg(instrument.fovs[:, 0]),
+                                    np.array([10, 0, -10])))
+
+        # Test vectors
+        
+        pos = np.array([[0, 0, 7000]]).T
+        vel = np.array([[1, 0, 0]]).T
+        vec = instrument.vectors(pos, vel)
+        self.assertTrue(np.allclose(np.array([[0, 0, -1]]),
+                                    vec[:, 1]))
+
+        # minus sin because we use trigonometrical direction of angles
+        
+        self.assertTrue(np.allclose(np.array([[0,
+                                               -np.sin(np.deg2rad(10)),
+                                               -np.cos(np.deg2rad(10))]]),
+                                    vec[:, 0]))
+        self.assertTrue(np.allclose(np.array([[0,
+                                               -np.sin(np.deg2rad(-10)),
+                                               -np.cos(np.deg2rad(-10))]]),
+                                    vec[:, 2]))
+
+        # Test times
+
+        start_of_scan = datetime(2014, 1, 8, 11, 30)
+        times = instrument.times(start_of_scan)
+        self.assertEquals(times[1], start_of_scan)
+        self.assertEquals(times[0], start_of_scan - timedelta(seconds=0.1))
+        self.assertEquals(times[2], start_of_scan + timedelta(seconds=0.1))
+
+    def test_geodetic_lat(self):
+        """Test the determination of the geodetic latitude.
+        """
+
+        a = 6378.137 # km
+        b = 6356.75231414 # km, GRS80
+
+        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])))
+        
+        
+    def test_subpoint(self):
+        """Test nadir determination.
+        """
+        a = 6378.137 # km
+        b = 6356.75231414 # km, GRS80
+        point = np.array([0, 0, 7000])
+        nadir = subpoint(point, a, b)
+        self.assertTrue(np.allclose(nadir, np.array([[0, 0, b]]).T))
+
+        point = np.array([7000, 0, 7000])
+        nadir = subpoint(point, a, b)
+        self.assertTrue(np.allclose(nadir,
+                                    np.array([[4507.85431429,
+                                               0,
+                                               4497.06396339]]).T))
+        points = np.array([[7000, 0, 7000],
+                           [7000, 0, 7000]]).T
+        nadir = subpoint(points, a, b)
+        self.assertTrue(np.allclose(nadir,
+                                    np.array([[4507.85431429,
+                                               0,
+                                               4497.06396339]]).T))
+
+
+        
+
+class TestGeolocDefs(unittest.TestCase):
+    """Test the instrument definitions.
+    """
+    def test_avhrr(self):
+        """Test the definition of the avhrr instrument
+        """
+        avh = avhrr(1, np.array([0, 1023.5 ,2047]))
+        self.assertTrue(np.allclose(np.rad2deg(avh.fovs[:, 0]),
+                                    np.array([55.37, 0, -55.37])))
+
+        avh = avhrr(1, np.array([0, 1023.5 ,2047]), 10)
+        self.assertTrue(np.allclose(np.rad2deg(avh.fovs[:, 0]),
+                                    np.array([10, 0, -10])))
+
+def suite():
+    """The suite for test_geoloc
+    """
+    loader = unittest.TestLoader()
+    mysuite = unittest.TestSuite()
+    mysuite.addTest(loader.loadTestsFromTestCase(TestQuaternion))
+    mysuite.addTest(loader.loadTestsFromTestCase(TestGeoloc))
+    mysuite.addTest(loader.loadTestsFromTestCase(TestGeolocDefs))
+    
+    return mysuite
diff --git a/pyorbital/tests/test_orbital.py b/pyorbital/tests/test_orbital.py
new file mode 100644
index 0000000..9704ca6
--- /dev/null
+++ b/pyorbital/tests/test_orbital.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2012-2014 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Test the geoloc orbital.
+"""
+
+import unittest
+from datetime import datetime, timedelta
+
+import numpy as np
+
+from pyorbital import orbital
+
+eps_deg = 10e-3
+
+class Test(unittest.TestCase):
+
+    def test_get_orbit_number(self):
+        """Testing getting the orbitnumber from the tle"""
+        sat = orbital.Orbital("NPP",
+            line1="1 37849U 11061A   12017.90990040 -.00000112  00000-0 -32693-4 0   772",
+            line2="2 37849  98.7026 317.8811 0001845  92.4533 267.6830 14.19582686 11574")
+        dobj = datetime(2012, 1, 18, 8, 4, 19)
+        orbnum = sat.get_orbit_number(dobj)
+        self.assertEqual(orbnum, 1163)
+
+    def test_sublonlat(self):
+        sat = orbital.Orbital("ISS (ZARYA)", 
+            line1="1 25544U 98067A   03097.78853147  .00021906  00000-0  28403-3 0  8652", 
+            line2="2 25544  51.6361  13.7980 0004256  35.6671  59.2566 15.58778559250029")
+        d = datetime(2003, 3, 23, 0, 3, 22)
+        lon, lat, alt = sat.get_lonlatalt(d)
+        expected_lon = -68.199894472013213
+        expected_lat = 23.159747677881075
+        expected_alt = 392.01953430856935
+        self.failUnless(np.abs(lon - expected_lon) < eps_deg, 'Calculation of sublon failed')
+        self.failUnless(np.abs(lat - expected_lat) < eps_deg, 'Calculation of sublat failed')
+        self.failUnless(np.abs(alt - expected_alt) < eps_deg, 'Calculation of altitude failed')
+        
+
+    def test_observer_look(self):
+        sat = orbital.Orbital("ISS (ZARYA)", 
+            line1="1 25544U 98067A   03097.78853147  .00021906  00000-0  28403-3 0  8652", 
+            line2="2 25544  51.6361  13.7980 0004256  35.6671  59.2566 15.58778559250029")
+        d = datetime(2003, 3, 23, 0, 3, 22)
+        az, el = sat.get_observer_look(d, -84.39733, 33.775867, 0)
+        expected_az = 122.45169655331965
+        expected_el = 1.9800219611255456
+        self.failUnless(np.abs(az - expected_az) < eps_deg, 'Calculation of azimut failed')
+        self.failUnless(np.abs(el - expected_el) < eps_deg, 'Calculation of elevation failed')
+        
+    def test_orbit_num_an(self):
+        sat = orbital.Orbital("METOP-A", 
+            line1="1 29499U 06044A   11254.96536486  .00000092  00000-0  62081-4 0  5221", 
+            line2="2 29499  98.6804 312.6735 0001758 111.9178 248.2152 14.21501774254058")
+        d = datetime(2011, 9, 14, 5, 30)
+        self.assertEqual(sat.get_orbit_number(d), 25437)
+        
+    def test_orbit_num_non_an(self):
+        sat = orbital.Orbital("METOP-A", 
+            line1="1 29499U 06044A   13060.48822809  .00000017  00000-0  27793-4 0  9819", 
+            line2="2 29499  98.6639 121.6164 0001449  71.9056  43.3132 14.21510544330271")
+        dt = timedelta(minutes=98)
+        self.assertEqual(sat.get_orbit_number(sat.tle.epoch + dt), 33028)
+        
+    def test_orbit_num_equator(self):
+        sat = orbital.Orbital("SUOMI NPP", 
+            line1="1 37849U 11061A   13061.24611272  .00000048  00000-0  43679-4 0  4334", 
+            line2="2 37849  98.7444   1.0588 0001264  63.8791 102.8546 14.19528338 69643")
+        t1 = datetime(2013, 3, 2, 22, 2, 25)
+        t2 = datetime(2013, 3, 2, 22, 2, 26)
+        on1 = sat.get_orbit_number(t1)
+        on2 = sat.get_orbit_number(t2)
+        self.assertEqual(on1, 6973)
+        self.assertEqual(on2, 6974)
+        pos1, vel1 = sat.get_position(t1, normalize=False)
+        pos2, vel2 = sat.get_position(t2, normalize=False)
+        del vel1, vel2
+        self.assertTrue(pos1[2] < 0)
+        self.assertTrue(pos2[2] > 0)
+
+
+
+def suite():
+    """The suite for test_orbital
+    """
+    loader = unittest.TestLoader()
+    mysuite = unittest.TestSuite()
+    mysuite.addTest(loader.loadTestsFromTestCase(Test))
+    
+    return mysuite
diff --git a/pyorbital/tests/test_tlefile.py b/pyorbital/tests/test_tlefile.py
new file mode 100644
index 0000000..b7e41e1
--- /dev/null
+++ b/pyorbital/tests/test_tlefile.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2014 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Testing TLE file reading
+"""
+
+
+from pyorbital.tlefile import Tle
+import datetime
+import unittest
+
+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"
+
+
+
+class TLETest(unittest.TestCase):
+    """Test TLE reading.
+
+    We're using the wikipedia example::
+
+     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
+    
+    """
+
+    def check_example(self, tle):
+        """Check the *tle* instance against predetermined values.
+        """
+        # line 1
+        self.assertEqual(tle.satnumber, "25544")
+        self.assertEqual(tle.classification, "U")
+        self.assertEqual(tle.id_launch_year, "98")
+        self.assertEqual(tle.id_launch_number, "067")
+        self.assertEqual(tle.id_launch_piece.strip(), "A")
+        self.assertEqual(tle.epoch_year, "08")
+        self.assertEqual(tle.epoch_day, 264.51782528)
+        epoch = (datetime.datetime(2008, 1, 1)
+                 + datetime.timedelta(days=264.51782528 - 1))
+        self.assertEqual(tle.epoch, epoch)
+        self.assertEqual(tle.mean_motion_derivative, -.00002182)
+        self.assertEqual(tle.mean_motion_sec_derivative, 0.0)
+        self.assertEqual(tle.bstar, -.11606e-4)
+        self.assertEqual(tle.ephemeris_type, 0)
+        self.assertEqual(tle.element_number, 292)
+
+        # line 2
+        self.assertEqual(tle.inclination, 51.6416)
+        self.assertEqual(tle.right_ascension, 247.4627)
+        self.assertEqual(tle.excentricity, .0006703)
+        self.assertEqual(tle.arg_perigee, 130.5360)
+        self.assertEqual(tle.mean_anomaly, 325.0288)
+        self.assertEqual(tle.mean_motion, 15.72125391)
+        self.assertEqual(tle.orbit, 56353)
+
+    def test_from_line(self):
+        tle = Tle("ISS (ZARYA)", line1=line1, line2=line2)
+        self.check_example(tle)
+
+    def test_from_file(self):
+        from tempfile import mkstemp
+        from os import write, close, remove
+        filehandle, filename = mkstemp()
+        try:
+            write(filehandle, "\n".join([line0, line1, line2]))
+            close(filehandle)
+            tle = Tle("ISS (ZARYA)", filename)
+            self.check_example(tle)
+        finally:
+            remove(filename)
+
+
+def suite():
+    """The suite for test_tlefile
+    """
+    loader = unittest.TestLoader()
+    mysuite = unittest.TestSuite()
+    mysuite.addTest(loader.loadTestsFromTestCase(TLETest))
+    
+    return mysuite
+
diff --git a/pyorbital/tlefile.py b/pyorbital/tlefile.py
new file mode 100644
index 0000000..a939c62
--- /dev/null
+++ b/pyorbital/tlefile.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011, 2012, 2013, 2014.
+
+# Author(s):
+
+#   Esben S. Nielsen <esn at dmi.dk>
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+
+import logging
+import datetime
+import urllib2
+
+tle_urls = ('http://celestrak.com/NORAD/elements/weather.txt',
+            'http://celestrak.com/NORAD/elements/resource.txt')
+
+logger = logging.getLogger(__name__)
+
+def read(platform, tle_file=None, line1=None, line2=None):
+    """Read TLE for *satellite* from *tle_file*, from *line1* and *line2*, 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*.
+    """
+    with open(destination, "w") as dest:
+        for url in tle_urls:
+            response = urllib2.urlopen(url)
+            dest.write(response.read())
+
+class ChecksumError(Exception):
+    pass
+
+
+class Tle(object):
+    """Class holding TLE objects.
+    """    
+
+    def __init__(self, platform, tle_file=None, line1=None, line2=None):
+        platform = platform.strip().upper()
+
+        if line1 is not None and line2 is not None:
+            tle = line1.strip() + "\n" + line2.strip()
+        else:
+            if tle_file:
+                urls = (tle_file,)
+                open_func = open
+            else:
+                logger.debug("Fetch tle from the internet.")
+                urls = tle_urls
+                open_func = urllib2.urlopen
+            
+            tle = ""
+            for url in urls:
+                fp = open_func(url)
+                for l0 in fp:
+                    l1, l2 = fp.next(), fp.next()
+                    if l0.strip() == platform:
+                        tle = l1.strip() + "\n" + l2.strip()
+                        break
+                fp.close()
+                if tle:
+                    break
+            
+            if not tle:
+                raise AttributeError, "Found no TLE entry for '%s'" % platform
+
+        self._platform = platform
+        self._line1, self._line2 = tle.split('\n')
+        self._checksum()
+        self._read_tle()
+
+    @property
+    def line1(self):
+        return self._line1
+
+    @property
+    def line2(self):
+        return self._line2
+
+    @property
+    def platform(self):
+        return self._platform
+
+    def _checksum(self):
+        """Performs the checksum for the current TLE.
+        """
+        for line in [self.line1, self.line2]:
+            check = 0
+            for char in line[:-1]:
+                if char.isdigit():
+                    check += int(char)
+                if char == "-":
+                    check += 1
+
+            if (check % 10) != int(line[-1]):
+                raise ChecksumError(self._platform + " " + line)
+
+    def _read_tle(self):
+
+        def _read_tle_decimal(rep):
+            if rep[0] in ["-", " "]:
+                val = rep[0] + "." + rep[1:-2] + "e" + rep[-2:]
+            else:
+                val = "." + rep[:-2] + "e" + rep[-2:]
+
+            return float(val)
+        
+        self.satnumber = self._line1[2:7]
+        self.classification = self._line1[7]
+        self.id_launch_year = self._line1[9:11]
+        self.id_launch_number = self._line1[11:14]
+        self.id_launch_piece = self._line1[14:17]
+        self.epoch_year = self._line1[18:20]
+        self.epoch_day = float(self._line1[20:32])
+        self.epoch = (datetime.datetime.strptime(self.epoch_year, "%y") +
+                             datetime.timedelta(days=self.epoch_day - 1))
+        self.mean_motion_derivative = float(self._line1[33:43])
+        self.mean_motion_sec_derivative = _read_tle_decimal(self._line1[44:52])
+        self.bstar = float(self._line1[53] + "." + self._line1[54:59] + "e" + self._line1[59:61])
+        _read_tle_decimal(self._line1[53:61])
+        try:
+            self.ephemeris_type = int(self._line1[62])
+        except ValueError:
+            self.ephemeris_type = 0
+        self.element_number = int(self._line1[64:68])
+
+        self.inclination = float(self._line2[8:16])
+        self.right_ascension = float(self._line2[17:25])
+        self.excentricity = int(self._line2[26:33]) * 10 ** -7
+        self.arg_perigee = float(self._line2[34:42])
+        self.mean_anomaly = float(self._line2[43:51])
+        self.mean_motion = float(self._line2[52:63])
+        self.orbit = int(self._line2[63:68])
+
+    def __str__(self):
+        import pprint, StringIO
+        s = StringIO.StringIO()
+        d = dict(([(k, v) for k, v in self.__dict__.items() if k[0] != '_']))
+        pprint.pprint(d, s)
+        return s.getvalue()[:-1]
+
+if __name__ == '__main__':
+    tle = read('noaa 19')
+    print tle
diff --git a/pyorbital/version.py b/pyorbital/version.py
new file mode 100644
index 0000000..db58857
--- /dev/null
+++ b/pyorbital/version.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2014 Martin Raspaud
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+"""Version file.
+"""
+
+__major__ = "0"
+__minor__ = "3"
+__patch__ = "2"
+
+__version__ = "v" + ".".join([__major__, __minor__, __patch__])
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..3ce9449
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011-2014
+
+# Author(s):
+
+#   Martin Raspaud <martin.raspaud at 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
+# 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/>.
+
+from setuptools import setup
+import imp
+
+version = imp.load_source('pyorbital.version', 'pyorbital/version.py')
+
+setup(name='pyorbital',
+      version=version.__version__,
+      description='Orbital parameters and astronomical computations in Python',
+      author='Martin Raspaud, Esben S. Nielsen',
+      author_email='martin.raspaud at smhi.se, esn at dmi.dk',
+      classifiers=["Development Status :: 5 - Production/Stable",
+                   "Intended Audience :: Science/Research",
+                   "License :: OSI Approved :: GNU General Public License v3 " +
+                   "or later (GPLv3+)",
+                   "Operating System :: OS Independent",
+                   "Programming Language :: Python",
+                   "Topic :: Scientific/Engineering",
+                   "Topic :: Scientific/Engineering :: Astronomy"],
+      url="https://github.com/mraspaud/pyorbital",
+      test_suite='pyorbital.tests.suite',
+      package_dir = {'pyorbital': 'pyorbital'},
+      packages = ['pyorbital'],      
+      install_requires=['numpy'],
+      zip_safe=False,
+      )
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/pyorbital.git



More information about the Pkg-grass-devel mailing list