From 755220b8dca3833b534ba565234797662abcc372 Mon Sep 17 00:00:00 2001 From: Per Helge Aarnes Date: Sun, 1 Sep 2024 18:00:47 +0200 Subject: [PATCH] Fix/upload pypi (#40) * update devcontainer * update README.md * update testpypi action * update .toml * update docker container * update test pypi github action * update README.md --- .devcontainer/Dockerfile | 7 +- .devcontainer/devcontainer.json | 41 ++++---- .../pypi-package-upload-testpypi.yml | 59 ++++++------ README.md | 96 ++++++++++--------- pyproject.toml | 2 - 5 files changed, 105 insertions(+), 100 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3ab5ba3..57f54a1 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -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 - # + && apt-get -y install --no-install-recommends libpq-dev gdal-bin libgdal-dev + # # [Optional] Uncomment this line to install global node packages. # RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0e85335..d4df1ee 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -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. @@ -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" -} +} \ No newline at end of file diff --git a/.github/workflows/pypi-package-upload-testpypi.yml b/.github/workflows/pypi-package-upload-testpypi.yml index 8e6e7b5..fc9b4a2 100644 --- a/.github/workflows/pypi-package-upload-testpypi.yml +++ b/.github/workflows/pypi-package-upload-testpypi.yml @@ -1,6 +1,7 @@ name: Upload Python Package to TEST PYPI on: + workflow_dispatch: pull_request: branches: - master @@ -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/* diff --git a/README.md b/README.md index 22da6dc..1dcb659 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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) @@ -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 @@ -99,7 +105,7 @@ $$ $$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}$$ @@ -107,9 +113,9 @@ $$\alpha=\frac{{f}^2_1}{{f}^2_2}$$ $$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}$. @@ -155,85 +161,85 @@ 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`.
More... - - **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`.
@@ -241,7 +247,7 @@ The `GNSS_MultipathAnalysis` function accepts several keyword arguments that all ### Output -- **analysisResults** (`dict`): +- **analysisResults** (`dict`): A dictionary containing the results of the analysis for all GNSS systems. diff --git a/pyproject.toml b/pyproject.toml index a354412..3667e70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", @@ -26,7 +25,6 @@ classifiers = [ "Operating System :: OS Independent", ] -license = { text = "MIT" } dependencies = [ "matplotlib==3.7.5", "numpy==1.24.4",