PyEvoMotion 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl
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.
- PyEvoMotion/cli.py +87 -3
- PyEvoMotion/core/base.py +296 -20
- PyEvoMotion/core/core.py +73 -24
- {pyevomotion-0.1.1.dist-info → pyevomotion-0.1.2.dist-info}/METADATA +1 -1
- pyevomotion-0.1.2.dist-info/RECORD +35 -0
- share/analyze_model_selection_accuracy.py +316 -0
- share/analyze_test_runs.py +436 -0
- share/anomalous_diffusion.pdf +0 -0
- share/confusion_matrix_heatmap.pdf +0 -0
- share/figUK_plots.pdf +0 -0
- share/figUK_regression_results.json +54 -7
- share/figUK_run_args.json +1 -0
- share/figUK_stats.tsv +41 -41
- share/figUSA_plots.pdf +0 -0
- share/figUSA_regression_results.json +54 -7
- share/figUSA_run_args.json +1 -0
- share/figUSA_stats.tsv +34 -34
- share/generate_sequences_from_test5_data.py +107 -0
- share/manuscript_figure.py +450 -80
- share/run_parallel_analysis.py +196 -0
- share/synth_figure.pdf +0 -0
- share/uk_time_windows.pdf +0 -0
- share/weekly_size.pdf +0 -0
- pyevomotion-0.1.1.dist-info/RECORD +0 -31
- share/figure.pdf +0 -0
- {pyevomotion-0.1.1.dist-info → pyevomotion-0.1.2.dist-info}/WHEEL +0 -0
- {pyevomotion-0.1.1.dist-info → pyevomotion-0.1.2.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Parallel execution script for running multiple PyEvoMotion analyses.
|
|
4
|
+
|
|
5
|
+
This script runs the UK and USA analyses multiple times to assess
|
|
6
|
+
reproducibility and variance due to nonlinear fitting randomness.
|
|
7
|
+
Results are saved in separate subdirectories for each run.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
python run_parallel_analysis.py [batch_name] [num_runs] [max_workers]
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
python run_parallel_analysis.py batch2 # Run batch2 with 5 runs
|
|
14
|
+
python run_parallel_analysis.py batch3 10 # Run batch3 with 10 runs
|
|
15
|
+
python run_parallel_analysis.py batch4 5 4 # Run batch4 with 5 runs, max 4 parallel workers
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
import subprocess
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from concurrent.futures import ProcessPoolExecutor, as_completed
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def run_analysis(country: str, run_number: int, base_output_dir: Path) -> tuple[str, int, bool]:
|
|
26
|
+
"""
|
|
27
|
+
Run a single PyEvoMotion analysis for UK or USA dataset.
|
|
28
|
+
|
|
29
|
+
:param country: Either "UK" or "USA"
|
|
30
|
+
:type country: str
|
|
31
|
+
:param run_number: The run number for this batch
|
|
32
|
+
:type run_number: int
|
|
33
|
+
:param base_output_dir: Base directory for output files
|
|
34
|
+
:type base_output_dir: Path
|
|
35
|
+
:return: Tuple of (country, run_number, success_status)
|
|
36
|
+
:rtype: tuple[str, int, bool]
|
|
37
|
+
"""
|
|
38
|
+
# Create output directory for this specific run
|
|
39
|
+
output_dir = base_output_dir / f"{country}_run{run_number}"
|
|
40
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
|
|
42
|
+
# Output file prefix (without extension - PyEvoMotion will add suffixes)
|
|
43
|
+
output_prefix = output_dir / f"fig{country}"
|
|
44
|
+
|
|
45
|
+
# Build the command
|
|
46
|
+
cmd = [
|
|
47
|
+
"PyEvoMotion",
|
|
48
|
+
f"tests/data/test3/test3{country}.fasta",
|
|
49
|
+
f"share/figdata{country}.tsv",
|
|
50
|
+
str(output_prefix),
|
|
51
|
+
"-k", "total",
|
|
52
|
+
"-dt", "7D",
|
|
53
|
+
"-dr", "2020-10-01..2021-08-01",
|
|
54
|
+
"-ep",
|
|
55
|
+
"-xj",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
print(f"Starting {country} run {run_number}...")
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
# Run the command
|
|
62
|
+
result = subprocess.run(
|
|
63
|
+
cmd,
|
|
64
|
+
stdout=subprocess.PIPE,
|
|
65
|
+
stderr=subprocess.PIPE,
|
|
66
|
+
text=True,
|
|
67
|
+
check=True
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
print(f"Completed {country} run {run_number}")
|
|
71
|
+
|
|
72
|
+
# Optionally save stdout/stderr to log files
|
|
73
|
+
log_file = output_dir / "run.log"
|
|
74
|
+
with open(log_file, 'w') as f:
|
|
75
|
+
f.write(f"Command: {' '.join(cmd)}\n")
|
|
76
|
+
f.write("\n=== STDOUT ===\n")
|
|
77
|
+
f.write(result.stdout)
|
|
78
|
+
f.write("\n=== STDERR ===\n")
|
|
79
|
+
f.write(result.stderr)
|
|
80
|
+
|
|
81
|
+
return (country, run_number, True)
|
|
82
|
+
|
|
83
|
+
except subprocess.CalledProcessError as e:
|
|
84
|
+
print(f"ERROR in {country} run {run_number}: {e}")
|
|
85
|
+
|
|
86
|
+
# Save error log
|
|
87
|
+
error_log = output_dir / "error.log"
|
|
88
|
+
with open(error_log, 'w') as f:
|
|
89
|
+
f.write(f"Command: {' '.join(cmd)}\n")
|
|
90
|
+
f.write(f"\nReturn code: {e.returncode}\n")
|
|
91
|
+
f.write("\n=== STDOUT ===\n")
|
|
92
|
+
f.write(e.stdout if e.stdout else "No stdout")
|
|
93
|
+
f.write("\n=== STDERR ===\n")
|
|
94
|
+
f.write(e.stderr if e.stderr else "No stderr")
|
|
95
|
+
|
|
96
|
+
return (country, run_number, False)
|
|
97
|
+
except Exception as e:
|
|
98
|
+
print(f"UNEXPECTED ERROR in {country} run {run_number}: {e}")
|
|
99
|
+
return (country, run_number, False)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def main():
|
|
103
|
+
"""
|
|
104
|
+
Main execution function for parallel batch analysis.
|
|
105
|
+
|
|
106
|
+
Runs UK and USA PyEvoMotion analyses multiple times in parallel to assess
|
|
107
|
+
reproducibility. Results are saved to batch subdirectories with configurable
|
|
108
|
+
parallelism and run counts via command line arguments.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
# Parse command line arguments
|
|
112
|
+
batch_name = sys.argv[1] if len(sys.argv) > 1 else "batch1"
|
|
113
|
+
num_runs = int(sys.argv[2]) if len(sys.argv) > 2 else 5
|
|
114
|
+
max_workers = int(sys.argv[3]) if len(sys.argv) > 3 else os.cpu_count()
|
|
115
|
+
|
|
116
|
+
# Configuration
|
|
117
|
+
NUM_RUNS = num_runs
|
|
118
|
+
COUNTRIES = ["UK", "USA"]
|
|
119
|
+
BASE_OUTPUT_DIR = Path(f"share/test-runs/{batch_name}")
|
|
120
|
+
|
|
121
|
+
# Check if directory already exists and warn user
|
|
122
|
+
if BASE_OUTPUT_DIR.exists():
|
|
123
|
+
existing_files = list(BASE_OUTPUT_DIR.glob("*"))
|
|
124
|
+
if existing_files:
|
|
125
|
+
print(f"WARNING: {BASE_OUTPUT_DIR} already exists with {len(existing_files)} items!")
|
|
126
|
+
response = input("Continue anyway? This may overwrite existing files. [y/N]: ")
|
|
127
|
+
if response.lower() != 'y':
|
|
128
|
+
print("Aborted.")
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
# Create base output directory
|
|
132
|
+
BASE_OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
|
133
|
+
print(f"Created output directory: {BASE_OUTPUT_DIR}")
|
|
134
|
+
print(f"Batch name: {batch_name}")
|
|
135
|
+
|
|
136
|
+
# Generate all tasks (combinations of country and run number)
|
|
137
|
+
tasks = [
|
|
138
|
+
(country, run_num)
|
|
139
|
+
for country in COUNTRIES
|
|
140
|
+
for run_num in range(1, NUM_RUNS + 1)
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
print(f"\nTotal number of tasks: {len(tasks)}")
|
|
144
|
+
print(f"Running {NUM_RUNS} runs for each of {COUNTRIES}")
|
|
145
|
+
print(f"Max parallel workers: {max_workers}")
|
|
146
|
+
print(f"Output will be saved to: {BASE_OUTPUT_DIR}/")
|
|
147
|
+
print("\nStarting parallel execution...\n")
|
|
148
|
+
|
|
149
|
+
# Run tasks in parallel
|
|
150
|
+
# Use max_workers to control parallelism (None = number of CPUs)
|
|
151
|
+
# Adjust this if you want to limit parallel processes
|
|
152
|
+
|
|
153
|
+
results = []
|
|
154
|
+
with ProcessPoolExecutor(max_workers=max_workers) as executor:
|
|
155
|
+
# Submit all tasks
|
|
156
|
+
future_to_task = {
|
|
157
|
+
executor.submit(run_analysis, country, run_num, BASE_OUTPUT_DIR): (country, run_num)
|
|
158
|
+
for country, run_num in tasks
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# Collect results as they complete
|
|
162
|
+
for future in as_completed(future_to_task):
|
|
163
|
+
country, run_num, success = future.result()
|
|
164
|
+
results.append((country, run_num, success))
|
|
165
|
+
|
|
166
|
+
# Print summary
|
|
167
|
+
print("\n" + "="*60)
|
|
168
|
+
print("EXECUTION SUMMARY")
|
|
169
|
+
print("="*60)
|
|
170
|
+
|
|
171
|
+
successful = [r for r in results if r[2]]
|
|
172
|
+
failed = [r for r in results if not r[2]]
|
|
173
|
+
|
|
174
|
+
print(f"\nTotal runs: {len(results)}")
|
|
175
|
+
print(f"Successful: {len(successful)}")
|
|
176
|
+
print(f"Failed: {len(failed)}")
|
|
177
|
+
|
|
178
|
+
if failed:
|
|
179
|
+
print("\nFailed runs:")
|
|
180
|
+
for country, run_num, _ in failed:
|
|
181
|
+
print(f" - {country} run {run_num}")
|
|
182
|
+
|
|
183
|
+
print(f"\nAll results saved to: {BASE_OUTPUT_DIR}/")
|
|
184
|
+
print("\nDirectory structure:")
|
|
185
|
+
for country in COUNTRIES:
|
|
186
|
+
for run_num in range(1, NUM_RUNS + 1):
|
|
187
|
+
run_dir = BASE_OUTPUT_DIR / f"{country}_run{run_num}"
|
|
188
|
+
status = "✓" if (country, run_num, True) in results else "✗"
|
|
189
|
+
print(f" {status} {run_dir}/")
|
|
190
|
+
|
|
191
|
+
print("\n" + "="*60)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
if __name__ == "__main__":
|
|
195
|
+
main()
|
|
196
|
+
|
share/synth_figure.pdf
CHANGED
|
Binary file
|
share/uk_time_windows.pdf
CHANGED
|
Binary file
|
share/weekly_size.pdf
CHANGED
|
Binary file
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
PyEvoMotion/__init__.py,sha256=NqFDD-EZBzouzTwXozZqhPC9sLr7GQaElRKtP0tkHoE,568
|
|
2
|
-
PyEvoMotion/cli.py,sha256=U_zX6Y9kU9l-vtC9BeR1ebT7PLogAqpBNHs-DT552vI,15322
|
|
3
|
-
PyEvoMotion/core/__init__.py,sha256=1I-NkFFh6ljLgB_mqQVFLNvCrVKEHLVxa_5dsv3ihWQ,450
|
|
4
|
-
PyEvoMotion/core/base.py,sha256=0NQ0njPIFn9sL4PdymWE3LYcOmrl3LyCsMDRtAPCRVM,16851
|
|
5
|
-
PyEvoMotion/core/core.py,sha256=ynsHkqZMZZaoikRp1967smHaSzYVX658LjVewZtdQnI,19927
|
|
6
|
-
PyEvoMotion/core/parser.py,sha256=w23KzX0jl3NLS0WYjAY1s_2VFEqfn6EoTrQXmGRRXfg,17323
|
|
7
|
-
PyEvoMotion/utils.py,sha256=Ye3eL1RXZOZzzs2KZy0R45u06DOtLYo-zqE45tN2t7g,2859
|
|
8
|
-
share/anomalous_diffusion.pdf,sha256=yBjHK1dzyx1akaOjmQ8ogWhH1QUWXqCTdUHlXMhtwug,19384
|
|
9
|
-
share/figUK.tsv,sha256=DnPkVfbMGfsOq9x8IAkbPzIWsmQBB1hOXChSNkNlHGo,6711825
|
|
10
|
-
share/figUK_plots.pdf,sha256=-YfMSLcpsHWq4D9hwFc45LrBdL6BNEyNVNs2j_Y36M8,22865
|
|
11
|
-
share/figUK_regression_results.json,sha256=GFD3av78AhVzwuJkOYpqo5NwbUSdWoxe7_2fz7Xeysk,470
|
|
12
|
-
share/figUK_run_args.json,sha256=lWbeubYYU--BhEzkFHGOSF4cJ_wMhmYHwyj8Iaxqpj0,314
|
|
13
|
-
share/figUK_stats.tsv,sha256=ZvzPtCtnvnXQOU9blDx-_iU3h5IUXOU94D9xCfobXWE,2055
|
|
14
|
-
share/figUSA.tsv,sha256=hSPmKjCFk0a5B0XN75JhQOuhZgfcz9ZCxNrfqMrYcF0,6577552
|
|
15
|
-
share/figUSA_plots.pdf,sha256=679_rgan3Eb6KsclNu5xEeIvQEGJDIN4wMzMeqq2ZvI,22271
|
|
16
|
-
share/figUSA_regression_results.json,sha256=Q9t5KE_vV_-wuhRcXhnMrEMDc6BT1LFmlDu17RpigkY,468
|
|
17
|
-
share/figUSA_run_args.json,sha256=-jsoE6BXQTy7-UsgoVjuCZsShgtseQ3YUxX8vIGJMN4,317
|
|
18
|
-
share/figUSA_stats.tsv,sha256=BnpZs8oWgeRHiKCW8r7KrYc9YaO3i5X447jKPhtUZeQ,1751
|
|
19
|
-
share/figdataUK.tsv,sha256=HMF07FNT7d3Tb2OMHuFYkRzc6vb5EQ6vj2nJBpXlXJ8,939837
|
|
20
|
-
share/figdataUSA.tsv,sha256=z5yaIwcyfLo7Wr5ioE-x6_qXg9IhT_CmAJxcLTfP4jA,827811
|
|
21
|
-
share/figure.pdf,sha256=9D2gy7fr-LC52kRfD09aZP8Z8jmY_7K8IhigzIgAK5U,24194
|
|
22
|
-
share/generate_sequences_from_synthdata.py,sha256=_2IdMgcOB7SxAq30iypA-VypSmZyZmMhA8otKQnkfAw,3443
|
|
23
|
-
share/mafft_install.sh,sha256=pCw70UsKkkNXUsZMwQlQ2b4zSXFrBA7jAj9iOfGLzUw,1007
|
|
24
|
-
share/manuscript_figure.py,sha256=G61puV4VjfTgXbokD380aSB0C4Wo9HEJ8y3kw0_Z-TQ,24474
|
|
25
|
-
share/synth_figure.pdf,sha256=2hckyY0Uie16yn3YH5B1LE2lakOJGLzSbF6GHelvSEE,26350
|
|
26
|
-
share/uk_time_windows.pdf,sha256=U1zAMRgZxvfpfMr2ahUqHGYSxPVoDRQTGJSF96NJFck,35022
|
|
27
|
-
share/weekly_size.pdf,sha256=9hn6U8IBWQvZTR8hNLo3r3Kb4hwB7awxlt31_clcHjA,14602
|
|
28
|
-
pyevomotion-0.1.1.dist-info/METADATA,sha256=jgRSgfXK41_APjXUKNA41jggW_bGx9zYxnULz1B1ulQ,7833
|
|
29
|
-
pyevomotion-0.1.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
30
|
-
pyevomotion-0.1.1.dist-info/entry_points.txt,sha256=UMzoojYwQi-713hRggkQXUIfGNygUARhTdGs77Usp7s,53
|
|
31
|
-
pyevomotion-0.1.1.dist-info/RECORD,,
|
share/figure.pdf
DELETED
|
Binary file
|
|
File without changes
|
|
File without changes
|