Python Package of GNSS Data Processing
======================================

:Create Date: 2017-08-16
:Update Date: 2023-11-30
:Version: 1.0.12
:Authors: 张良
:Contact: lzhang2019@whu.edu.cn
:Organization: `武汉大学GNSS近地空间环境学课题组(姚宜斌教授课题组) <http://ybyao.users.sgg.whu.edu.cn>`_
:Copyright: 武汉大学GNSS近地空间环境学课题组

最新更新
---------------
1. 一键下载广播星历、精密轨道、精密钟差、CODE GIM 文件。


::

    $ pip3 install --upgrade ppgnss # 升级/安装
    $ ppget --data=gim --from=2023,1 --to=2023,2 --outdir=data # 下载CODE GIM文件到 data目录
    $ ppget --data=clk --from=2023,1 --to=2023,2 --outdir=data # 下载钟差文件到data目录
    $ ppget --data=brdc --from=2023,1 --to=2023,2 --outdir=data # 下载广播星历到data目录


2. ``v1.0.14`` 以后版本使用 ``pip3`` 安装时，无需手动安装依赖

简介
---------------

ppgnss 是基于 python 编写的 GNSS 数据处理程序包，提供 GNSS 相关的文件读取、时间转换、坐标转换等基础功能。

本程序包安装方便、调用简单，是 GNSS 科研必备基础库。

如何安装
---------------

可以选择 ``pip`` 安装或源码安装。

使用 pip 快速安装
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

使用 ``pip`` 可以快速安装::

    $ pip3 install ppgnss

可以参考 `B站视频：如何在vscode 中使用 ppgnss <https://www.bilibili.com/video/BV1Tw411P7jr/?vd_source=65c213dd98db97fe4792a7c0be36870b>`_

使用源码安装
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Requirements
---------------------

The package can only used on ``Python 3.8``. So make sure you have ``Python 3.8`` installed. And then, dependency should be installed. ::


    $ git clone https://gitee.com/snnugiser/ppgnss
    $ cd ppgnss
    $ pip3 install -r requirements.txt


You can run command in the main directory as follow to install ``ppgnss`` package::

  $ sudo python setup.py install

If you want to learn more about ``setup.py`` files, check out `this repository <https://github.com/kennethreitz/setup.py>`_.

How to use
--------------------

After installed, ``ppgnss`` can be used as normal python package.



How to import ``ppgnss`` module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In python script file or python interpreter, import ``ppgnss`` as follow::

  >> import ppgnss
  >> from ppgnss import gnss_time # or
  >> import ppgnss.gnss_time as gt


ppgnss API document
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``ppgnss API document`` is generated by `sphinx <http://www.sphinx-doc.org/en/stable/>`_. To generate the document can use command as follow::

  $ make html

in directory ``ppgnss/docs``. Files generated into directory ``docs/_build/html``



运行示例
----------------------

``tests/`` 下有单元测试代码，可以从中查看示例函数调用方式。

小技巧
--------------------
1. 读大文件比较耗时，读完可以用 ``gnss_utils.saveobject`` 存为对象文件，然后每次使用时用 ``gnss_utils.loadobject`` 加载。这样耗时的读文件只进行了一次。

快速入门
---------------------

时间转换
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

首先，导入时间转换模块::

  from ppgnss import gnss_time


1. 年积日转年月日

::

  year, doy = 2020, 300
  yr, mo, dy = gnss_time.doy2ymd(year, doy)

2. 年月日转年积日

::

  yr, mo, dy = 2020, 3, 12
  year, doy = gnss_time.ymd2doy(yr, mo, dy)

3. 年月日转儒略日
::

  yr, mo, dy = 2020, 2, 15.3
  jd = gnss_time.ymd2jd(yr, mo, dy)

4. 字符串转 datetime

::

  str_time = "2016 10 0 0 0 0.0000"
  dt = gnss_time.strtime2datetime(str_time)

5. 年积日转GPS周

::

  year, doy = 2022, 132
  gpsw, dow = gnss_time.doy2gpsw(year, doy)


坐标转换
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

导入坐标转换模块::

  from ppgnss import gnss_geodesy

1. 经纬度转空间直角坐标系

::

  lat, lon, hgt = 35.82, 120.32, 104
  x, y, z = gnss_geodesy.blh2xyz(lat, lon, hgt)

2. 空间直角坐标系转经纬度

::

  x, y, z = -1250323.7185,  5584256.2418, 2810873.5627
  lat, lon, hgt = gnss_geodesy.xyz2blh(x, y, z)

3. 空间直角坐标系转站心坐标系

::

  base = [-2814241.6307, 4640483.1794, 3339376.6524]
  rover = [-2814943.8488, 4640647.3401, 3338562.0520]
  dxyz = [rover[0] - base[0], rover[1] - base[1], rover[2] - base[2]]
  enu = gnss_geodesy.dxyz2neu(dxyz, base)

4. 小数度转度分秒

::

  dd = 30.82
  deg, mi, sec = gnss_geodesy.dd2dms(dd)

文件读取
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

导入文件读取模块::

  from ppgnss import gnss_io

1. 读取 RTKLib 结果文件

::
  
  pos_filename = /path/to/rtklib/pos/file
  xr_data = gnss_io.read_rtklib_solution(pos_filename, type="blh") # blh format or
  xr_data = gnss_io.read_rtklib_solution(pos_filename, type="xyz") # xyz format

2. 读取 IONEX 文件

::

    ionex = /path/to/ionex/file
    xr_gim = gnss_io.read_ionex_file(ionex)
    print(xr_gim)

大量实用示例陆续更新
--------------------
示例源码
~~~~~~~~~~~~~~~~~~~~~~
`ppgnss examples <https://gitee.com/snnugiser/ppgnss_examples>`_.

视频课程
~~~~~~~~~~~~~~~~~~~~~~
1. `在 vscode 中使用 ppgnss <https://www.bilibili.com/video/BV1Tw411P7jr/?spm_id_from=333.337.search-card.all.click&vd_source=65c213dd98db97fe4792a7c0be36870b>`_
2. `配合 wget 下载GIM文件 <https://www.bilibili.com/video/BV1vC4y1R7MG/?spm_id_from=333.788.recommend_more_video.0&vd_source=65c213dd98db97fe4792a7c0be36870b>`_.
3. `配合 wget 下载BRDM文件 <https://www.bilibili.com/video/BV13u4y137u9/?spm_id_from=333.788.recommend_more_video.0&vd_source=65c213dd98db97fe4792a7c0be36870b>`_.
4. `配合 wget 下载SP3文件 <https://www.bilibili.com/video/BV1PG411e7C3/?spm_id_from=333.999.0.0&vd_source=65c213dd98db97fe4792a7c0be36870b>`_.

开发说明
-------------------------------

开发主分枝
~~~~~~~~~~~~~~~~~~~~~~

The main version repository is `ppgnss <https://bitbucket.org/ppgnss/ppgnss/>`_. ``master`` branch is the main branch for formal version and ``dev`` branch is the development branch. Develop code based on the ``dev`` branch, you should firstly fork the branch to your own repository.

分叉工程
~~~~~~~~~~~~~~~~~~~~~~~~

``fork`` the project to your own repository. The new repository can be named another name to distinguish. For example, ``ppgnss-dev`` can be a good name.


修改和编写代码
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

子模块
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

所有子模块都应放在 ``ppgnss`` 目录下． 子模块名应以 ``gnss_`` 开始.

编码规范
^^^^^^^^^^^^^^^^^^^^^^^^^^^

编码应符合 `pep-8 <https://www.python.org/dev/peps/pep-0008/>`_. 推荐使用 ``autopep8`` 和 ``pylint`` 工具进行代码检查．通常，编辑器或 IDE 都有相应的 ``autopep8`` 和 ``pylint`` 支持．

文档字符串
^^^^^^^^^^^^^^^^^^^^^^^^

所有函数都应有文档字符串 (``docstring``). 为使文档字符串可以使用 ``sphinx`` 生成文档，建议使用 ``reST`` 风格．一个简单的示例为::

  def add(para1, para2):
     '''
     Add para1 and para2. ..:math:`c = para_0 + para_2`

     :param para1: The first number.
     :type para1: int or float
     :param para2: the second number.
     :type para2: int or float
     :return: sum of para1 and para2
     :rtyep: float

     Example usage::

       >> add(1, 2)
       3

     '''
     pass

单元测试
^^^^^^^^^^^^^^^^^^^^^^^^

如果没有特殊情况，所有函数都应有与之相对应的单元测试．一般地，每个子模块对应一个单元测试文件，每个函数有特定的单元测试语句．在单元测试覆盖的好的情况下，修改代码会比较方便．单元测试一般要包括正常调用和异常调用．具体测试用例可以在开发中慢慢摸索．

Commit code
~~~~~~~~~~~~~~~~~~~~~~~~~~

每次向自己的代码库提交代码要提供提交说明．最好提交的内容可以一句话可以总结．

Pull Request and code review
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

每次提交后可以向主开发分枝推送．利用 ``Pull Request`` 向主开发分枝推送．推送代码量以 200-400 行为宜．　每次向主开发分枝推送必须经过 ``Code Review`` 才能合并到主开发分枝．任何一段代码都至少有一个人进行 ``Code Review`` . 在 ``Pull Request`` 时，可以选择让谁进行 ``Code Review`` .

Code Review
~~~~~~~~~~~~~~~~~~~~~~~~~

代码审查的主要目的是检查代码是否容易读懂．让任何一段代码都有至少两个人熟悉．主要内容有

1. 代码是否能正常运行
2. 单元测试是否正常运行．
3. 代码是否清晰易读, 可维护
4. 在  ``docstring`` 中对输入输出是否描述清楚． ``docstring`` 是否可以能够用 ``sphinx`` 直接生成说明文档．
5. 代码风格是否符合 ``pep-8``
6. 与现有代码是否重叠，是否有重构的空间
7. 其他觉得可以改进的地方