Skip to content

Commit

Permalink
Merge pull request #41 from paarnes/dev
Browse files Browse the repository at this point in the history
Fix/upload pypi (#40)
  • Loading branch information
paarnes authored Sep 1, 2024
2 parents ad30791 + 755220b commit 18a4afc
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 100 deletions.
7 changes: 4 additions & 3 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
&& rm -rf /tmp/pip-tmp


RUN python -m pip install --upgrade pip
RUN python -m pip install notebook jupyterlab

# [Optional] Uncomment this section to install additional OS packages.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends libpq-dev gdal-bin libgdal-dev
# <your-package-list-here>
&& apt-get -y install --no-install-recommends libpq-dev gdal-bin libgdal-dev
# <your-package-list-here>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
Expand Down
41 changes: 20 additions & 21 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"args": {
// Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
Expand All @@ -14,42 +14,41 @@
"NODE_VERSION": "lts/*"
}
},


// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
"files.trimTrailingWhitespace": true,
"jupyter.defaultKernel": "Python 3",
"python.languageServer": "Pylance",
"jupyter.alwaysTrustNotebooks": true,
"jupyter.interactiveWindow.textEditor.executeSelection": true,
"files.autoSave": "onFocusChange",
"jupyter.kernels.excludePythonEnvironments": [
"/usr/bin/python3"
], //making VS CODE pick the local installed Python interpreter as kernel
"editor.formatOnSave": true
},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
"ms-python.vscode-pylance",
"42Crunch.vscode-openapi",
"ms-python.black-formatter",
"waderyan.gitblame",
"ms-toolsai.jupyter",
"ms-toolsai.jupyter-keymap",
"ms-toolsai.jupyter-renderers"
]
}
},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",

// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}
}
59 changes: 30 additions & 29 deletions .github/workflows/pypi-package-upload-testpypi.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Upload Python Package to TEST PYPI

on:
workflow_dispatch:
pull_request:
branches:
- master
Expand All @@ -10,32 +11,32 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install --upgrade setuptools wheel build twine
- name: Get current version from pyproject.toml
id: get_version
run: echo "::set-output name=version::$(grep -oP '(?<=version = ")[^"]*' pyproject.toml)"

- name: Increment version
id: increment_version
run: echo "::set-output name=version::$(python -c "version='${{ steps.get_version.outputs.version }}'.split('.'); version[-1] = str(int(version[-1]) + 1); print('.'.join(version))")"

- name: Update version in pyproject.toml
run: sed -i "s/version = \".*\"/version = \"${{ steps.increment_version.outputs.version }}\"/" pyproject.toml

- name: Build and upload to Test PyPI (master branch)
if: github.ref == 'refs/heads/master'
run: |
python -m build
twine upload --repository-url https://test.pypi.org/legacy/ --username __token__ --password ${{ secrets.TEST_PYPI_TOKEN }} dist/*
- name: Checkout repository
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install --upgrade setuptools wheel build twine
- name: Get current version from pyproject.toml
id: get_version
run: echo "::set-output name=version::$(grep -oP '(?<=version = ")[^"]*' pyproject.toml)"

- name: Increment version
id: increment_version
run: echo "::set-output name=version::$(python -c "version='${{ steps.get_version.outputs.version }}'.split('.'); version[-1] = str(int(version[-1]) + 1); print('.'.join(version))")"

- name: Update version in pyproject.toml
run: sed -i "s/version = \".*\"/version = \"${{ steps.increment_version.outputs.version }}\"/" pyproject.toml

- name: Build and upload to Test PyPI (master branch)
# if: github.ref == 'refs/heads/master'
run: |
python -m build
twine upload --repository-url https://test.pypi.org/legacy/ --username __token__ --password ${{ secrets.TEST_PYPI_TOKEN }} dist/*
96 changes: 51 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,26 @@

## Introduction

GNSS Multipath Analysis is a software tool for analyzing the multipath effect on Global Navigation Satellite Systems (GNSS). It is primarily based on the MATLAB software [GNSS_Receiver_QC_2020](https://gitlab.com/bjro/GNSS_reading_protocol/-/tree/main/GNSS_Receiver_QC_2020) by Bjørn-Eirik Roald, but has been adapted to Python and includes additional features.
GNSS Multipath Analysis is a software tool for analyzing the multipath effect on Global Navigation Satellite Systems (GNSS). The core functionality is based on the MATLAB software [GNSS_Receiver_QC_2020](https://gitlab.com/bjro/GNSS_reading_protocol/-/tree/main/GNSS_Receiver_QC_2020), but has been adapted to Python and includes additional features. A considerable part of the results has been validated by comparing the results with estimates from RTKLIB. This software will be further developed, and feedback and suggestions are therefore gratefully received. Don't hesitate to report if you find bugs or missing functionality. Either by e-mail or by raising an issue here in GitHub.

## Features
- Supports broadcasted ephemerides (RINEX nagiation files) and SP3 files
- Supports both RINEX v2.xx and v3.xx observation files
- Generates various plots like:
- Ionospheric delay wrt time and zenith mapped ionospheric delay (combined)
- The Multipath effect plotted wrt time and elevation angle (combined)
- Barplot showing RMS values for each signal and system
- Polar plot of the multipath effect and the Signal to nosie ratio (SNR)
- polarplots of SNR and multipath
- SNR vs. time/elevation
-
- Extracts GLONASS FCN from RINEX navigation files
- Cycle slip detection and multipath effect estimation
- Results export to CSV and Pickle formats
- Option to choose which navigation system to analyze
- Estimates the code multipath for all GNSS systems (GPS, GLONASS, Galileo, and BeiDou).
- Estimates the code multipath for all available signals/codes in the RINEX file.
- Provides statistics on the total number of cycle slips detected (using both ionospheric residuals and code-phase differences).
- Supports both RINEX navigation files (broadcast ephemerides) and SP3 files (precise ephemerides).
- Supports both RINEX v2.xx and v3.xx observation files.
- Generates various plots, including:
- Ionospheric delay over time and zenith-mapped ionospheric delay (combined).
- The multipath effect plotted against time and elevation angle (combined).
- Bar plot showing multipath RMSE for each signal and system.
- Polar plot of the multipath effect and Signal-to-Noise Ratio (SNR).
- Polar plots of SNR and multipath.
- Polar plot of each observed satellite in the system.
- SNR versus time/elevation.
- Extracts GLONASS FCN from RINEX navigation files.
- Detects cycle slips and estimates the multipath effect.
- Exports results to CSV and a Python dictionary as a Pickle (both compressed and uncompressed formats are supported).
- Allows selection of specific navigation systems and signal bands for analysis.


## Installation
Expand All @@ -58,6 +61,8 @@ pip install gnssmultipath
- **Python >=3.8**: Ensure you have Python 3.8 or newer installed.
- **LaTeX** (optional): Required for generating plots with LaTeX formatting.

Note: In the example plots, TEX is used to get prettier text formatting. However, this requires TEX/LaTex to be installed on your computer. The program will first try to use TEX, and if it's not possible, standard text formatting will be used. So TEX/LaTex is not required to run the program and make plots.

### Installing LaTeX (optional)
- On Ubuntu: `sudo apt-get install texlive-full`
- On Windows: Download and install from [MiKTeX](https://miktex.org/download)
Expand All @@ -77,6 +82,7 @@ analysisResults = GNSS_MultipathAnalysis(rinObs_file,
broadcastNav1=rinNav_file,
outputDir=outputdir)
```
If you have a SP3 file, and not a RINEX navigation file, you just replace the keyword argument ``broadcastNav1`` with ``sp3NavFilename_1``.

## The steps are:
1. Reads in the RINEX observation file
Expand All @@ -99,17 +105,17 @@ $$

$$MP_1 = R_1 - \left(1+\frac{2}{\alpha - 1}\right)\Phi_1 + \left(\frac{2}{\alpha - 1}\right)\Phi_2$$

where $R_1$ is the code observation on band 1, $\Phi_1$ and $\Phi_2$ is phase observation on band 1 and band 2 respectively. Furthermore $\alpha$ is the ratio between the two frequency squared
where $R_1$ is the code observation on band 1, $\Phi_1$ and $\Phi_2$ is phase observation on band 1 and band 2 respectively. Furthermore $\alpha$ is the ratio between the two frequency squared

$$\alpha=\frac{{f}^2_1}{{f}^2_2}$$

7. Based on the multipath estimates computed in step 6, both weighted and unweighted RMS-values get computed. The RMS value has unit _meter_, and is given by

$$RMS=\sqrt{\frac{\sum\limits_{i=1}^{N_{sat}}\sum\limits_{j=1}^{N_{epohcs}} MP_{ij}}{N_{est}}}$$

For the weighted RMS value, the satellite elevation angle is used in a weighting function defined as
For the weighted RMS value, the satellite elevation angle is used in a weighting function defined as

$$w =\frac{1}{4sin^2\beta}$$
$$w =\frac{1}{4sin^2\beta}$$

for every estimates with elevation angle $\beta$ is below $30^{\circ}$ and $w =1$ for $\beta > 30^{\circ}$.

Expand Down Expand Up @@ -155,93 +161,93 @@ for every estimates with elevation angle $\beta$ is below $30^{\circ}$ and $w =1

The `GNSS_MultipathAnalysis` function accepts several keyword arguments that allow for detailed customization of the analysis process. Below is a list of the first five arguments:

- **rinObsFilename** (`str`):
- **rinObsFilename** (`str`):
Path to the RINEX 3 observation file. This is a required argument.

- **broadcastNav1** (`Union[str, None]`, optional):
- **broadcastNav1** (`Union[str, None]`, optional):
Path to the first RINEX navigation file. Default is `None`.

- **broadcastNav2** (`Union[str, None]`, optional):
- **broadcastNav2** (`Union[str, None]`, optional):
Path to the second RINEX navigation file (if available). Default is `None`.

- **broadcastNav3** (`Union[str, None]`, optional):
- **broadcastNav3** (`Union[str, None]`, optional):
Path to the third RINEX navigation file (if available). Default is `None`.

- **broadcastNav4** (`Union[str, None]`, optional):
- **broadcastNav4** (`Union[str, None]`, optional):
Path to the fourth RINEX navigation file (if available). Default is `None`.

<details>
<summary>More...</summary>

- **sp3NavFilename_1** (`Union[str, None]`, optional):
- **sp3NavFilename_1** (`Union[str, None]`, optional):
Path to the first SP3 navigation file. Default is `None`.

- **sp3NavFilename_2** (`Union[str, None]`, optional):
- **sp3NavFilename_2** (`Union[str, None]`, optional):
Path to the second SP3 navigation file (optional). Default is `None`.

- **sp3NavFilename_3** (`Union[str, None]`, optional):
- **sp3NavFilename_3** (`Union[str, None]`, optional):
Path to the third SP3 navigation file (optional). Default is `None`.

- **desiredGNSSsystems** (`Union[List[str], None]`, optional):
- **desiredGNSSsystems** (`Union[List[str], None]`, optional):
List of GNSS systems to include in the analysis. For example, `['G', 'R']` to include only GPS and GLONASS. Default is all systems (`None`).

- **phaseCodeLimit** (`Union[float, int, None]`, optional):
- **phaseCodeLimit** (`Union[float, int, None]`, optional):
Critical limit that indicates cycle slip for phase-code combination in m/s. If set to `0`, the default value of `6.667 m/s` will be used. Default is `None`.

- **ionLimit** (`Union[float, None]`, optional):
- **ionLimit** (`Union[float, None]`, optional):
Critical limit indicating cycle slip for the rate of change of the ionospheric delay in m/s. If set to `0`, the default value of `0.0667 m/s` will be used. Default is `None`.

- **cutoff_elevation_angle** (`Union[int, None]`, optional):
- **cutoff_elevation_angle** (`Union[int, None]`, optional):
Cutoff angle for satellite elevation in degrees. Estimates with elevation angles below this value will be excluded. Default is `None`.

- **outputDir** (`Union[str, None]`, optional):
- **outputDir** (`Union[str, None]`, optional):
Path to the directory where output files should be saved. If not specified, the output will be generated in a sub-directory within the current working directory. Default is `None`.

- **plotEstimates** (`bool`, optional):
- **plotEstimates** (`bool`, optional):
Whether to plot the estimates. Default is `True`.

- **plot_polarplot** (`bool`, optional):
- **plot_polarplot** (`bool`, optional):
Whether to generate polar plots. Default is `True`.

- **include_SNR** (`bool`, optional):
- **include_SNR** (`bool`, optional):
If set to `True`, the Signal-to-Noise Ratio (SNR) from the RINEX observation file will be included in the analysis. Default is `True`.

- **save_results_as_pickle** (`bool`, optional):
- **save_results_as_pickle** (`bool`, optional):
If `True`, the results will be saved as a binary pickle file. Default is `True`.

- **save_results_as_compressed_pickle** (`bool`, optional):
- **save_results_as_compressed_pickle** (`bool`, optional):
If `True`, the results will be saved as a binary compressed pickle file using zstd compression. Default is `False`.

- **write_results_to_csv** (`bool`, optional):
- **write_results_to_csv** (`bool`, optional):
If `True`, a subset of the results will be exported as a CSV file. Default is `True`.

- **output_csv_delimiter** (`str`, optional):
- **output_csv_delimiter** (`str`, optional):
The delimiter to use for the CSV file. Default is a semicolon (`;`).

- **nav_data_rate** (`int`, optional):
- **nav_data_rate** (`int`, optional):
The desired data rate for ephemerides in minutes. A higher value speeds up processing but may reduce accuracy. Default is `60` minutes.

- **includeResultSummary** (`Union[bool, None]`, optional):
- **includeResultSummary** (`Union[bool, None]`, optional):
Whether to include a detailed summary of statistics in the output file, including for individual satellites. Default is `None`.

- **includeCompactSummary** (`Union[bool, None]`, optional):
- **includeCompactSummary** (`Union[bool, None]`, optional):
Whether to include a compact overview of statistics in the output file. Default is `None`.

- **includeObservationOverview** (`Union[bool, None]`, optional):
- **includeObservationOverview** (`Union[bool, None]`, optional):
Whether to include an overview of observation types for each satellite in the output file. Default is `None`.

- **includeLLIOverview** (`Union[bool, None]`, optional):
- **includeLLIOverview** (`Union[bool, None]`, optional):
Whether to include an overview of LLI (Loss of Lock Indicator) data in the output file. Default is `None`.

- **use_LaTex** (`bool`, optional):
- **use_LaTex** (`bool`, optional):
If `True`, LaTeX will be used for rendering text in plots, requiring LaTeX to be installed on your system. Default is `True`.

</details>


### Output

- **analysisResults** (`dict`):
- **analysisResults** (`dict`):
A dictionary containing the results of the analysis for all GNSS systems.


Expand Down
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ maintainers = [
]
description = "A python software that provides comprehensive solutions for GNSS multipath analysis."
readme = "README.md"
readme-content-type = "text/markdown"
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Python :: 3",
Expand All @@ -26,7 +25,6 @@ classifiers = [
"Operating System :: OS Independent",
]

license = { text = "MIT" }
dependencies = [
"matplotlib==3.7.5",
"numpy==1.24.4",
Expand Down

0 comments on commit 18a4afc

Please sign in to comment.