pg-sui 1.6.14a4__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 (162) hide show
  1. pg_sui-1.6.14a4/.dockerignore +16 -0
  2. pg_sui-1.6.14a4/.gitattributes +1 -0
  3. pg_sui-1.6.14a4/.github/workflows/conda.yaml +147 -0
  4. pg_sui-1.6.14a4/.github/workflows/docker.yaml +194 -0
  5. pg_sui-1.6.14a4/.github/workflows/release.yaml +93 -0
  6. pg_sui-1.6.14a4/.gitignore +205 -0
  7. pg_sui-1.6.14a4/.readthedocs.yaml +26 -0
  8. pg_sui-1.6.14a4/.vscode/launch.json +8 -0
  9. pg_sui-1.6.14a4/.vscode/settings.json +86 -0
  10. pg_sui-1.6.14a4/Dockerfile +69 -0
  11. pg_sui-1.6.14a4/LICENSE +674 -0
  12. pg_sui-1.6.14a4/MANIFEST.in +25 -0
  13. pg_sui-1.6.14a4/PKG-INFO +344 -0
  14. pg_sui-1.6.14a4/README.md +273 -0
  15. pg_sui-1.6.14a4/changelog.md +238 -0
  16. pg_sui-1.6.14a4/conda/recipe/bld.bat +4 -0
  17. pg_sui-1.6.14a4/conda/recipe/conda_build_config.yaml +17 -0
  18. pg_sui-1.6.14a4/conda/recipe/meta.yaml +63 -0
  19. pg_sui-1.6.14a4/configs/config.yaml +63 -0
  20. pg_sui-1.6.14a4/docs/build/Makefile +20 -0
  21. pg_sui-1.6.14a4/docs/build/_static/custom.css +0 -0
  22. pg_sui-1.6.14a4/docs/build/_templates +0 -0
  23. pg_sui-1.6.14a4/docs/build/about.rst +78 -0
  24. pg_sui-1.6.14a4/docs/build/changelog.rst +277 -0
  25. pg_sui-1.6.14a4/docs/build/conf.py +127 -0
  26. pg_sui-1.6.14a4/docs/build/gui.rst +61 -0
  27. pg_sui-1.6.14a4/docs/build/implement_new_models.rst +449 -0
  28. pg_sui-1.6.14a4/docs/build/imputer_methods.rst +431 -0
  29. pg_sui-1.6.14a4/docs/build/index.rst +31 -0
  30. pg_sui-1.6.14a4/docs/build/install.rst +58 -0
  31. pg_sui-1.6.14a4/docs/build/make.bat +35 -0
  32. pg_sui-1.6.14a4/docs/build/modules.rst +7 -0
  33. pg_sui-1.6.14a4/docs/build/non_ml_imputers.rst +173 -0
  34. pg_sui-1.6.14a4/docs/build/pgsui.data_processing.rst +34 -0
  35. pg_sui-1.6.14a4/docs/build/pgsui.impute.rst +19 -0
  36. pg_sui-1.6.14a4/docs/build/pgsui.impute.supervised.imputers.rst +29 -0
  37. pg_sui-1.6.14a4/docs/build/pgsui.impute.supervised.rst +12 -0
  38. pg_sui-1.6.14a4/docs/build/pgsui.impute.unsupervised.imputers.rst +43 -0
  39. pg_sui-1.6.14a4/docs/build/pgsui.impute.unsupervised.models.rst +48 -0
  40. pg_sui-1.6.14a4/docs/build/pgsui.impute.unsupervised.rst +28 -0
  41. pg_sui-1.6.14a4/docs/build/pgsui.rst +12 -0
  42. pg_sui-1.6.14a4/docs/build/pgsui.utils.rst +33 -0
  43. pg_sui-1.6.14a4/docs/build/supervised_imputers.rst +133 -0
  44. pg_sui-1.6.14a4/docs/build/tutorial.rst +518 -0
  45. pg_sui-1.6.14a4/docs/build/unsupervised_imputers.rst +134 -0
  46. pg_sui-1.6.14a4/environment.yml +7 -0
  47. pg_sui-1.6.14a4/img/NLPCA_Model_Architecture.svg +1143 -0
  48. pg_sui-1.6.14a4/img/VAE_Model_Architecture_rotated.svg +1870 -0
  49. pg_sui-1.6.14a4/img/pgsui-logo-faded-thumb.png +0 -0
  50. pg_sui-1.6.14a4/img/pgsui-logo-faded.png +0 -0
  51. pg_sui-1.6.14a4/img/pgsui-logo-notfaded.png +0 -0
  52. pg_sui-1.6.14a4/multiqc_config.yaml +85 -0
  53. pg_sui-1.6.14a4/notebooks/run_pgsui_dev.ipynb +279 -0
  54. pg_sui-1.6.14a4/package-lock.json +10 -0
  55. pg_sui-1.6.14a4/pg_sui.egg-info/PKG-INFO +344 -0
  56. pg_sui-1.6.14a4/pg_sui.egg-info/SOURCES.txt +160 -0
  57. pg_sui-1.6.14a4/pg_sui.egg-info/dependency_links.txt +1 -0
  58. pg_sui-1.6.14a4/pg_sui.egg-info/entry_points.txt +4 -0
  59. pg_sui-1.6.14a4/pg_sui.egg-info/requires.txt +41 -0
  60. pg_sui-1.6.14a4/pg_sui.egg-info/top_level.txt +1 -0
  61. pg_sui-1.6.14a4/pgsui/__init__.py +44 -0
  62. pg_sui-1.6.14a4/pgsui/_version.py +34 -0
  63. pg_sui-1.6.14a4/pgsui/cli.py +909 -0
  64. pg_sui-1.6.14a4/pgsui/data_processing/__init__.py +0 -0
  65. pg_sui-1.6.14a4/pgsui/data_processing/config.py +565 -0
  66. pg_sui-1.6.14a4/pgsui/data_processing/containers.py +1424 -0
  67. pg_sui-1.6.14a4/pgsui/data_processing/transformers.py +781 -0
  68. pg_sui-1.6.14a4/pgsui/electron/app/__init__.py +0 -0
  69. pg_sui-1.6.14a4/pgsui/electron/app/__main__.py +5 -0
  70. pg_sui-1.6.14a4/pgsui/electron/app/extra-resources/.gitkeep +1 -0
  71. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/1024x1024.png +0 -0
  72. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/128x128.png +0 -0
  73. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/16x16.png +0 -0
  74. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/24x24.png +0 -0
  75. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/256x256.png +0 -0
  76. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/32x32.png +0 -0
  77. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/48x48.png +0 -0
  78. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/512x512.png +0 -0
  79. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/64x64.png +0 -0
  80. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/icon.icns +0 -0
  81. pg_sui-1.6.14a4/pgsui/electron/app/icons/icons/icon.ico +0 -0
  82. pg_sui-1.6.14a4/pgsui/electron/app/main.js +227 -0
  83. pg_sui-1.6.14a4/pgsui/electron/app/package-lock.json +6894 -0
  84. pg_sui-1.6.14a4/pgsui/electron/app/package.json +51 -0
  85. pg_sui-1.6.14a4/pgsui/electron/app/preload.js +15 -0
  86. pg_sui-1.6.14a4/pgsui/electron/app/server.py +157 -0
  87. pg_sui-1.6.14a4/pgsui/electron/app/ui/logo.png +0 -0
  88. pg_sui-1.6.14a4/pgsui/electron/app/ui/renderer.js +131 -0
  89. pg_sui-1.6.14a4/pgsui/electron/app/ui/styles.css +59 -0
  90. pg_sui-1.6.14a4/pgsui/electron/app/ui/ui_shim.js +72 -0
  91. pg_sui-1.6.14a4/pgsui/electron/bootstrap.py +43 -0
  92. pg_sui-1.6.14a4/pgsui/electron/launch.py +57 -0
  93. pg_sui-1.6.14a4/pgsui/electron/package.json +14 -0
  94. pg_sui-1.6.14a4/pgsui/example_data/__init__.py +0 -0
  95. pg_sui-1.6.14a4/pgsui/example_data/phylip_files/__init__.py +0 -0
  96. pg_sui-1.6.14a4/pgsui/example_data/phylip_files/test.phy +118 -0
  97. pg_sui-1.6.14a4/pgsui/example_data/popmaps/__init__.py +0 -0
  98. pg_sui-1.6.14a4/pgsui/example_data/popmaps/phylogen_nomx.popmap +203 -0
  99. pg_sui-1.6.14a4/pgsui/example_data/structure_files/__init__.py +0 -0
  100. pg_sui-1.6.14a4/pgsui/example_data/structure_files/test.pops.2row.allsites.str +234 -0
  101. pg_sui-1.6.14a4/pgsui/example_data/vcf_files/phylogen_subset14K.vcf.gz +0 -0
  102. pg_sui-1.6.14a4/pgsui/example_data/vcf_files/phylogen_subset14K.vcf.gz.tbi +0 -0
  103. pg_sui-1.6.14a4/pgsui/impute/__init__.py +0 -0
  104. pg_sui-1.6.14a4/pgsui/impute/deterministic/imputers/allele_freq.py +725 -0
  105. pg_sui-1.6.14a4/pgsui/impute/deterministic/imputers/mode.py +844 -0
  106. pg_sui-1.6.14a4/pgsui/impute/deterministic/imputers/nmf.py +221 -0
  107. pg_sui-1.6.14a4/pgsui/impute/deterministic/imputers/phylo.py +973 -0
  108. pg_sui-1.6.14a4/pgsui/impute/deterministic/imputers/ref_allele.py +669 -0
  109. pg_sui-1.6.14a4/pgsui/impute/supervised/__init__.py +0 -0
  110. pg_sui-1.6.14a4/pgsui/impute/supervised/base.py +343 -0
  111. pg_sui-1.6.14a4/pgsui/impute/supervised/imputers/__init__.py +0 -0
  112. pg_sui-1.6.14a4/pgsui/impute/supervised/imputers/hist_gradient_boosting.py +317 -0
  113. pg_sui-1.6.14a4/pgsui/impute/supervised/imputers/random_forest.py +291 -0
  114. pg_sui-1.6.14a4/pgsui/impute/unsupervised/__init__.py +0 -0
  115. pg_sui-1.6.14a4/pgsui/impute/unsupervised/base.py +1118 -0
  116. pg_sui-1.6.14a4/pgsui/impute/unsupervised/callbacks.py +116 -0
  117. pg_sui-1.6.14a4/pgsui/impute/unsupervised/imputers/__init__.py +0 -0
  118. pg_sui-1.6.14a4/pgsui/impute/unsupervised/imputers/autoencoder.py +1285 -0
  119. pg_sui-1.6.14a4/pgsui/impute/unsupervised/imputers/nlpca.py +1554 -0
  120. pg_sui-1.6.14a4/pgsui/impute/unsupervised/imputers/ubp.py +1575 -0
  121. pg_sui-1.6.14a4/pgsui/impute/unsupervised/imputers/vae.py +1228 -0
  122. pg_sui-1.6.14a4/pgsui/impute/unsupervised/loss_functions.py +261 -0
  123. pg_sui-1.6.14a4/pgsui/impute/unsupervised/models/__init__.py +0 -0
  124. pg_sui-1.6.14a4/pgsui/impute/unsupervised/models/autoencoder_model.py +293 -0
  125. pg_sui-1.6.14a4/pgsui/impute/unsupervised/models/nlpca_model.py +206 -0
  126. pg_sui-1.6.14a4/pgsui/impute/unsupervised/models/ubp_model.py +200 -0
  127. pg_sui-1.6.14a4/pgsui/impute/unsupervised/models/vae_model.py +349 -0
  128. pg_sui-1.6.14a4/pgsui/impute/unsupervised/nn_scorers.py +255 -0
  129. pg_sui-1.6.14a4/pgsui/utils/__init__.py +0 -0
  130. pg_sui-1.6.14a4/pgsui/utils/classification_viz.py +608 -0
  131. pg_sui-1.6.14a4/pgsui/utils/logging_utils.py +22 -0
  132. pg_sui-1.6.14a4/pgsui/utils/misc.py +73 -0
  133. pg_sui-1.6.14a4/pgsui/utils/plotting.py +1116 -0
  134. pg_sui-1.6.14a4/pgsui/utils/pretty_metrics.py +290 -0
  135. pg_sui-1.6.14a4/pgsui/utils/scorers.py +297 -0
  136. pg_sui-1.6.14a4/pyproject.toml +125 -0
  137. pg_sui-1.6.14a4/scripts/build_gui_dists.zsh +56 -0
  138. pg_sui-1.6.14a4/scripts/download_training_data.zsh +21 -0
  139. pg_sui-1.6.14a4/scripts/pg_sui.py +254 -0
  140. pg_sui-1.6.14a4/scripts/run_iqtree.zsh +18 -0
  141. pg_sui-1.6.14a4/scripts/start_pgsui.sh +9 -0
  142. pg_sui-1.6.14a4/scripts/stop_pgsui.sh +3 -0
  143. pg_sui-1.6.14a4/scripts/summarize_input_metadata.py +53 -0
  144. pg_sui-1.6.14a4/scripts/vcf2phy.py +87 -0
  145. pg_sui-1.6.14a4/scripts/vcf2phy.zsh +14 -0
  146. pg_sui-1.6.14a4/setup.cfg +4 -0
  147. pg_sui-1.6.14a4/snpiosp/__init__.py +0 -0
  148. pg_sui-1.6.14a4/snpiosp/compare_dataset_stats.py +898 -0
  149. pg_sui-1.6.14a4/snpiosp/run_snpiosp.py +478 -0
  150. pg_sui-1.6.14a4/snpiosp/snpiosp.py +516 -0
  151. pg_sui-1.6.14a4/tests/conftest.py +147 -0
  152. pg_sui-1.6.14a4/tests/test_config.py +98 -0
  153. pg_sui-1.6.14a4/tests/test_deterministic_imputers.py +63 -0
  154. pg_sui-1.6.14a4/tests/test_imputers_unsupervised.py +110 -0
  155. pg_sui-1.6.14a4/tests/test_scorers.py +62 -0
  156. pg_sui-1.6.14a4/tests/test_transformers.py +128 -0
  157. pg_sui-1.6.14a4/workflow/envs/tree_sim.yml +14 -0
  158. pg_sui-1.6.14a4/workflow/profile/config.yaml +10 -0
  159. pg_sui-1.6.14a4/workflow/run_sim1.smk +222 -0
  160. pg_sui-1.6.14a4/workflow/scripts/sim_treeparams.py +420 -0
  161. pg_sui-1.6.14a4/workflow/sim1_config.yaml +10 -0
  162. pg_sui-1.6.14a4/workflow/t0.01_c0.1_a0.0_gtrgamma.phylip +81 -0
@@ -0,0 +1,16 @@
1
+ .git
2
+ __pycache__/
3
+ .venv/
4
+ dist/
5
+ build/
6
+ *.egg-info/
7
+ pgsui/electron/app/dist/
8
+ .venv/
9
+ .vscode/
10
+ .pytest_cache/
11
+ .codex/
12
+ *.pyc
13
+ *.pyo
14
+ *.pyd
15
+ *.egg-info/
16
+
@@ -0,0 +1 @@
1
+ *.ipynb linguist-generated
@@ -0,0 +1,147 @@
1
+ name: conda
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ run_conda_build:
10
+ description: "Build and upload conda package"
11
+ required: false
12
+ default: "true"
13
+
14
+ jobs:
15
+ tests:
16
+ name: Unit tests (pip)
17
+ runs-on: ubuntu-latest
18
+ strategy:
19
+ matrix:
20
+ python-version: ["3.11", "3.12"]
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Clean test artifacts
26
+ run: rm -rf dist build .pytest_cache tmp_test_output
27
+
28
+ - name: Setup Python
29
+ uses: actions/setup-python@v5
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+ cache: pip
33
+
34
+ - name: Install dependencies
35
+ env:
36
+ MPLCONFIGDIR: ${{ runner.temp }}/mpl
37
+ run: |
38
+ python -m pip install -U pip
39
+ python -m pip install ".[dev]"
40
+
41
+ - name: Run tests
42
+ env:
43
+ MPLCONFIGDIR: ${{ runner.temp }}/mpl
44
+ run: pytest -q
45
+
46
+ clean:
47
+ name: Clean conda build cache
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - name: Set up micromamba
51
+ uses: mamba-org/setup-micromamba@v1
52
+ with:
53
+ environment-name: conda-clean
54
+ create-args: >-
55
+ micromamba
56
+ init-shell: bash
57
+
58
+ - name: Clean conda build cache
59
+ run: |
60
+ micromamba clean --all --yes
61
+
62
+ conda-package:
63
+ name: Build conda package
64
+ runs-on: ${{ matrix.os }}
65
+ needs: [tests, clean]
66
+ if: |
67
+ startsWith(github.ref, 'refs/tags/v') ||
68
+ (github.event_name == 'workflow_dispatch' && github.event.inputs.run_conda_build == 'true')
69
+ strategy:
70
+ fail-fast: false
71
+ matrix:
72
+ include:
73
+ - os: ubuntu-latest
74
+ subdir: linux-64
75
+ - os: macos-latest
76
+ subdir: osx-arm64
77
+ defaults:
78
+ run:
79
+ shell: bash -l {0}
80
+ env:
81
+ MPLCONFIGDIR: /tmp/mpl
82
+ # Resolve token from common secret names to avoid misconfiguration
83
+ UPLOAD_TOKEN: ${{ secrets.PGSUI_UPLOAD_TOKEN || secrets.CONDA_UPLOAD_TOKEN }}
84
+ CONDA_SUBDIR: ${{ matrix.subdir }}
85
+ steps:
86
+ - name: Checkout
87
+ uses: actions/checkout@v4
88
+ with:
89
+ fetch-depth: 0
90
+
91
+ - name: Set up micromamba
92
+ uses: mamba-org/setup-micromamba@v1
93
+ with:
94
+ environment-name: conda-build
95
+ create-args: >-
96
+ python=3.11
97
+ pip
98
+ conda-build
99
+ anaconda-client
100
+ -c conda-forge
101
+ -c defaults
102
+ init-shell: bash
103
+ cache-environment: true
104
+
105
+ - name: Build recipe
106
+ env:
107
+ PKG_VERSION: ${{ github.ref_name }}
108
+ run: |
109
+ set -euo pipefail
110
+ RAW_VERSION=${PKG_VERSION:-}
111
+ CLEAN_VERSION=${RAW_VERSION#v}
112
+ # Conda versions cannot contain hyphens or plus signs; normalize to dots (e.g., v1.6.14-dev2 -> 1.6.14.dev2)
113
+ CLEAN_VERSION=${CLEAN_VERSION//-/.}
114
+ CLEAN_VERSION=${CLEAN_VERSION//+/.}
115
+ export PKG_VERSION=${CLEAN_VERSION:-1.6.8}
116
+ export SETUPTOOLS_SCM_PRETEND_VERSION=${PKG_VERSION}
117
+ # Help conda/jinja resolve version even if .git metadata is absent
118
+ export GIT_DESCRIBE_TAG=${PKG_VERSION}
119
+ echo "Building conda package version: ${PKG_VERSION} for ${CONDA_SUBDIR}"
120
+ conda build conda/recipe --output-folder conda/dist -c btmartin721 -c conda-forge -c bioconda -c pytorch -c defaults
121
+
122
+ - name: Upload conda artifacts
123
+ uses: actions/upload-artifact@v4
124
+ with:
125
+ name: conda-packages-${{ matrix.subdir }}
126
+ path: |
127
+ conda/dist/**/*.tar.bz2
128
+ conda/dist/**/*.conda
129
+
130
+ - name: Verify upload token
131
+ run: |
132
+ set -euo pipefail
133
+ if [[ -z "${UPLOAD_TOKEN:-}" ]]; then
134
+ echo "No Anaconda token available. Set one of the secrets: PGSUI_UPLOAD_TOKEN, CONDA_UPLOAD_TOKEN, ANACONDA_API_TOKEN, ANACONDA_TOKEN, or ANACONDA_UPLOAD_TOKEN."
135
+ exit 1
136
+ fi
137
+ echo "::add-mask::${UPLOAD_TOKEN}"
138
+
139
+ - name: Publish to Anaconda
140
+ run: |
141
+ set -euo pipefail
142
+ mapfile -t files < <(find conda/dist -type f \( -name '*.tar.bz2' -o -name '*.conda' \))
143
+ if [[ ${#files[@]} -eq 0 ]]; then
144
+ echo "No conda artifacts found to upload."
145
+ exit 1
146
+ fi
147
+ anaconda -t "$UPLOAD_TOKEN" upload --label main --user btmartin721 "${files[@]}"
@@ -0,0 +1,194 @@
1
+ name: docker
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+
9
+ env:
10
+ IMAGE_NAME: btmartin721/pg-sui
11
+
12
+ jobs:
13
+ tests:
14
+ name: Unit tests (pip)
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ python-version: ["3.11", "3.12"]
19
+ steps:
20
+ - name: Checkout
21
+ uses: actions/checkout@v4
22
+
23
+ - name: Clean test artifacts
24
+ run: rm -rf dist build .pytest_cache tmp_test_output
25
+
26
+ - name: Setup Python
27
+ uses: actions/setup-python@v5
28
+ with:
29
+ python-version: ${{ matrix.python-version }}
30
+ cache: pip
31
+
32
+ - name: Install dependencies
33
+ env:
34
+ MPLCONFIGDIR: ${{ runner.temp }}/mpl
35
+ run: |
36
+ python -m pip install -U pip
37
+ python -m pip install ".[dev]"
38
+
39
+ - name: Run tests
40
+ env:
41
+ MPLCONFIGDIR: ${{ runner.temp }}/mpl
42
+ run: pytest -q
43
+
44
+ build:
45
+ name: Build Docker image
46
+ runs-on: ubuntu-latest
47
+ needs: tests
48
+ permissions:
49
+ contents: read
50
+ packages: write
51
+ env:
52
+ DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_BTMARTIN721 }}
53
+ DOCKERHUB_USERNAME_SECRET: ${{ secrets.DOCKERHUB_USERNAME }}
54
+ steps:
55
+ - name: Maximize disk space
56
+ run: |
57
+ set -euxo pipefail
58
+ echo "Disk usage before cleanup:"
59
+ df -h
60
+ sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL /home/linuxbrew/.linuxbrew || true
61
+ sudo apt-get clean
62
+ docker system prune -af || true
63
+ echo "Disk usage after cleanup:"
64
+ df -h
65
+
66
+ - name: Wait for PyPI publish workflow (tag pushes)
67
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
68
+ env:
69
+ GH_TOKEN: ${{ github.token }}
70
+ TARGET_SHA: ${{ github.sha }}
71
+ run: |
72
+ set -euo pipefail
73
+
74
+ workflow_id=$(gh api repos/${{ github.repository }}/actions/workflows --jq '.workflows[] | select(.name=="publish-pypi") | .id' | head -n 1)
75
+ if [[ -z "${workflow_id:-}" ]]; then
76
+ echo "Could not find publish-pypi workflow id in repository workflows."
77
+ exit 1
78
+ fi
79
+
80
+ echo "Waiting for publish-pypi workflow (id: $workflow_id) to finish for SHA $TARGET_SHA"
81
+
82
+ for attempt in {1..40}; do
83
+ run_info=$(gh api "repos/${{ github.repository }}/actions/workflows/${workflow_id}/runs" \
84
+ --jq 'first(.workflow_runs[] | select(.head_sha=="'"${TARGET_SHA}"'"))')
85
+
86
+ if [[ -z "${run_info:-}" || "$run_info" == "null" ]]; then
87
+ echo "No matching publish-pypi run yet (attempt $attempt/40); sleeping 30s..."
88
+ sleep 30
89
+ continue
90
+ fi
91
+
92
+ status=$(echo "$run_info" | jq -r '.status')
93
+ conclusion=$(echo "$run_info" | jq -r '.conclusion // ""')
94
+ url=$(echo "$run_info" | jq -r '.html_url')
95
+
96
+ echo "publish-pypi workflow run: $url (status=$status, conclusion=$conclusion)"
97
+
98
+ if [[ "$status" == "completed" ]]; then
99
+ if [[ "$conclusion" == "success" ]]; then
100
+ echo "publish-pypi workflow completed successfully."
101
+ exit 0
102
+ else
103
+ echo "publish-pypi workflow finished with conclusion=$conclusion"
104
+ exit 1
105
+ fi
106
+ fi
107
+
108
+ sleep 30
109
+ done
110
+
111
+ echo "Timed out waiting for publish-pypi workflow to complete."
112
+ exit 1
113
+
114
+ - name: Resolve Docker Hub username
115
+ id: dockerhub-creds
116
+ if: github.event_name != 'pull_request'
117
+ run: |
118
+ if [[ -n "${DOCKERHUB_USERNAME_SECRET}" ]]; then
119
+ echo "username=${DOCKERHUB_USERNAME_SECRET}" >> "$GITHUB_OUTPUT"
120
+ elif [[ -n "${{ vars.DOCKERHUB_USERNAME }}" ]]; then
121
+ echo "username=${{ vars.DOCKERHUB_USERNAME }}" >> "$GITHUB_OUTPUT"
122
+ else
123
+ echo "username=" >> "$GITHUB_OUTPUT"
124
+ fi
125
+
126
+ - name: Checkout
127
+ uses: actions/checkout@v4
128
+
129
+ - name: Set up QEMU
130
+ uses: docker/setup-qemu-action@v3
131
+
132
+ - name: Set up Docker Buildx
133
+ id: buildx
134
+ uses: docker/setup-buildx-action@v3
135
+ with:
136
+ install: true
137
+ driver-opts: network=host
138
+
139
+ - name: Derive version
140
+ id: version
141
+ run: |
142
+ if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
143
+ echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
144
+ fi
145
+
146
+ - name: Docker metadata
147
+ id: meta
148
+ uses: docker/metadata-action@v5
149
+ with:
150
+ images: ${{ env.IMAGE_NAME }}
151
+ tags: |
152
+ type=semver,pattern={{version}},value=${{ steps.version.outputs.version }},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
153
+ type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
154
+ type=raw,value=pr-${{ github.event.pull_request.number }},enable=${{ github.event_name == 'pull_request' }}
155
+ type=ref,event=branch
156
+ type=sha,format=short
157
+
158
+ - name: Log in to Docker Hub
159
+ if: github.event_name != 'pull_request' && steps.dockerhub-creds.outputs.username != '' && env.DOCKERHUB_PASSWORD != ''
160
+ uses: docker/login-action@v3
161
+ with:
162
+ username: ${{ steps.dockerhub-creds.outputs.username }}
163
+ password: ${{ env.DOCKERHUB_PASSWORD }}
164
+
165
+ - name: Warn about missing Docker Hub credentials
166
+ if: github.event_name != 'pull_request' && (steps.dockerhub-creds.outputs.username == '' || env.DOCKERHUB_PASSWORD == '')
167
+ run: |
168
+ echo "Docker Hub credentials not provided; skipping login. Push will fail without credentials."
169
+
170
+ - name: Build and push
171
+ uses: docker/build-push-action@v5
172
+ with:
173
+ context: .
174
+ file: Dockerfile
175
+ # Build single-arch when loading for PRs; multi-arch only for tag pushes.
176
+ platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || 'linux/amd64,linux/arm64' }}
177
+ push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && env.DOCKERHUB_PASSWORD != '' && steps.dockerhub-creds.outputs.username != '' }}
178
+ load: ${{ github.event_name == 'pull_request' }}
179
+ builder: ${{ steps.buildx.outputs.name }}
180
+ tags: ${{ steps.meta.outputs.tags }}
181
+ labels: ${{ steps.meta.outputs.labels }}
182
+ provenance: false
183
+ cache-from: type=gha
184
+ cache-to: type=gha,mode=max
185
+
186
+ - name: Smoke test image
187
+ if: github.event_name == 'pull_request'
188
+ run: |
189
+ image=$(echo "${{ steps.meta.outputs.tags }}" | head -n 1)
190
+ docker run --rm "$image" pg-sui --help
191
+
192
+ - name: Confirm Docker image built
193
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
194
+ run: 'echo "Docker image pushed with tags: ${{ steps.meta.outputs.tags }}"'
@@ -0,0 +1,93 @@
1
+ name: publish-pypi
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ tests:
11
+ name: Unit tests (pip)
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ["3.11", "3.12"]
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Clean test artifacts
21
+ run: rm -rf dist build .pytest_cache tmp_test_output
22
+
23
+ - name: Setup Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+ cache: pip
28
+
29
+ - name: Install dependencies
30
+ env:
31
+ MPLCONFIGDIR: ${{ runner.temp }}/mpl
32
+ run: |
33
+ python -m pip install -U pip
34
+ python -m pip install ".[dev]"
35
+
36
+ - name: Run tests
37
+ env:
38
+ MPLCONFIGDIR: ${{ runner.temp }}/mpl
39
+ run: pytest -q
40
+
41
+ build-and-publish:
42
+ runs-on: ubuntu-latest
43
+ needs: tests
44
+ permissions:
45
+ contents: write
46
+ steps:
47
+ - name: Checkout
48
+ uses: actions/checkout@v4
49
+ with:
50
+ fetch-depth: 0 # setuptools-scm needs the tags
51
+
52
+ - name: Setup Python
53
+ uses: actions/setup-python@v5
54
+ with:
55
+ python-version: "3.12"
56
+
57
+ - name: Install build deps
58
+ run: |
59
+ python -m pip install -U pip
60
+ pip install build twine
61
+
62
+ - name: Extract version from tag
63
+ id: version
64
+ run: |
65
+ echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
66
+ echo "Publishing PG-SUI version ${GITHUB_REF_NAME#v}"
67
+
68
+ - name: Build
69
+ run: |
70
+ rm -rf dist/
71
+ python -m build
72
+
73
+ - name: Publish to TestPyPI
74
+ env:
75
+ TWINE_USERNAME: __token__
76
+ TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
77
+ run: |
78
+ twine upload --non-interactive --skip-existing --repository testpypi dist/*
79
+
80
+ - name: Publish to PyPI
81
+ env:
82
+ TWINE_USERNAME: __token__
83
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
84
+ run: |
85
+ twine upload --non-interactive --skip-existing dist/*
86
+
87
+ - name: Create GitHub release
88
+ uses: softprops/action-gh-release@v1
89
+ with:
90
+ tag_name: ${{ github.ref_name }}
91
+ name: Release ${{ github.ref_name }}
92
+ body: |
93
+ Automated release for PG-SUI ${{ github.ref_name }}.
@@ -0,0 +1,205 @@
1
+ # ======================================================
2
+ # Python: bytecode / caches / compiled artifacts
3
+ # ======================================================
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+ *.so
8
+
9
+ # ======================================================
10
+ # Python: packaging / build artifacts
11
+ # ======================================================
12
+ .Python
13
+ *.egg-info/
14
+ *.egg
15
+ dist/
16
+ conda/dist/
17
+ conda-bld/
18
+ *.whl
19
+ *.manifest
20
+ *.spec
21
+ _version.py
22
+
23
+ # ======================================================
24
+ # Python: virtual environments
25
+ # ======================================================
26
+ .venv/
27
+ .venv-test-docker/
28
+
29
+ # ======================================================
30
+ # Python: type checkers
31
+ # ======================================================
32
+ .mypy_cache/
33
+ dmypy.json
34
+ dmypy.log
35
+ .pyre/
36
+ .pytype/
37
+
38
+ # ======================================================
39
+ # Python: testing / coverage
40
+ # ======================================================
41
+ .cache/
42
+ .pytest_cache/
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ old_tests/
54
+ test_output/
55
+
56
+ # ======================================================
57
+ # Python / ML frameworks
58
+ # ======================================================
59
+ *.pt
60
+ *.pth
61
+
62
+ # ======================================================
63
+ # Notebooks / interactive environments
64
+ # ======================================================
65
+ .ipynb_checkpoints/
66
+ profile_default/
67
+ ipython_config.py
68
+
69
+ # ======================================================
70
+ # Documentation / site builds
71
+ # ======================================================
72
+ # Sphinx
73
+ docs/_build/
74
+ docs/build/_build/
75
+ pgsui/docs/_build/
76
+ **/doctrees/
77
+ *.doctree
78
+ doctrees/
79
+ *_build/
80
+ .buildinfo
81
+
82
+ # mkdocs
83
+ /site
84
+
85
+ # Other doc/html outputs
86
+ html/
87
+ *.html
88
+
89
+ # ======================================================
90
+ # Web / Node / Electron
91
+ # ======================================================
92
+ **/node_modules/
93
+ pgsui/electron/app/dist/
94
+ pgsui_electron_logs/
95
+ .codex/
96
+
97
+ # ======================================================
98
+ # IDEs / editors
99
+ # ======================================================
100
+ .idea/
101
+ .spyderproject
102
+ .spyproject
103
+ .ropeproject
104
+
105
+ # ======================================================
106
+ # OS / misc
107
+ # ======================================================
108
+ .DS_Store
109
+ *.log
110
+ *.zip
111
+
112
+ # ======================================================
113
+ # Framework-specific leftovers (kept from template)
114
+ # ======================================================
115
+ # Django
116
+ local_settings.py
117
+ db.sqlite3
118
+
119
+ # Flask
120
+ instance/
121
+ .webassets-cache
122
+
123
+ # Scrapy
124
+ .scrapy
125
+
126
+ # PyBuilder
127
+ target/
128
+
129
+ # ======================================================
130
+ # Project-specific outputs
131
+ # ======================================================
132
+ pgsui_output/
133
+ snpio_output/
134
+ pgsui_*_output/
135
+ autoencoder_*_output/
136
+ snpio_simulated_unlinked_output/
137
+ sim_unlinked_output/
138
+ sim_results/
139
+ sim_results/*
140
+ summarize/
141
+ simulation/
142
+ simulation/*
143
+ sim_results/
144
+ *14K.vcf_output/
145
+
146
+ # Training / data folders
147
+ ./training_data/
148
+ .training_data.nosync/
149
+ training_data_2
150
+ training_data_2*
151
+
152
+ # Other tool outputs / one-offs
153
+ monomorphic_sites_mqc.txt
154
+ vcf_attributes.h5
155
+ dnasp_summary_plots.cleaned.csv
156
+
157
+ # ======================================================
158
+ # Project-specific files to ignore (one-off inputs/trees)
159
+ # ======================================================
160
+ DEPRECATED*.py
161
+ BOX.vcf
162
+ BOX2.vcf
163
+ BOX_concat_goodOnly_N214.nex
164
+ BOX_phylogen_dataset_output/
165
+ box_scf.cf.tree
166
+ partitioned_all.contree
167
+ partitioned_all.iqtree
168
+ coala_sims.R
169
+ sim_treeparams.py
170
+ simulate_rad.py
171
+ simulate_wgs.py
172
+ summarize_results.zsh
173
+ run_sumstats.zsh
174
+ run_52.zsh
175
+ training_data/
176
+ validation_inputs/
177
+ validation_inputs_phylip/
178
+ validation_inputs_phylip_max150k/
179
+ validation_inputs.tar
180
+ iqtree_results/
181
+ iqtree_results_GTR/
182
+ subset_distributions.png
183
+ subset_dimensions.csv
184
+ subset_filenames.txt
185
+ subset_metadata_summary.csv
186
+ subset_metadata.csv
187
+ subset_phylip.tar.gz
188
+ subset_files.zsh
189
+ subset_phylip/
190
+ snpio_results23*_output/
191
+ results23_test_output/
192
+ pgsui_validation/
193
+ iqtree_results_unique/
194
+ iqtree_results_GTR/
195
+ dataset_stats_output/
196
+ pgsui_validation.nosync/
197
+ iqtree_results_GTR.nosync/
198
+ iqtree_results_unique.nosync/
199
+ summarize.nosync/
200
+ subset_phylip.nosync/
201
+ simulation.nosync/
202
+ validation_inputs_phylip_max150k.nosync/
203
+ gui_test_output/
204
+ *.dmg
205
+ tmp_test_output/
@@ -0,0 +1,26 @@
1
+ # .readthedocs.yaml
2
+ # ReadTheDocs configuration file
3
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html
4
+
5
+ # Specify the version of the ReadTheDocs configuration file
6
+ version: 2
7
+
8
+ # Python version to use
9
+ # Set the version of Python and other tools you might need
10
+ build:
11
+ os: "ubuntu-20.04"
12
+ tools:
13
+ python: "3.11"
14
+
15
+ # Sphinx documentation options
16
+ sphinx:
17
+ configuration: docs/build/conf.py
18
+ builder: html
19
+ fail_on_warning: false
20
+
21
+ python:
22
+ install:
23
+ - method: pip
24
+ path: .
25
+ extra_requirements:
26
+ - docs
@@ -0,0 +1,8 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "configurations": [
6
+ { "name": "Python Debugger: Current File with Arguments", "type": "debugpy", "request": "launch", "program": "${file}", "console": "integratedTerminal", "args": "${command:pickArgs}" },
7
+ ]
8
+ }