Mage: Ensemble: Add bin reading method.

scenario-dev-pa
Pierre-Antoine 2026-08-21 15:27:35 +02:00
parent e7290fa81b
commit 51b3987a4a
2 changed files with 150 additions and 1 deletions

View File

@ -1513,6 +1513,145 @@ class Mage8(Mage):
return results
@timer
def read_ensemble_bin(self, study, fname, tables, run_number, qlog=None):
logger.info(f"read_bin: Start reading '{fname}' ...")
start = time.time()
with mage_file_open(fname, "r") as f:
def newline(): return np.fromfile(f, dtype=np.int32, count=1)
def endline(): return np.fromfile(f, dtype=np.int32, count=1)
def read_int(size): return np.fromfile(
f, dtype=np.int32, count=size)
def read_float(size): return np.fromfile(
f, dtype=np.float32, count=size)
def read_float64(size): return 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]
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)
endline()
# Reach information (2nd line)
newline()
_ = read_int(2*nb_reach)
endline()
# X (3rd line)
newline()
_ = read_float(nb_profile)
endline()
# Z and Y (4th line)
newline()
_ = read_float(3*nb_profile)
endline()
# Data
newline()
tmp_table = {}
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)
if key not in tmp_table:
tmp_table[key] = []
tmp_table[key].append(data)
endline()
end = newline().size <= 0
table = {}
for k in tmp_table:
table[k] = np.array(tmp_table[k])
self.read_ensemble_bin_agregate_data(
table, tables, run_number
)
logger.info(f"reading time: '{time.time() - start}'")
def read_ensemble_bin_agregate_data(self, tables, res, run_number):
z = tables["Z"]
q = tables["Q"]
if "z_mean" not in res:
res["z_mean"] = z
res["q_mean"] = q
res["z_min"] = z
res["z_max"] = z
res["q_min"] = q
res["q_max"] = q
# FIXME: Keep all results ?
res["traces"] = [(run_number, tables)]
else:
# Get mean results for Z and Q
res["z_mean"] = (res["z_mean"] + z) / 2
res["q_mean"] = (res["q_mean"] + q) / 2
# Z and Q min max values
res["z_min"] = np.minimum(z, res["z_min"])
res["z_max"] = np.maximum(z, res["z_max"])
res["q_min"] = np.minimum(q, res["q_min"])
res["q_max"] = np.maximum(q, res["q_max"])
# FIXME: Keep all results ?
res["traces"].append((run_number, tables))
@timer
def results_ensemble(self, study, repertory,
tables, run_number,
qlog=None, name=None):
self._study = study
if name is None:
name = study.name.replace(" ", "_")
fname = os.path.join(repertory, f"{name}.BIN".replace(" ", "_"))
if not os.path.isfile(fname):
logger.info(f"Result file {name}.BIN does not exist")
return None
try:
self.read_ensemble_bin(study, fname, tables, run_number, qlog)
except Exception as e:
logger.error(f"Failed to read results")
logger_exception(e)
return None
return True
class MageFake7(Mage8):
_type = "mage_fake7"

View File

@ -474,6 +474,8 @@ class SolverLogEnsWindow(SolverLogWindow):
self._samples[ens] = ens.get_sample(self._run_number)
self._results_tables = {}
super(SolverLogEnsWindow, self).__init__(
solver=solver,
study=study,
@ -503,7 +505,8 @@ class SolverLogEnsWindow(SolverLogWindow):
)
self.statusbar.showMessage(
"Done" if int_code == 0 else "Failed",
("Done" if int_code == 0 else "Failed")
+ f"#{self._last_run}",
3000
)
@ -515,6 +518,13 @@ class SolverLogEnsWindow(SolverLogWindow):
def next(self):
self._process = self.new_process(self._parent)
self._solver.results_ensemble(
self._study, self._workdir,
self._results_tables,
self._last_run,
qlog=self._output,
)
self._log(f" *** Run #{self._last_run}", color="blue")
self._solver.export_ensemble_variation(
self._study, self._workdir, qlog=self._output,