From fb842346c388e959e9cfb37705e3a4c697ada5a1 Mon Sep 17 00:00:00 2001 From: madsmpedersen <m@madsp.dk> Date: Fri, 27 Nov 2015 08:44:45 +0100 Subject: [PATCH] status enum changes --- wetb/hawc2/log_file.py | 35 ++++++++++------- wetb/hawc2/simulation.py | 84 +++++++++++++++++++++++++++------------- 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/wetb/hawc2/log_file.py b/wetb/hawc2/log_file.py index 1b80353..fe9b250 100644 --- a/wetb/hawc2/log_file.py +++ b/wetb/hawc2/log_file.py @@ -13,11 +13,7 @@ MISSING = "Log file cannot be found" PENDING = "Simulation not started yet" INITIALIZATION = 'Initializing simulation' SIMULATING = "Simulating" -ABORTED = "" DONE = "Simulation succeded" -INITIALIZATION_ERROR = "Initialization error" -SIMULATION_ERROR = "Simulation error" -ERROR = "Error" def is_file_open(filename): try: @@ -64,16 +60,19 @@ class LogFile(object): pass self.reset() - def extract_time(self, time_line): - time_line = time_line.strip() - if 'Starting simulation' == time_line: - return 0 + def extract_time(self, txt): + i1 = txt.rfind("Global time") + if i1 == -1: + return self.current_time + else: + time_line = txt[i1:].strip() + if time_line == "": return self.current_time try: return float(time_line[time_line.index('=') + 1:time_line.index('Iter')]) except: - print ("#" + time_line + "#") + print ("Cannot extract time from #" + time_line + "#") pass def update_status(self): @@ -91,7 +90,8 @@ class LogFile(object): self.status = INITIALIZATION if len(txt) > 0: - self.lastline = (txt.strip()[max(0, txt.strip().rfind("\n")):]).strip() + if len(txt.strip()): + self.lastline = (txt.strip()[max(0, txt.strip().rfind("\n")):]).strip() if self.status == INITIALIZATION: init_txt, *rest = txt.split("Starting simulation") if "*** ERROR ***" in init_txt: @@ -100,18 +100,23 @@ class LogFile(object): txt = rest[0] self.status = SIMULATING if not 'Elapsed time' in self.lastline: - self.start_time = (self.extract_time(self.lastline), time.time()) + i1 = txt.rfind("Global time") + if i1 > -1: + self.start_time = (self.extract_time(txt[i1:]), time.time()) if self.status == SIMULATING: simulation_txt, *rest = txt.split('Elapsed time') if "*** ERROR ***" in simulation_txt: self.errors.extend([l.strip() for l in simulation_txt.strip().split("\n") if "error" in l.lower()]) i1 = simulation_txt.rfind("Global time") - i2 = simulation_txt[:i1].rfind('Global time') - self.current_time = self.extract_time(simulation_txt[i1:]) - self.pct = int(100 * self.current_time // self.time_stop) - if self.current_time is not None and self.start_time is not None and (self.current_time - self.start_time[0]) > 0: + if i1 > -1: + self.current_time = self.extract_time(simulation_txt[i1:]) + if self.time_stop > 0: + self.pct = int(100 * self.current_time // self.time_stop) + try: self.remaining_time = (time.time() - self.start_time[1]) / (self.current_time - self.start_time[0]) * (self.time_stop - self.current_time) + except: + pass if rest: self.status = DONE self.pct = 100 diff --git a/wetb/hawc2/simulation.py b/wetb/hawc2/simulation.py index 7685a0f..50a41dd 100644 --- a/wetb/hawc2/simulation.py +++ b/wetb/hawc2/simulation.py @@ -1,6 +1,6 @@ import os from wetb.hawc2.htc_file import HTCFile -from wetb.hawc2.log_file import LogFile, SIMULATING +from wetb.hawc2.log_file import LogFile from threading import Timer, Thread import sys from multiprocessing.process import Process @@ -10,10 +10,17 @@ import subprocess import shutil import json import glob +from wetb.hawc2 import log_file - +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 @@ -22,24 +29,35 @@ class Simulation(object): self.folder = os.path.dirname(htcfilename) if not os.path.isabs(htcfilename): htcfilename = os.path.join(modelpath, htcfilename) - + self.htcfilename = htcfilename self.filename = os.path.basename(htcfilename) self.htcFile = HTCFile(htcfilename) self.time_stop = self.htcFile.simulation.time_stop[0] - + self.copy_turbulence = True 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.last_status = (0, "Pending", []) + self._status = QUEUED self.thread = Thread(target=self.simulate) self.simulationThread = SimulationThread(self.modelpath, self.htcFile.filename, hawc2exe) self.timer = RepeatedTimer(1, self.update_status) + def __str__(self): + return "Simulation(%s)" % self.filename def update_status(self, *args, **kwargs): + 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): status = self.logFile.status() if status[1] == SIMULATING: if self.last_status[1] != SIMULATING: @@ -83,54 +101,66 @@ class Simulation(object): - def finish_simulation(self, copy_turbulence): + def finish_simulation(self): + if self.status == CLEANED: return files = self.htcFile.output_files() - if copy_turbulence: + if self.copy_turbulence: 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)) - if os.path.isfile(src): - os.makedirs(os.path.dirname(dst), exist_ok=True) - if not os.path.isfile(dst) or os.path.getmtime(dst) != os.path.getmtime(src): - shutil.copy(src, dst) + + 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)) - shutil.rmtree(self.tmp_modelpath) + self.status = CLEANED def simulate(self): - self.is_simulating = True - self.timer.start() + self.logFile.clear() + self.status = INITIALIZING + self.simulationThread.start() self.simulationThread.join() - - errorcode, stdout, stderr, cmd = self.simulationThread.res - if errorcode: - print (errorcode) - print (stdout) - print (stderr) - print (cmd) - self.timer.stop() + 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.logFile.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 - self.update_status() def start(self): - self.thread.start() - def terminate(self): + def stop(self): self.timer.stop() self.simulationThread.process.kill() - self.simulationThread.join() + self.finish_simulation() + if self.logFile.status not in [log_file.DONE]: + self.logFile.status = ABORTED class SimulationProcess(Process): -- GitLab