From d78310476ec44d52b252008208772c4899102b3d Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr> Date: Tue, 8 Aug 2023 13:48:01 +0200 Subject: [PATCH] Results: Add results model, view scheme and mage results reading. --- src/Model/Saved.py | 2 +- src/Solver/ASolver.py | 14 ++++ src/Solver/Mage.py | 139 +++++++++++++++++++++++++++++++++++ src/View/RunSolver/Window.py | 15 +++- src/View/ui/SolverLog.ui | 6 ++ 5 files changed, 174 insertions(+), 2 deletions(-) diff --git a/src/Model/Saved.py b/src/Model/Saved.py index a1b91fd5..60013cde 100644 --- a/src/Model/Saved.py +++ b/src/Model/Saved.py @@ -33,5 +33,5 @@ class SavedStatus(object): self._saved = True def modified(self): - logger.debug("model status set as modified") + # logger.debug("model status set as modified") self._saved = False diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index 300bb36c..64cc01cb 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -19,6 +19,8 @@ import os import logging +from tools import timer + try: from signal import SIGTERM, SIGSTOP, SIGCONT _signal = True @@ -29,6 +31,9 @@ from enum import Enum from Model.Except import NotImplementedMethodeError +from Model.Results.Results import Results +from Model.Results.River.River import River, Reach, Profile + logger = logging.getLogger() class STATUS(Enum): @@ -164,6 +169,15 @@ class AbstractSolver(object): """ raise NotImplementedMethodeError(self, self.log_file) + ########### + # RESULTS # + ########### + + @timer + def results(self, study, repertory, qlog = None): + results = Results(study = study) + return results + ####### # Run # ####### diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index 0d43d2ef..907f5ff3 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -17,12 +17,19 @@ # -*- coding: utf-8 -*- import os +import logging +import numpy as np from tools import timer from Solver.ASolver import AbstractSolver from Checker.Mage import MageNetworkGraphChecker +from Model.Results.Results import Results +from Model.Results.River.River import River, Reach, Profile + +logger = logging.getLogger() + def mage_file_open(filepath, mode): f = open(filepath, mode) @@ -337,6 +344,21 @@ class Mage(AbstractSolver): return True + ########### + # RESULTS # + ########### + + def read_bin(self, study, repertory, results, qlog = None): + return + + @timer + def results(self, study, repertory, qlog = None): + results = Results(study = study) + + self.read_bin(study, repertory, results, qlog) + + return results + ########## # MAGE 7 # ########## @@ -450,3 +472,120 @@ class Mage8(Mage): self._export_REP(study, repertory, files, qlog) return True + + ########### + # RESULTS # + ########### + + def read_bin(self, study, repertory, results, qlog = None): + with mage_file_open(os.path.join(repertory, f"0.BIN"), "r") as f: + newline = lambda: np.fromfile(f, dtype=np.int32, count=1) + endline = lambda: np.fromfile(f, dtype=np.int32, count=1) + + read_int = lambda size: np.fromfile(f, dtype=np.int32, count=size) + read_float = lambda size: np.fromfile(f, dtype=np.float32, count=size) + read_float64 = lambda size: np.fromfile(f, dtype=np.float64, count=size) + + # Meta data (1st line) + newline() + + data = read_int(3) + + nb_reach = data[0] + nb_profile = data[1] + mage_version = data[2] + + logger.debug(f"read_bin: nb_reach = {nb_reach}") + logger.debug(f"read_bin: nb_profile = {nb_profile}") + logger.debug(f"read_bin: mage_version = {mage_version}") + + if mage_version <= 80: + msg = ( + "Read BIN files: " + + f"Possible incompatible mage version '{mage_version}', " + + "please check your solver configuration..." + ) + logger.warning(msg) + + if qlog is not None: + qlog.put("[WARNING] " + msg) + + results.set("solver_version", f"Mage8 ({mage_version})") + results.set("nb_reach", f"{nb_reach}") + results.set("nb_profile", f"{nb_profile}") + + endline() + + # Reach information (2nd line) + newline() + + reachs = [] + iprofiles = {} + reach_offset = {} + + ip_to_r = lambda i: iprofiles[ + next( + filter( + lambda k: k[0] <= i <= k[1], + iprofiles + ) + ) + ] + ip_to_ri = lambda r, i: i - reach_offset[r] + + data = read_int(2*nb_reach) + + for i in range(nb_reach): + # Add results reach to reach list + r = results.river.add(i) + reachs.append(r) + + # ID of first and last reach profiles + i1 = data[2*i] - 1 + i2 = data[2*i+1] - 1 + + # Add profile id correspondance to reach + key = (i1, i2) + iprofiles[key] = r + + # Profile ID offset + reach_offset[r] = i1 + + logger.debug(f"read_bin: iprofiles = {iprofiles}") + + endline() + + # X (3rd line) + newline() + _ = read_float(nb_profile) + endline() + + # Z and Y (4th line) + newline() + _ = read_float(3*nb_profile) + endline() + + # Data + newline() + + end = False + while not end: + n = read_int(1)[0] + timestamp = read_float64(1)[0] + key = bytearray(np.fromfile(f, dtype=np.byte, count=1)).decode() + data = read_float(n) + + logger.debug(f"read_bin: timestamp = {timestamp} sec") + for i, d in enumerate(data): + # Get reach corresponding to profile ID + reach = ip_to_r(i) + # Get profile id in reach + ri = ip_to_ri(reach, i) + + # Set data for profile RI + reach.set(ri, timestamp, key, d) + + endline() + end = newline().size <= 0 + + logger.info(reachs[0].profiles[0]._data) diff --git a/src/View/RunSolver/Window.py b/src/View/RunSolver/Window.py index 4f915950..b03a4603 100644 --- a/src/View/RunSolver/Window.py +++ b/src/View/RunSolver/Window.py @@ -16,8 +16,9 @@ # -*- coding: utf-8 -*- -import tempfile import os +import logging +import tempfile from queue import Queue from tools import trace, timer @@ -53,6 +54,8 @@ except: _translate = QCoreApplication.translate +logger = logging.getLogger() + class SelectSolverWindow(ASubWindow, ListedSubWindow): def __init__(self, title="Select solver", study=None, config=None, @@ -110,6 +113,8 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self._config = config self._solver = solver + self._results = None + super(SolverLogWindow, self).__init__( name=self._title, ui="SolverLog", parent=parent ) @@ -169,6 +174,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_pause").triggered.connect(self.pause) self.find(QAction, "action_stop").triggered.connect(self.stop) self.find(QAction, "action_log_file").triggered.connect(self.log_file) + self.find(QAction, "action_results").triggered.connect(self.results) self._alarm.timeout.connect(self.update) @@ -193,6 +199,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_start").setEnabled(True) self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(False) + self.find(QAction, "action_results").setEnabled(True) if self._solver.log_file() != "": self.find(QAction, "action_log_file").setEnabled(True) @@ -221,6 +228,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(True) self.find(QAction, "action_log_file").setEnabled(False) + self.find(QAction, "action_results").setEnabled(False) def pause(self): self._log(" *** Pause", color="blue") @@ -229,6 +237,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_start").setEnabled(True) self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(True) + self.find(QAction, "action_results").setEnabled(False) def stop(self): self._log(" *** Stop", color="blue") @@ -237,9 +246,13 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_start").setEnabled(True) self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(False) + self.find(QAction, "action_results").setEnabled(True) if self._solver.log_file() != "": self.find(QAction, "action_log_file").setEnabled(True) + def results(self): + self._results = self._solver.results(self._study, self._workdir, qlog = self._output) + def log_file(self): file_name = os.path.join(self._workdir, self._solver.log_file()) log = SolverLogFileWindow( diff --git a/src/View/ui/SolverLog.ui b/src/View/ui/SolverLog.ui index bbbc3edb..c94c57db 100644 --- a/src/View/ui/SolverLog.ui +++ b/src/View/ui/SolverLog.ui @@ -63,6 +63,7 @@ <addaction name="action_pause"/> <addaction name="action_stop"/> <addaction name="action_log_file"/> + <addaction name="action_results"/> </widget> <action name="action_stop"> <property name="icon"> @@ -100,6 +101,11 @@ <string>LogFile</string> </property> </action> + <action name="action_results"> + <property name="text"> + <string>results</string> + </property> + </action> </widget> <resources/> <connections/> -- GitLab