gri-convolve 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. gri_convolve-0.2.0/.coveragerc +8 -0
  2. gri_convolve-0.2.0/.docs_other_projects.md +81 -0
  3. gri_convolve-0.2.0/.gitignore +35 -0
  4. gri_convolve-0.2.0/.gitlab-ci-deps.yml +10 -0
  5. gri_convolve-0.2.0/.gitlab-ci.yml +95 -0
  6. gri_convolve-0.2.0/.init_venv.sh +82 -0
  7. gri_convolve-0.2.0/.pre-commit-config.yaml +40 -0
  8. gri_convolve-0.2.0/.pre-commit-unskipped.py +38 -0
  9. gri_convolve-0.2.0/.python-version +1 -0
  10. gri_convolve-0.2.0/.ruff.toml +60 -0
  11. gri_convolve-0.2.0/.vscode/settings.json +15 -0
  12. gri_convolve-0.2.0/CONTRIBUTING.md +113 -0
  13. gri_convolve-0.2.0/LICENSE +21 -0
  14. gri_convolve-0.2.0/PKG-INFO +175 -0
  15. gri_convolve-0.2.0/README.md +161 -0
  16. gri_convolve-0.2.0/gri_convolve/__init__.py +5 -0
  17. gri_convolve-0.2.0/gri_convolve/altitude/__init__.py +5 -0
  18. gri_convolve-0.2.0/gri_convolve/altitude/nearest.py +28 -0
  19. gri_convolve-0.2.0/gri_convolve/convolve/__init__.py +7 -0
  20. gri_convolve-0.2.0/gri_convolve/convolve/atwa_convolve.py +186 -0
  21. gri_convolve-0.2.0/gri_convolve/convolve/cluster_convolve.py +260 -0
  22. gri_convolve-0.2.0/gri_convolve/convolve/convolve.py +88 -0
  23. gri_convolve-0.2.0/gri_convolve/convolve/smart_convolve.py +72 -0
  24. gri_convolve-0.2.0/gri_convolve/py.typed +0 -0
  25. gri_convolve-0.2.0/pyproject.toml +53 -0
  26. gri_convolve-0.2.0/report.xml +1 -0
  27. gri_convolve-0.2.0/test/__init__.py +0 -0
  28. gri_convolve-0.2.0/test/convolve/__init__.py +0 -0
  29. gri_convolve-0.2.0/test/convolve/test_atwa_convolve.py +111 -0
  30. gri_convolve-0.2.0/test/convolve/test_cluster_convolve.py +133 -0
  31. gri_convolve-0.2.0/test/convolve/test_cluster_convolve2.py +141 -0
  32. gri_convolve-0.2.0/test/convolve/test_convolve.py +124 -0
  33. gri_convolve-0.2.0/test/convolve/test_smart_convolve.py +128 -0
  34. gri_convolve-0.2.0/uv.lock +456 -0
@@ -0,0 +1,8 @@
1
+ [run]
2
+ omit = */test*, ./*.py, .venv/*
3
+ branch = True
4
+ source = .
5
+ [report]
6
+ skip_empty = True
7
+ [html]
8
+ directory = .cov_html
@@ -0,0 +1,81 @@
1
+ [![GeoSol Research Logo](https://geosolresearch.com/logos/foss_logo.png "GeoSol Research")](https://geosolresearch.com)
2
+
3
+ # GeoSol FOSS Projects
4
+
5
+ [Back to main README](README.md)
6
+
7
+ GeoSol Research is working to create, maintain, and improve several FOSS projects in the geolocation space. Here is what we are currently offering!
8
+
9
+ ## Foundation Libraries
10
+
11
+ ### [GRI Utils](https://gitlab.com/geosol-foss/python/gri-utils)
12
+
13
+ The math back end to many other projects. This includes constants, coordinate conversion and transformation, orbit propagation, observable calculations, and geolocation algorithms. Most are based around numpy arrays.
14
+
15
+ ### [GRI Memoize](https://gitlab.com/geosol-foss/python/gri-memoize)
16
+
17
+ Class-based memoization with full type hints and IDE integration. Provides caching decorators for performance optimization.
18
+
19
+ ### [GRI Fitter](https://gitlab.com/geosol-foss/python/gri-fitter)
20
+
21
+ Equation fitting wrapper around scipy.optimize.curve\_fit. Simplifies curve fitting workflows with a clean API.
22
+
23
+ ### [GRI Plot](https://gitlab.com/geosol-foss/python/gri-plot)
24
+
25
+ Plotting utilities for Plotly and Matplotlib. Provides consistent styling and common plot types for geospatial visualization.
26
+
27
+ ### [GRI Signal](https://gitlab.com/geosol-foss/python/gri-signal)
28
+
29
+ Functional signal processing library with pure functions operating on numpy arrays. Includes filters (lowpass, bandpass, analytic), FFT metrics, PSD analysis, cross-correlation, beamforming, and signal generation utilities.
30
+
31
+ ## Core Libraries
32
+
33
+ ### [GRI Pos](https://gitlab.com/geosol-foss/python/gri-pos)
34
+
35
+ A position object that greatly simplifies handling coordinates, distances, and memory, mostly on the WGS-84 ellipsoid.
36
+
37
+ ### [GRI Ell](https://gitlab.com/geosol-foss/python/gri-ell)
38
+
39
+ An object to handle statistical locations like ellipse and ellipsoid, centered around a GRI-Position object. Transformations between statistical spaces, conversions between sigma and percentages in 2D and 3D, statistical distances, and attributes.
40
+
41
+ ### [GRI NSEpoch](https://gitlab.com/geosol-foss/python/gri-nsepoch)
42
+
43
+ A lot of the work we do is down to nanosecond or tens of nanosecond accuracy. We needed an object that could both handle that level of precision as well as do a lot of the string <=> time conversions for the many semi-standards formats we run into in this field.
44
+
45
+ ### [GRI Convolve](https://gitlab.com/geosol-foss/python/gri-convolve)
46
+
47
+ Ellipsoid convolution with outlier detection and clustering. Combines multiple statistical position estimates into refined solutions.
48
+
49
+ ## Atmospheric Libraries
50
+
51
+ ### [GRI Tropo](https://gitlab.com/geosol-foss/python/gri-tropo)
52
+
53
+ Tropospheric delay corrections using ITU-R 2019 models and ERA5 refractivity data.
54
+
55
+ ### [GRI Tropo Data](https://gitlab.com/geosol-foss/python/gri-tropo-data)
56
+
57
+ ERA5 data pipeline for downloading and processing tropospheric refractivity data used by gri-tropo.
58
+
59
+ ### [GRI Iono](https://gitlab.com/geosol-foss/python/gri-iono)
60
+
61
+ Ionospheric delay corrections using Bent, IRI, and NeQuick models.
62
+
63
+ ### [GRI Iono Data](https://gitlab.com/geosol-foss/python/gri-iono-data)
64
+
65
+ Solar flux and NeQuickG coefficient data pipeline for ionospheric modeling.
66
+
67
+ ## Simulation Libraries
68
+
69
+ ### [GRI GeoSim](https://gitlab.com/geosol-foss/python/gri-geosim)
70
+
71
+ Geometric/geolocation simulation library for platforms, sensors, emitters, and observables. Simulate satellite and ground-based geolocation scenarios with AOA/TDOA/FDOA measurements.
72
+
73
+ ### [GRI SigSim](https://gitlab.com/geosol-foss/python/gri-sigsim)
74
+
75
+ Object-based RF signal simulation library. Wraps gri-signal functions with chainable object-oriented classes for waveforms (chirp, OFDM, pulsed), channel modeling (delay, Doppler, multipath), receiver simulation, and observable extraction (TOA, FOA, AOA).
76
+
77
+ ## Examples and Testing
78
+
79
+ ### [GRI Sandbox](https://gitlab.com/geosol-foss/python/gri-sandbox)
80
+
81
+ Some neat (small) examples and projects we've put together over time using the above libraries!
@@ -0,0 +1,35 @@
1
+ ### Python ###
2
+ *.py[cod]
3
+ __pycache__/
4
+ build/
5
+ dist/
6
+ wheels/
7
+ lib/
8
+ lib64/
9
+ *.egg-info/
10
+ *.egg
11
+ .venv
12
+
13
+ ### Temp files ###
14
+ *~
15
+ *.swp
16
+ .version
17
+ .pytest_cache/
18
+ .mypy_cache/
19
+ testreports/
20
+ .VSCodeCounter/
21
+ .coverage
22
+ coverage.xml
23
+ .cov_html/
24
+ *.pstats
25
+ *.stats
26
+ .claude/
27
+ CLAUDE.md
28
+
29
+ ### Credentials ###
30
+ .env*
31
+ *.key
32
+ *.pem
33
+ *.p12
34
+ .cdsapirc
35
+ .ecmwfdatastoresrc
@@ -0,0 +1,10 @@
1
+ # Project-specific dependencies to clone
2
+ # Customize this file per project to clone different repositories
3
+ # TODO: This is only a stopgap until the projects are on pypi. For projects with no
4
+ # dependencies: "before_script: []"
5
+ .clone_dependencies:
6
+ before_script:
7
+ - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/geosol-foss/python/gri-ell.git ../gri-ell
8
+ - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/geosol-foss/python/gri-pos.git ../gri-pos
9
+ - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/geosol-foss/python/gri-utils.git ../gri-utils
10
+ - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/geosol-foss/python/gri-memoize.git ../gri-memoize
@@ -0,0 +1,95 @@
1
+ include:
2
+ - local: .gitlab-ci-deps.yml
3
+
4
+ stages:
5
+ - test
6
+ - lint
7
+ - deploy
8
+
9
+ variables:
10
+ UV_CACHE_DIR: "$CI_PROJECT_DIR/.uv-cache"
11
+ COVERAGE_THRESHOLD: "70"
12
+
13
+ cache:
14
+ key: "${CI_COMMIT_REF_SLUG}"
15
+ paths:
16
+ - .uv-cache/
17
+ - .venv/
18
+
19
+ .python_base:
20
+ image: python:3.14
21
+ before_script:
22
+ # TODO: This reference and include is a stopgap until we have the projects on pypi
23
+ - !reference [.clone_dependencies, before_script]
24
+ - pip install uv
25
+ - uv sync
26
+ - source .venv/bin/activate
27
+
28
+ test:
29
+ extends: .python_base
30
+ stage: test
31
+ script:
32
+ - pytest --cov --cov-report=term --cov-report=html --cov-report=xml --junitxml=report.xml -v
33
+ coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
34
+ artifacts:
35
+ when: always
36
+ reports:
37
+ junit: report.xml
38
+ coverage_report:
39
+ coverage_format: cobertura
40
+ path: coverage.xml
41
+ paths:
42
+ - report.xml
43
+ - .cov_html/
44
+ - coverage.xml
45
+ expire_in: 30 days
46
+ only:
47
+ - branches
48
+ - merge_requests
49
+ - tags
50
+
51
+ lint:ruff:
52
+ extends: .python_base
53
+ stage: lint
54
+ script:
55
+ - ruff check . --config .ruff.toml
56
+ - ruff format --check . --config .ruff.toml
57
+ allow_failure: false
58
+ only:
59
+ - branches
60
+ - merge_requests
61
+ - tags
62
+
63
+ lint:pyright:
64
+ extends: .python_base
65
+ stage: lint
66
+ variables:
67
+ PYRIGHT_PYTHON_FORCE_VERSION: latest
68
+ script:
69
+ - pyright
70
+ allow_failure: false
71
+ only:
72
+ - branches
73
+ - merge_requests
74
+ - tags
75
+
76
+ deploy:pypi:
77
+ stage: deploy
78
+ image: python:3.14
79
+ id_tokens:
80
+ PYPI_ID_TOKEN:
81
+ aud: pypi
82
+ variables:
83
+ UV_CACHE_DIR: /tmp/uv-cache
84
+ cache: []
85
+ before_script:
86
+ - pip install uv
87
+ script:
88
+ - uv build
89
+ - uv publish
90
+ artifacts:
91
+ paths:
92
+ - dist/
93
+ expire_in: 1 week
94
+ only:
95
+ - tags
@@ -0,0 +1,82 @@
1
+ # Source this file to set up the virtual environment
2
+ #
3
+ # > . .init_venv.sh
4
+ #
5
+ # To be used with our uv-based setup. Assumes python version and all dependencies are
6
+ # in pyproject.toml. Will finalize uv.sources editable libraries with uv pip compat.
7
+ #
8
+ # Once this has been done once, you can just use the normal virtual environment's
9
+ # 'activate' command to re-renter the virtual environment.
10
+ #
11
+ # You can also re-source this file to reinstall / update the project. Calls 'uv sync'
12
+ # and re-updates editable sources.
13
+
14
+ # Text output highlighting
15
+ bold=$(tput bold)
16
+ normal=$(tput sgr0)
17
+
18
+ VENV=".venv"
19
+ export PYRIGHT_PYTHON_FORCE_VERSION=latest
20
+
21
+ # Make sure we're out of any venvs
22
+ deactivate &> /dev/null
23
+
24
+ # Find if we have any editable local paths
25
+ regex="\{ *path *= *\".*\",.* *editable *= *true *\}"
26
+ MATCHES=$(grep -oP "$regex" pyproject.toml)
27
+ if [[ -n $MATCHES ]]; then
28
+ # We have locally editable installs. Check for editable mode setting
29
+ grep "config-settings *= *{ *editable_mode *= *\"compat\" *}" pyproject.toml > /dev/null
30
+ if [ $? -ne 0 ]; then
31
+ echo "${bold}ERROR: Locally editable package requested, but incorrect toml config${normal}"
32
+ echo
33
+ echo "Add to pyproject.toml:"
34
+ echo
35
+ echo "[tool.uv]"
36
+ echo "config-settings = { editable_mode = \"compat\" }"
37
+ echo
38
+ return 1
39
+ fi
40
+ fi
41
+
42
+ # Sync with uv
43
+ echo "${bold}Syncing environment${normal}"
44
+ # Check if installed
45
+ which uv &> /dev/null
46
+ if [ $? -ne 0 ]; then
47
+ while true; do
48
+ read -p "uv is not installed. Install it now? (y/n) " yn
49
+ case $yn in
50
+ [yY] )
51
+ break
52
+ ;;
53
+ [nN] )
54
+ echo "Exiting ..."
55
+ return 1
56
+ ;;
57
+ * )
58
+ echo "Invalid response. Please enter 'y' or 'n'"
59
+ ;;
60
+ esac
61
+ done
62
+ echo "Installing uv ..."
63
+ curl -LsSf https://astral.sh/uv/install.sh | sh
64
+ . $HOME/.local/bin/env
65
+ fi
66
+ uv sync
67
+
68
+ # activate and print version
69
+ echo "${bold}Activating environment${normal}"
70
+ . $VENV/bin/activate
71
+ $VENV/bin/python --version
72
+
73
+ # Install pre-commit scripts
74
+ echo "${bold}Installing git hooks${normal}"
75
+ pre-commit install
76
+ if [ $? -ne 0 ]; then
77
+ return 1
78
+ fi
79
+
80
+ # print final hints
81
+ echo
82
+ echo "$VENV activated. To deactivate, use ${bold}\"deactivate\".${normal}"
@@ -0,0 +1,40 @@
1
+ # See https://pre-commit.com for more information
2
+ # See https://pre-commit.com/hooks.html for more hooks
3
+ repos:
4
+ - repo: https://github.com/gitleaks/gitleaks
5
+ rev: v8.24.3
6
+ hooks:
7
+ - id: gitleaks
8
+ - repo: https://github.com/pre-commit/pre-commit-hooks
9
+ # Base pre-commit-provided hooks
10
+ rev: v6.0.0
11
+ hooks:
12
+ - id: trailing-whitespace
13
+ args: [ --markdown-linebreak-ext=md ]
14
+ exclude: '\.dt[012]$'
15
+ - id: end-of-file-fixer
16
+ exclude: '\.dt[012]$'
17
+ - id: check-added-large-files
18
+ - repo: local
19
+ hooks:
20
+ - id: ruff-check
21
+ name: ruff check
22
+ entry: ruff check --fix --config .ruff.toml
23
+ language: system
24
+ types: [python]
25
+ - id: ruff-format
26
+ name: ruff format
27
+ entry: ruff format
28
+ language: system
29
+ types: [python]
30
+ - id: pyright
31
+ name: pyright
32
+ entry: pyright
33
+ language: system
34
+ types: [python]
35
+ - id: unskipped
36
+ name: Check for pytest skipped tests commented back in
37
+ entry: python .pre-commit-unskipped.py
38
+ language: system
39
+ files: '\.py$'
40
+ stages: [pre-commit]
@@ -0,0 +1,38 @@
1
+ # ruff: noqa: T201
2
+ """Find all the unit tests and make sure none of the skips are commented in!
3
+
4
+ You can run this manually with:
5
+ > python .pre-commit-noskips.py
6
+ """
7
+
8
+ import sys
9
+ from pathlib import Path
10
+
11
+
12
+ def _main() -> None:
13
+ # Get the test directory, which should be adjascent to this script
14
+ script_dir = Path(__file__)
15
+ test_dir = script_dir.parent / "test"
16
+ if not test_dir.exists():
17
+ print("WARNING::: Didn't find a test directory!")
18
+ sys.exit(0)
19
+ tests = test_dir.rglob("test*.py")
20
+ found = False
21
+ for testfile in tests:
22
+ with testfile.open("r") as fp:
23
+ for idx, line in enumerate(fp, 1):
24
+ if line.strip().startswith("#") and (
25
+ "pytest.skip" in line or "pytest.mark.skip" in line
26
+ ):
27
+ print(
28
+ f"ERROR::: Line {idx} of {testfile.relative_to(test_dir)} "
29
+ "has a skip commented out:",
30
+ )
31
+ print(f" {idx}: {line}")
32
+ found = True
33
+ if found:
34
+ sys.exit(1) # Error4 aborts the commit
35
+
36
+
37
+ if __name__ == "__main__":
38
+ _main()
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,60 @@
1
+ extend = "pyproject.toml"
2
+
3
+ [lint]
4
+ select = ["ALL"]
5
+ #select = [
6
+ # # pycodestyle
7
+ # "E",
8
+ # # Pyflakes
9
+ # "F",
10
+ # # pyupgrade
11
+ # "UP",
12
+ # # flake8-bugbear
13
+ # "B",
14
+ # # flake8-simplify
15
+ # "SIM",
16
+ # # isort
17
+ # "I",
18
+ # # docstring
19
+ # "D",
20
+ # # TODO
21
+ # "TD",
22
+ #]
23
+
24
+ ignore = [
25
+ "D105", # Do not require magic method documentation
26
+ "ANN002", # Allow non-typed *args
27
+ "ANN003", # Allow non-typed **kwargs
28
+ "ANN204", # Do not require magic method documentation
29
+ "CPY", # Copyright notices
30
+ "EM101", # raw string in exception
31
+ "EM102", # fstrings in exceptions
32
+ "ERA001", # allow commented out code
33
+ "PERF203",# allow try-except in loops
34
+ "TRY003", # raise vanilla
35
+ "TD002", # TODO author
36
+ "TD003", # TODO link
37
+ "TD004", # TODO colon
38
+ "FIX001", # Fixme
39
+ "FIX002", # TODO
40
+ ]
41
+
42
+ [lint.extend-per-file-ignores]
43
+ "test/**/*.py" = [
44
+ "D100", # undocumented public module
45
+ "D103", # undocumented public function
46
+ "D104", # undocumented public package
47
+ "ANN001", # no type annotations for function arguments
48
+ "ANN201", # no return type for public function
49
+ "S101", # asserts allowed
50
+ "SLF001", # Allow private member access in unit tests
51
+ "PLR2004", # magic values allowed in comparisons
52
+ "PT011", # pytest.raises can be broad
53
+ "PT013", # allow sub-imports of pytest
54
+ "PLR0913", # allow many arguments in parameterized tests
55
+ ]
56
+
57
+ [lint.pydocstyle]
58
+ convention = "google"
59
+ ignore-var-parameters = true
60
+ ignore-decorators = ["typing.overload"]
@@ -0,0 +1,15 @@
1
+ {
2
+ "python.testing.pytestArgs": ["test"],
3
+ "python.testing.unittestEnabled": false,
4
+ "python.testing.pytestEnabled": true,
5
+ "editor.rulers": [88],
6
+ "[python]": {
7
+ "editor.formatOnSave": true,
8
+ "editor.defaultFormatter": "charliermarsh.ruff",
9
+ "editor.codeActionsOnSave": {
10
+ "source.fixAll": "explicit",
11
+ "source.organizeImports.ruff": "explicit"
12
+ }
13
+ },
14
+ "ruff.interpreter": ["${workspaceFolder}/.venv/bin/python"]
15
+ }
@@ -0,0 +1,113 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in contributing! This guide covers everything you need
4
+ to get started.
5
+
6
+ ## Setup
7
+
8
+ Requires **Python 3.14+** and **bash**.
9
+
10
+ ```bash
11
+ git clone <repo-url>
12
+ cd <repo>
13
+ . .init_venv.sh
14
+ ```
15
+
16
+ This creates a virtual environment with [uv](https://docs.astral.sh/uv/),
17
+ installs all dependencies (including editable local siblings), and sets up
18
+ pre-commit hooks. After the first run you can just activate the existing
19
+ environment:
20
+
21
+ ```bash
22
+ source .venv/bin/activate
23
+ ```
24
+
25
+ To start fresh, delete `.venv/` and re-source `.init_venv.sh`.
26
+
27
+ ## Running Tests
28
+
29
+ [pytest](https://docs.pytest.org/) with
30
+ [pytest-cov](https://pypi.org/project/pytest-cov/) for coverage:
31
+
32
+ ```bash
33
+ pytest --cov # terminal summary
34
+ pytest --cov --cov-report html # detailed HTML report in .cov_html/
35
+ ```
36
+
37
+ CI requires **70% minimum** coverage. Open the HTML report to see exactly which
38
+ lines are covered:
39
+
40
+ ```bash
41
+ xdg-open .cov_html/index.html # or: google-chrome, firefox
42
+ ```
43
+
44
+ ## Linting and Type Checking
45
+
46
+ ### Ruff
47
+
48
+ [Ruff](https://docs.astral.sh/ruff/) handles both linting and formatting. The
49
+ configuration selects **all rules** (`select = ["ALL"]`) with a small ignore
50
+ list in `.ruff.toml`.
51
+
52
+ ```bash
53
+ ruff check # lint
54
+ ruff format # format
55
+ ```
56
+
57
+ ### Pyright
58
+
59
+ [Pyright](https://microsoft.github.io/pyright/#/) for static type checking:
60
+
61
+ ```bash
62
+ pyright
63
+ ```
64
+
65
+ ### Pre-commit
66
+
67
+ All of the above run automatically on `git commit` via
68
+ [pre-commit](https://pre-commit.com/). If the commit fails, fix the issues,
69
+ re-stage, and commit again.
70
+
71
+ ```bash
72
+ pre-commit run --all-files # run manually against everything
73
+ ```
74
+
75
+ > **Tip:** To force a commit past hooks (e.g. work-in-progress), use
76
+ > `git commit -n`. CI will still enforce the same checks.
77
+
78
+ ## Code Style
79
+
80
+ - **Docstrings**: [Google convention](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings)
81
+ - **Type hints**: Required on all public function signatures
82
+ - **Line length**: 88 characters max
83
+ - **Formatting**: Let `ruff format` handle it
84
+ - **Imports**: All at the top of the file, organized by ruff's isort rules
85
+
86
+ ## Submitting Changes
87
+
88
+ 1. Create a branch from `main`
89
+ 2. Make your changes with tests
90
+ 3. Ensure `pytest --cov` passes with >= 70% coverage
91
+ 4. Ensure `pre-commit run --all-files` passes
92
+ 5. Open a merge request against `main`
93
+
94
+ ## IDE Setup (VS Code)
95
+
96
+ Install the [Ruff extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff)
97
+ by Astral and add to your `settings.json`:
98
+
99
+ ```json
100
+ {
101
+ "[python]": {
102
+ "editor.formatOnSave": true,
103
+ "editor.defaultFormatter": "charliermarsh.ruff",
104
+ "editor.codeActionsOnSave": {
105
+ "source.fixAll": "explicit",
106
+ "source.organizeImports.ruff": "explicit"
107
+ }
108
+ },
109
+ "ruff.interpreter": ["${workspaceFolder}/.venv/bin/python"]
110
+ }
111
+ ```
112
+
113
+ Pyright is included in VS Code's Pylance extension by default.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 GeoSol Research Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.