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.
@@ -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