lytools-HPC 0.0.1__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.
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: lytools_HPC
3
+ Version: 0.0.1
4
+ Home-page: https://github.com/leeyang1991/lytools_HPC
5
+ Author: Yang Li
6
+ Author-email: leeyang1991@gmail.com
7
+ Requires-Python: >=3
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: submitit
10
+ Requires-Dist: redis
11
+ Requires-Dist: pathos
12
+ Requires-Dist: rich
13
+ Requires-Dist: requests
14
+ Requires-Dist: packaging
15
+ Dynamic: author
16
+ Dynamic: author-email
17
+ Dynamic: description
18
+ Dynamic: description-content-type
19
+ Dynamic: home-page
20
+ Dynamic: requires-dist
21
+ Dynamic: requires-python
22
+
23
+ # HPC Functions
24
+
25
+ ## Monitoring you jobs with a progress bar.
26
+
27
+ This requires a Redis server to store the progress information. The following steps will guide you through setting up the Redis server and using submitit with a progress bar.
28
+ ### Python packages required:
29
+ ```bash
30
+ pip install submitit redis pathos rich
31
+ ```
32
+ ### Step 1: Deploy a Redis service
33
+ **DO NOT** deploy it on a HPC nodes. You can use your local machine or a server with a public IP address.
34
+ #### Deploy redis via Docker
35
+ Compose file for Redis server:
36
+ ```yaml
37
+ services:
38
+ redis-progress:
39
+ image: redis:7
40
+ container_name: redis-progress
41
+ restart: unless-stopped
42
+
43
+ ports:
44
+ - "6379:6379"
45
+
46
+ volumes:
47
+ - ./redis_data:/data
48
+
49
+ command: >
50
+ redis-server
51
+ --appendonly yes
52
+ --requirepass yourpassword
53
+ --maxmemory 2gb
54
+ --maxmemory-policy allkeys-lru
55
+
56
+ deploy:
57
+ resources:
58
+ limits:
59
+ memory: 3g
60
+
61
+ ```
62
+ ```docker compose up -d``` # Start the Redis server
63
+
64
+ #### Test Redis connection
65
+ ```python
66
+ import redis
67
+ r = redis.Redis(host='your_redis_host', port=6379, password='yourpassword')
68
+ r.set('test_key', 'test_value')
69
+ print(r.get('test_key').decode())
70
+ ```
71
+
72
+ #### Create redis connection configuration file
73
+ Location: ```~/.config/redis/redis.conf```
74
+ ```txt
75
+ your_redis_host
76
+ 6379
77
+ yourpassword
78
+ ```
79
+
80
+ ### Step 2: Submit your jobs
81
+ ```python
82
+ from HPC_func import *
83
+
84
+ def my_function(x):
85
+ return x * x
86
+
87
+ job_name = 'Your_job_name'
88
+ params_list = [1,2,3,4,5,6,7,8,9,10]
89
+ log_folder = 'Your_log_folder'
90
+ init_job(job_name, params_list)
91
+ sumbit_jobs_array(my_function, params_list, log_folder,
92
+ job_name=job_name,
93
+ job_number_limit=1,
94
+ parallel_process_per_task=2,
95
+ slurm_array_parallelism=1,
96
+ parallel_process_p_or_t='p',
97
+ cpus_per_task=10,
98
+ mem_gb=2,
99
+ timeout_min=10,
100
+ slurm_partition="general",
101
+ exclude_nodes=None,
102
+ pbar_update_freq=1,
103
+ )
104
+ ```
105
+
106
+ ### Step 3: Monitor the progress bar
107
+ ```python
108
+ from HPC_func import *
109
+ job_name = 'Your_job_name'
110
+ progress_bar_monitoring(job_name)
111
+ ```
112
+
113
+ ### Step 4: Check the log files
114
+ ```python
115
+ from HPC_func import *
116
+ log_folder = 'Your_log_folder'
117
+ Check_logs(log_folder).read_err_files() # Read error files
118
+ Check_logs(log_folder).read_out_files() # Read output files
119
+ ```
@@ -0,0 +1,50 @@
1
+ # coding='utf-8'
2
+ __version__ = '0.0.1'
3
+ __package_name__ = 'lytools_HPC'
4
+ import warnings
5
+ import requests
6
+ from packaging import version
7
+
8
+ def check_latest_version(package_name, current_version, cache_hours=0.1):
9
+ cache_file = os.path.expanduser(f"~/.{package_name}_version_check")
10
+ latest_version = None
11
+ now = time.time()
12
+
13
+ if os.path.exists(cache_file):
14
+ try:
15
+ with open(cache_file, "r") as f:
16
+ data = json.load(f)
17
+ if now - data["timestamp"] < cache_hours * 3600:
18
+ latest_version = data["latest_version"]
19
+ except Exception:
20
+ pass
21
+
22
+ if latest_version is None:
23
+ try:
24
+ url = f"https://pypi.org/pypi/{package_name}/json"
25
+ resp = requests.get(url, timeout=3)
26
+ if resp.status_code == 200:
27
+ data = resp.json()
28
+ latest_version = data["info"]["version"]
29
+ with open(cache_file, "w") as f:
30
+ json.dump({"latest_version": latest_version, "timestamp": now}, f)
31
+ except Exception:
32
+ return
33
+
34
+ try:
35
+ if version.parse(current_version) < version.parse(latest_version):
36
+ warnings.warn(
37
+ f"{package_name} {current_version} is outdated. "
38
+ f"Latest version is {latest_version}. "
39
+ f"Upgrade via: pip install -U {package_name}"
40
+ )
41
+ except Exception:
42
+ pass
43
+
44
+ try:
45
+ current = __version__
46
+ check_latest_version(__package_name__, current)
47
+ except Exception:
48
+ pass
49
+
50
+ from ._lytools_HPC import *
@@ -0,0 +1,450 @@
1
+ import submitit
2
+ from concurrent.futures import ThreadPoolExecutor
3
+ import redis
4
+ from threading import Lock
5
+ from pathos.multiprocessing import ProcessPool
6
+ import time
7
+ from rich.text import Text
8
+
9
+ import os
10
+ import json
11
+ from pathlib import Path
12
+ import pickle
13
+
14
+ from rich.progress import (
15
+ Progress,
16
+ BarColumn,
17
+ TextColumn,
18
+ TimeRemainingColumn,
19
+ TimeElapsedColumn,
20
+ ProgressColumn
21
+ )
22
+
23
+
24
+ def listdir(fdir):
25
+ '''
26
+ Mac OS
27
+ list the names of the files in the directory
28
+ return sorted files list without '.DS_store'
29
+ '''
30
+ list_dir = []
31
+ for f in sorted(os.listdir(fdir)):
32
+ if f.startswith('.'):
33
+ continue
34
+ list_dir.append(f)
35
+ return list_dir
36
+
37
+
38
+ def mkdir(dir, force=False):
39
+ if not os.path.isdir(dir):
40
+ if force == True:
41
+ os.makedirs(dir)
42
+ else:
43
+ os.mkdir(dir)
44
+
45
+ def split_into_n_jobs(lst, n_jobs):
46
+ """
47
+ Split the list into n_jobs parts.
48
+ """
49
+ total = len(lst)
50
+ chunk_size = total // n_jobs
51
+ remainder = total % n_jobs
52
+
53
+ chunks = []
54
+ start = 0
55
+
56
+ for i in range(n_jobs):
57
+ extra = 1 if i < remainder else 0
58
+ end = start + chunk_size + extra
59
+ chunks.append(lst[start:end])
60
+ start = end
61
+ return chunks
62
+
63
+ _REDIS = None
64
+
65
+ def get_redis():
66
+ global _REDIS
67
+ if _REDIS is None:
68
+ _REDIS = HPC_redis().conn_redis()
69
+ return _REDIS
70
+
71
+ _LOCK = Lock()
72
+ _LOCAL_COUNTER = 0
73
+
74
+ def update_i(job_name, batch_size=100):
75
+ '''
76
+ :param job_name:
77
+ '''
78
+ global _LOCAL_COUNTER
79
+
80
+ with _LOCK:
81
+ _LOCAL_COUNTER += 1
82
+
83
+ if _LOCAL_COUNTER >= batch_size:
84
+ r = get_redis()
85
+ r.hincrby(job_name, "step", _LOCAL_COUNTER)
86
+ _LOCAL_COUNTER = 0
87
+
88
+ class IterSpeedColumn(ProgressColumn):
89
+
90
+ def render(self, task):
91
+ if task.finished:
92
+ return Text(f"{task.speed:.2f} it/s", style="green")
93
+
94
+ speed = task.speed
95
+
96
+ if speed is None:
97
+ return Text("-- it/s", style="dim")
98
+
99
+ return Text(f"{speed:.2f} it/s", style="cyan")
100
+
101
+ def sumbit_jobs_array(func,params_list,log_folder,job_name,
102
+ job_number_limit=500,
103
+ parallel_process_per_task=10,
104
+ slurm_array_parallelism=20,
105
+ parallel_process_p_or_t='p',
106
+ cpus_per_task=1,
107
+ mem_gb=1,
108
+ timeout_min=5,
109
+ slurm_partition="general",
110
+ exclude_nodes=None,
111
+ pbar_update_freq=1
112
+ ):
113
+ '''
114
+ :param func: the kernel function to run, should take one argument, e.g. func(params)
115
+ :param params_list: list of tuples [params1, params2, ...]
116
+ :param log_folder: slurm log_folder
117
+ :param job_name: slurm job_name
118
+ :param job_number_limit: number of total jobs you want to submit to slurm
119
+ :param parallel_process_per_task: number of parallel processes per task, Recommend equal to :param cpus_per_task
120
+ :param slurm_array_parallelism: slurm array parallelism
121
+ :param parallel_process_p_or_t: 'p' for multiprocessing, 't' for multi-threading
122
+ :param cpus_per_task: number of cpus per task
123
+ :param mem_gb: memory per task
124
+ :param timeout_min: timeout in minutes
125
+ :param slurm_partition: slurm partition
126
+ :param exclude_nodes: list of nodes to exclude
127
+ :param pbar_update_freq: frequency of updating progress bar
128
+ '''
129
+
130
+ if len(params_list) == 0:
131
+ raise ValueError("params_list is empty")
132
+ if len(params_list) > job_number_limit:
133
+ super_params_list = split_into_n_jobs(params_list,job_number_limit)
134
+ if parallel_process_p_or_t == 't':
135
+ def super_func(chunk):
136
+ def wrapper(p):
137
+ func(p)
138
+ update_i(job_name,pbar_update_freq)
139
+
140
+ with ThreadPoolExecutor(max_workers=parallel_process_per_task) as Thread_:
141
+ list(Thread_.map(wrapper, chunk))
142
+
143
+ elif parallel_process_p_or_t == 'p':
144
+ def super_func(chunk):
145
+ # for p in chunk:
146
+ # func(p)
147
+
148
+ def wrapper(p):
149
+ func(p)
150
+ update_i(job_name,pbar_update_freq)
151
+
152
+ pool = ProcessPool(nodes=parallel_process_per_task)
153
+ pool.map(wrapper, chunk)
154
+ pass
155
+ else:
156
+ raise ValueError("parallel_process_p_or_t must be 'p' for multiprocessing or 't' for threading")
157
+
158
+ final_params_list = super_params_list
159
+ final_func = super_func
160
+ else:
161
+ final_params_list = params_list
162
+ final_func = func
163
+
164
+ if os.path.exists(log_folder):
165
+ for f in os.listdir(log_folder):
166
+ os.remove(os.path.join(log_folder, f))
167
+ mkdir(log_folder, force=True)
168
+
169
+ print('submiting...')
170
+ executor = submitit.AutoExecutor(folder=log_folder)
171
+ executor.update_parameters(
172
+ slurm_job_name=job_name,
173
+ cpus_per_task=cpus_per_task,
174
+ mem_gb=mem_gb,
175
+ timeout_min=timeout_min,
176
+ slurm_array_parallelism=slurm_array_parallelism,
177
+ slurm_partition=slurm_partition,
178
+ exclude=exclude_nodes,
179
+ )
180
+ jobs = executor.map_array(final_func, final_params_list)
181
+
182
+ info = {
183
+ "Total Cores Used": cpus_per_task * slurm_array_parallelism,
184
+ "Concurrent Processes": parallel_process_per_task * slurm_array_parallelism,
185
+ "Total Loop Length": len(params_list),
186
+ "Number of Jobs": len(final_params_list),
187
+ "First Job ID": jobs[0].job_id,
188
+ "Memory for Each Job(GB)":mem_gb,
189
+ "Time out Minutes For Each Job": timeout_min,
190
+ "Partition":slurm_partition,
191
+ }
192
+ pretty_table_print(info)
193
+
194
+
195
+
196
+ def pretty_table_print(info):
197
+ max_key_len = max(len(k) for k in info)
198
+
199
+ print("\n=== Job Summary ===")
200
+ for k, v in info.items():
201
+ print(f"{k + ':':<{max_key_len + 2}} {v}")
202
+ print("=" * (max_key_len + 15))
203
+ pass
204
+
205
+ def monitoring_job(progress_dir_json):
206
+ refresh_interval = 1
207
+ # refresh_interval = 5
208
+ task_map = {}
209
+ with Progress(
210
+ TextColumn("[bold yellow]{task.description}"),
211
+ BarColumn(style="red", # Unfinished part
212
+ complete_style="green", # Finished part
213
+ finished_style="yellow"), # 100% finished),
214
+ TextColumn("{task.completed}/{task.total} {task.percentage:>3.0f}%"),
215
+ TimeElapsedColumn(),
216
+ TimeRemainingColumn(),
217
+ ) as progress_total:
218
+
219
+ with Progress(
220
+ TextColumn("[bold yellow]{task.description}"),
221
+ BarColumn(),
222
+ TextColumn("{task.completed}/{task.total} {task.percentage:>3.0f}%"),
223
+ TimeElapsedColumn(),
224
+ TimeRemainingColumn(),
225
+ ) as progress:
226
+
227
+ overall_task = None
228
+ total_jobs = None
229
+
230
+ while True:
231
+
232
+ files = list(progress_dir_json.glob("*.json"))
233
+ finished_jobs = 0
234
+
235
+ for f in files:
236
+
237
+ try:
238
+ with open(f) as fp:
239
+ data = json.load(fp)
240
+ except:
241
+ continue
242
+
243
+ jobid = data["jobid"]
244
+ step = data["step"]
245
+ total = data["total"]
246
+ total_job = data["total_job"]
247
+ sub_job_name = data["sub_job_name"]
248
+
249
+ # 初始化 total progress
250
+
251
+ if total_jobs is None:
252
+ total_jobs = total_job
253
+ overall_task = progress_total.add_task(
254
+ "[bold green]TOTAL", total=total_jobs
255
+ )
256
+
257
+ # if completed
258
+ if step >= total:
259
+
260
+ finished_jobs += 1
261
+
262
+ if jobid in task_map:
263
+ progress.remove_task(task_map[jobid])
264
+ del task_map[jobid]
265
+
266
+ continue
267
+
268
+ # create bar
269
+ if jobid not in task_map:
270
+ task_map[jobid] = progress.add_task(
271
+ f"({jobid}/{total_job}) {sub_job_name}", total=total
272
+ )
273
+
274
+ progress.update(task_map[jobid], completed=step)
275
+
276
+ # update total bar
277
+ if overall_task is not None:
278
+ progress_total.update(overall_task, completed=finished_jobs)
279
+
280
+ # All tasks completed
281
+ if total_jobs and finished_jobs == total_jobs:
282
+ break
283
+
284
+ time.sleep(refresh_interval)
285
+ pass
286
+
287
+ class HPC_redis:
288
+
289
+ def __init__(self):
290
+ self.r = self.conn_redis()
291
+ pass
292
+
293
+ def conn_redis(self):
294
+ redis_conf = Path.home() / '.config' / 'redis' / 'redis.conf'
295
+ with open(redis_conf) as f:
296
+ redis_conf = f.readlines()
297
+ host = redis_conf[0].strip()
298
+ port = int(redis_conf[1].strip())
299
+ passwd = redis_conf[2].strip()
300
+
301
+ r = redis.Redis(
302
+ host=host,
303
+ port=port,
304
+ password=passwd,
305
+ )
306
+ # print(f"Connected to Redis at {host}:{port}")
307
+ return r
308
+
309
+ def hit_redis(self,job_name,amount=1):
310
+ self.r.hincrby(name=job_name,key=job_name,amount=amount)
311
+
312
+ def set_total_num(self,job_name,total_job:int):
313
+ # r.delete(job_name+'_total')
314
+ # r.hincrby(name=job_name, key=task_name+'_total', amount=total_job)
315
+ self.r.hset(job_name, 'total', str(total_job))
316
+
317
+ def delete_job(self,job_name):
318
+ self.r.delete(job_name)
319
+ pass
320
+
321
+ def query_redis(self,job_name):
322
+ while True:
323
+ print(self.r.hgetall(job_name))
324
+ time.sleep(1)
325
+
326
+ class Check_logs:
327
+ def __init__(self,log_folder):
328
+ self.log_folder = log_folder
329
+ pass
330
+
331
+ def read_err_files(self):
332
+ log_folder = self.log_folder
333
+ log_folder = Path(log_folder)
334
+ err_count = 0
335
+ for f in listdir(log_folder):
336
+ if not f.endswith(".err"):
337
+ continue
338
+ fpath = log_folder / f
339
+ # print(fpath)
340
+ with open(fpath) as fr:
341
+ err_content = fr.read()
342
+ if len(err_content) != 0:
343
+ print('==============')
344
+ print(f"Error in file: {f}")
345
+ print(err_content)
346
+ err_count += 1
347
+ print('#################')
348
+ print(f'Total error logs: {err_count}')
349
+ print('#################')
350
+ pass
351
+
352
+ def read_out_files(self):
353
+ log_folder = self.log_folder
354
+ log_folder = Path(log_folder)
355
+ count = 0
356
+ for f in listdir(log_folder):
357
+ if not f.endswith(".out"):
358
+ continue
359
+ fpath = log_folder / f
360
+ # print(fpath)
361
+ with open(fpath) as fr:
362
+ log_content = fr.read()
363
+ print(log_content)
364
+ print('------------')
365
+ count += 1
366
+ print(f'Total files: {count}')
367
+ pass
368
+
369
+ def read_result_files(self):
370
+ log_folder = self.log_folder
371
+ log_folder = Path(log_folder)
372
+ count = 0
373
+ for f in listdir(log_folder):
374
+ if not f.endswith("_result.pkl"):
375
+ continue
376
+ fpath = log_folder / f
377
+ # print(fpath)
378
+ content = pickle.load(open(fpath, 'rb'))
379
+ print(content)
380
+ print('------------')
381
+ count += 1
382
+ print(f'Total files: {count}')
383
+ pass
384
+
385
+ def read_submit_files(self):
386
+ log_folder = self.log_folder
387
+ log_folder = Path(log_folder)
388
+ count = 0
389
+ for f in listdir(log_folder):
390
+ if not f.endswith("_submitted.pkl"):
391
+ continue
392
+ fpath = log_folder / f
393
+ # print(fpath)
394
+ content = pickle.load(open(fpath, 'rb'))
395
+ print(content)
396
+ print('------------')
397
+ count += 1
398
+ print(f'Total files: {count}')
399
+ pass
400
+
401
+
402
+ def init_job(job_name,param_list):
403
+ total_job = len(param_list)
404
+ r = HPC_redis().conn_redis()
405
+ r.delete(job_name)
406
+ r.hset(job_name, 'total', str(total_job))
407
+ r.hset(job_name, 'step', str(0))
408
+
409
+
410
+ def flush_progress(job_name):
411
+ global _LOCAL_COUNTER
412
+
413
+ if _LOCAL_COUNTER > 0:
414
+ r = get_redis()
415
+ r.hincrby(job_name, "step", _LOCAL_COUNTER)
416
+ _LOCAL_COUNTER = 0
417
+
418
+
419
+ def update_progress(job_name, batch_size=100):
420
+ update_i(job_name, batch_size)
421
+ flush_progress(job_name)
422
+
423
+ def progress_bar_monitoring(job_name):
424
+ hpc_redis = HPC_redis()
425
+ info=hpc_redis.r.hgetall(job_name)
426
+ total = info.get(b'total')
427
+ step = info.get(b'step')
428
+ total_int = int(total)
429
+ step_int = int(step)
430
+ # exit()
431
+ with Progress(
432
+ TextColumn("[bold yellow]{task.description}"),
433
+ BarColumn(),
434
+ TextColumn("{task.completed}/{task.total} {task.percentage:>3.0f}%"),
435
+ TimeElapsedColumn(),
436
+ IterSpeedColumn(),
437
+ TimeRemainingColumn(),
438
+ # show_speed=True,
439
+ ) as progress:
440
+ task = progress.add_task(f"[bold green]{job_name}", total=total_int)
441
+ while True:
442
+ info = hpc_redis.r.hgetall(job_name)
443
+ # print(info)
444
+ step = info.get(b'step')
445
+ step_int = int(step)
446
+ progress.update(task, completed=step_int)
447
+ if step_int >= total_int:
448
+ break
449
+ time.sleep(1)
450
+
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: lytools_HPC
3
+ Version: 0.0.1
4
+ Home-page: https://github.com/leeyang1991/lytools_HPC
5
+ Author: Yang Li
6
+ Author-email: leeyang1991@gmail.com
7
+ Requires-Python: >=3
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: submitit
10
+ Requires-Dist: redis
11
+ Requires-Dist: pathos
12
+ Requires-Dist: rich
13
+ Requires-Dist: requests
14
+ Requires-Dist: packaging
15
+ Dynamic: author
16
+ Dynamic: author-email
17
+ Dynamic: description
18
+ Dynamic: description-content-type
19
+ Dynamic: home-page
20
+ Dynamic: requires-dist
21
+ Dynamic: requires-python
22
+
23
+ # HPC Functions
24
+
25
+ ## Monitoring you jobs with a progress bar.
26
+
27
+ This requires a Redis server to store the progress information. The following steps will guide you through setting up the Redis server and using submitit with a progress bar.
28
+ ### Python packages required:
29
+ ```bash
30
+ pip install submitit redis pathos rich
31
+ ```
32
+ ### Step 1: Deploy a Redis service
33
+ **DO NOT** deploy it on a HPC nodes. You can use your local machine or a server with a public IP address.
34
+ #### Deploy redis via Docker
35
+ Compose file for Redis server:
36
+ ```yaml
37
+ services:
38
+ redis-progress:
39
+ image: redis:7
40
+ container_name: redis-progress
41
+ restart: unless-stopped
42
+
43
+ ports:
44
+ - "6379:6379"
45
+
46
+ volumes:
47
+ - ./redis_data:/data
48
+
49
+ command: >
50
+ redis-server
51
+ --appendonly yes
52
+ --requirepass yourpassword
53
+ --maxmemory 2gb
54
+ --maxmemory-policy allkeys-lru
55
+
56
+ deploy:
57
+ resources:
58
+ limits:
59
+ memory: 3g
60
+
61
+ ```
62
+ ```docker compose up -d``` # Start the Redis server
63
+
64
+ #### Test Redis connection
65
+ ```python
66
+ import redis
67
+ r = redis.Redis(host='your_redis_host', port=6379, password='yourpassword')
68
+ r.set('test_key', 'test_value')
69
+ print(r.get('test_key').decode())
70
+ ```
71
+
72
+ #### Create redis connection configuration file
73
+ Location: ```~/.config/redis/redis.conf```
74
+ ```txt
75
+ your_redis_host
76
+ 6379
77
+ yourpassword
78
+ ```
79
+
80
+ ### Step 2: Submit your jobs
81
+ ```python
82
+ from HPC_func import *
83
+
84
+ def my_function(x):
85
+ return x * x
86
+
87
+ job_name = 'Your_job_name'
88
+ params_list = [1,2,3,4,5,6,7,8,9,10]
89
+ log_folder = 'Your_log_folder'
90
+ init_job(job_name, params_list)
91
+ sumbit_jobs_array(my_function, params_list, log_folder,
92
+ job_name=job_name,
93
+ job_number_limit=1,
94
+ parallel_process_per_task=2,
95
+ slurm_array_parallelism=1,
96
+ parallel_process_p_or_t='p',
97
+ cpus_per_task=10,
98
+ mem_gb=2,
99
+ timeout_min=10,
100
+ slurm_partition="general",
101
+ exclude_nodes=None,
102
+ pbar_update_freq=1,
103
+ )
104
+ ```
105
+
106
+ ### Step 3: Monitor the progress bar
107
+ ```python
108
+ from HPC_func import *
109
+ job_name = 'Your_job_name'
110
+ progress_bar_monitoring(job_name)
111
+ ```
112
+
113
+ ### Step 4: Check the log files
114
+ ```python
115
+ from HPC_func import *
116
+ log_folder = 'Your_log_folder'
117
+ Check_logs(log_folder).read_err_files() # Read error files
118
+ Check_logs(log_folder).read_out_files() # Read output files
119
+ ```
@@ -0,0 +1,8 @@
1
+ setup.py
2
+ lytools_HPC/__init__.py
3
+ lytools_HPC/_lytools_HPC.py
4
+ lytools_HPC.egg-info/PKG-INFO
5
+ lytools_HPC.egg-info/SOURCES.txt
6
+ lytools_HPC.egg-info/dependency_links.txt
7
+ lytools_HPC.egg-info/requires.txt
8
+ lytools_HPC.egg-info/top_level.txt
@@ -0,0 +1,6 @@
1
+ submitit
2
+ redis
3
+ pathos
4
+ rich
5
+ requests
6
+ packaging
@@ -0,0 +1 @@
1
+ lytools_HPC
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,31 @@
1
+
2
+ from setuptools import setup
3
+
4
+ def get_version():
5
+ init_f = './lytools_HPC/__init__.py'
6
+ with open(init_f) as f:
7
+ for line in f:
8
+ if line.startswith('__version__'):
9
+ return line.split('=')[-1].strip().strip("'")
10
+ version = get_version()
11
+
12
+ long_description = open('README.md').read()
13
+ setup(
14
+ name='lytools_HPC',
15
+ version=version,
16
+ long_description=long_description,
17
+ long_description_content_type='text/markdown',
18
+ author='Yang Li',
19
+ author_email='leeyang1991@gmail.com',
20
+ packages=['lytools_HPC'],
21
+ url='https://github.com/leeyang1991/lytools_HPC',
22
+ python_requires='>=3',
23
+ install_requires=[
24
+ 'submitit',
25
+ 'redis',
26
+ 'pathos',
27
+ 'rich',
28
+ 'requests',
29
+ 'packaging',
30
+ ],
31
+ )