Newer
Older
import os
from wetb.hawc2.htc_file import HTCFile
from threading import Timer, Thread
import sys
from multiprocessing.process import Process
import psutil
from wetb.utils.process_exec import process, exec_process
import subprocess
import shutil
import json
import glob
QUEUED = "queued" #until start
INITIALIZING = "initializing" #when starting
SIMULATING = "SIMULATING" # when logfile.status=simulating
FINISH = "finish" # when finish
ERROR = "error" # when hawc2 returns error
ABORTED = "aborted" # when stopped and logfile.status != Done
CLEANED = "cleaned" # after copy back
class Simulation(object):
is_simulating = False
def __init__(self, modelpath, htcfilename, hawc2exe="HAWC2MB.exe"):
self.modelpath = modelpath
self.folder = os.path.dirname(htcfilename)
if not os.path.isabs(htcfilename):
htcfilename = os.path.join(modelpath, htcfilename)
self.filename = os.path.basename(htcfilename)
self.htcFile = HTCFile(htcfilename)
self.time_stop = self.htcFile.simulation.time_stop[0]
self.log_filename = self.htcFile.simulation.logfile[0]
if os.path.isabs(self.log_filename):
self.log_filename = os.path.relpath(self.log_filename, self.modelpath)
self.logFile = LogFile(os.path.join(self.modelpath, self.log_filename), self.time_stop)
self.logFile.clear()
self.thread = Thread(target=self.simulate)
self.simulationThread = SimulationThread(self.modelpath, self.htcFile.filename, hawc2exe)
self.timer = RepeatedTimer(1, self.update_status)
if self.status in [INITIALIZING, SIMULATING]:
self.logFile.update_status()
if self.logFile.status == log_file.SIMULATING:
self._status = SIMULATING
if self.logFile.status == log_file.DONE:
self._status = FINISH
def show_status(self):
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
status = self.logFile.status()
if status[1] == SIMULATING:
if self.last_status[1] != SIMULATING:
print ("|" + ("-"*50) + "|" + ("-"*49) + "|")
sys.stdout.write("|")
#print (status)
sys.stdout.write("."*(status[0] - self.last_status[0]))
sys.stdout.flush()
elif self.last_status[1] == SIMULATING and status[1] != SIMULATING:
sys.stdout.write("."*(status[0] - self.last_status[0]) + "|")
sys.stdout.flush()
print ("\n")
if status[1] != SIMULATING:
if status[2]:
print (status[1:])
else:
print (status[1])
self.last_status = status
def prepare_simulation(self, id):
self.tmp_modelpath = os.path.join(self.modelpath, id + "/")
additional_files_file = os.path.join(self.modelpath, 'additional_files.txt')
additional_files = []
if os.path.isfile(additional_files_file):
with open(additional_files_file) as fid:
additional_files = json.load(fid).get('input', [])
for src in self.htcFile.input_files() + self.htcFile.turbulence_files() + additional_files:
if not os.path.isabs(src):
src = os.path.join(self.modelpath, src)
for src_file in glob.glob(src):
dst = os.path.join(self.tmp_modelpath, os.path.relpath(src_file, self.modelpath))
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.copy(src_file, dst)
if not os.path.isfile(dst) or os.stat(dst).st_size != os.stat(src_file).st_size:
print ("error copy ", dst)
else:
#print (dst)
pass
self.logFile.filename = os.path.join(self.tmp_modelpath, self.log_filename)
self.simulationThread.modelpath = self.tmp_modelpath
def finish_simulation(self):
if self.status == CLEANED: return
files.extend(self.htcFile.turbulence_files())
for dst in files:
if not os.path.isabs(dst):
dst = os.path.join(self.modelpath, dst)
src = os.path.join(self.tmp_modelpath, os.path.relpath(dst, self.modelpath))
for src_file in glob.glob(src):
dst_file = os.path.join(self.modelpath, os.path.relpath(src_file, self.tmp_modelpath))
os.makedirs(os.path.dirname(dst_file), exist_ok=True)
if not os.path.isfile(dst_file) or os.path.getmtime(dst_file) != os.path.getmtime(src_file):
shutil.copy(src_file, dst_file)
self.logFile.filename = os.path.join(self.modelpath, self.log_filename)
try:
shutil.rmtree(self.tmp_modelpath)
except (PermissionError, OSError) as e:
raise Warning(str(e))
def simulate(self):
self.is_simulating = True
self.simulationThread.start()
self.simulationThread.join()
self.returncode, self.stderr, self.stdout = self.simulationThread.res
if self.returncode or 'error' in self.stderr.lower() or 'error' in self.stdout.lower():
print (self.returncode)
print ("stdout:\n", self.stdout)
print ("-"*50)
print ("stderr:\n", self.stderr)
print ("#"*50)
self.errors = (list(set([l for l in self.stderr.split("\n") if 'error' in l.lower()])))
self.status = ERROR
# else:
# self.stop()
# self.finish_simulation()
# self.controller.update_queues()
self.is_simulating = False
def start(self):
self.thread.start()
self.timer.stop()
self.simulationThread.process.kill()
try:
self.finish_simulation()
except:
pass
if self.logFile.status not in [log_file.DONE]:
self.logFile.status = ABORTED
#class SimulationProcess(Process):
#
# def __init__(self, modelpath, htcfile, hawc2exe="HAWC2MB.exe"):
# Process.__init__(self)
# self.modelpath = modelpath
# self.htcfile = os.path.abspath(htcfile)
# self.hawc2exe = hawc2exe
# self.res = [0, "", "", ""]
# self.process = process([self.hawc2exe, self.htcfile] , self.modelpath)
#
#
# def run(self):
# p = psutil.Process(os.getpid())
# p.nice = psutil.BELOW_NORMAL_PRIORITY_CLASS
# exec_process(self.process)
class SimulationThread(Thread):
def __init__(self, modelpath, htcfile, hawc2exe):
Thread.__init__(self)
self.modelpath = modelpath
self.htcfile = os.path.relpath(htcfile, self.modelpath)
self.hawc2exe = hawc2exe
self.res = [0, "", "", ""]
def start(self):
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
CREATE_NO_WINDOW = 0x08000000
self.process = subprocess.Popen([self.hawc2exe, self.htcfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, cwd=self.modelpath, creationflags=CREATE_NO_WINDOW)
Thread.start(self)
def run(self):
p = psutil.Process(os.getpid())
p.nice = psutil.BELOW_NORMAL_PRIORITY_CLASS
self.res = exec_process(self.process)
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
class RepeatedTimer(object):
def __init__(self, interval, function, *args, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
def _run(self):
self.is_running = False
self.start()
self.function(*self.args, **self.kwargs)
def start(self):
if not self.is_running:
self._timer = Timer(self.interval, self._run)
self._timer.start()
self.is_running = True
def stop(self):
self._timer.cancel()
self.is_running = False
if __name__ == "__main__":
sim = Simulation('C:\mmpe\HAWC2\Hawc2_model/', 'htc/error.htc')
sim.simulate()