Ensemble: Rename function to disctribution.

scenario-dev-pa
Pierre-Antoine 2026-09-10 15:56:29 +02:00
parent 4040b2456c
commit 345f24996f
8 changed files with 77 additions and 77 deletions

View File

@ -1,4 +1,4 @@
# Function.py -- Pamhyr # Distribution.py -- Pamhyr
# Copyright (C) 2026 INRAE # Copyright (C) 2026 INRAE
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@ -30,13 +30,13 @@ from Model.Scenario import Scenario
logger = logging.getLogger() logger = logging.getLogger()
class Function(SQLSubModel): class Distribution(SQLSubModel):
_sub_classes = [] _sub_classes = []
def __init__(self, id: int = -1, def __init__(self, id: int = -1,
name: str = "", script: str = "", name: str = "", script: str = "",
status=None): status=None):
super(Function, self).__init__( super(Distribution, self).__init__(
id=id, status=status, id=id, status=status,
owner_scenario=0 owner_scenario=0
) )
@ -57,7 +57,7 @@ class Function(SQLSubModel):
@classmethod @classmethod
def _db_create(cls, execute, ext=""): def _db_create(cls, execute, ext=""):
execute(f""" execute(f"""
CREATE TABLE ensemble_function{ext} ( CREATE TABLE ensemble_distribution{ext} (
{cls.create_db_add_pamhyr_id()}, {cls.create_db_add_pamhyr_id()},
deleted BOOLEAN NOT NULL DEFAULT FALSE, deleted BOOLEAN NOT NULL DEFAULT FALSE,
name TEXT NOT NULL, name TEXT NOT NULL,
@ -90,7 +90,7 @@ class Function(SQLSubModel):
table = execute( table = execute(
"SELECT pamhyr_id, deleted, name, script " + "SELECT pamhyr_id, deleted, name, script " +
"FROM ensemble_function " + "FROM ensemble_distribution " +
f"WHERE pamhyr_id NOT IN ({', '.join(map(str, loaded))})" f"WHERE pamhyr_id NOT IN ({', '.join(map(str, loaded))})"
) )
@ -102,20 +102,20 @@ class Function(SQLSubModel):
name = next(it) name = next(it)
script = next(it) script = next(it)
new_function = cls( new_distribution = cls(
id, name=name, script=script, id, name=name, script=script,
status=data["status"] status=data["status"]
) )
if deleted: if deleted:
new_function.set_as_deleted() new_distribution.set_as_deleted()
loaded.add(id) loaded.add(id)
new.append(new_function) new.append(new_distribution)
return new return new
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
# Only save custom function # Only save custom distribution
if self._type != "custom": if self._type != "custom":
return True return True
@ -124,7 +124,7 @@ class Function(SQLSubModel):
execute( execute(
"INSERT INTO " + "INSERT INTO " +
"ensemble_function(pamhyr_id, deleted, " + "ensemble_distribution(pamhyr_id, deleted, " +
" name, script) " + " name, script) " +
"VALUES (?, ?, ?, ?)", "VALUES (?, ?, ?, ?)",
self.pamhyr_id, self.is_deleted(), self.pamhyr_id, self.is_deleted(),
@ -145,10 +145,10 @@ class Function(SQLSubModel):
########################### ###########################
# FUNCTION IMPLEMENTATION # # DISTRIBUTION IMPLEMENTATION #
########################### ###########################
class Uniform(Function): class Uniform(Distribution):
_sub_classes = [] _sub_classes = []
def __init__(self, id: int = -1, def __init__(self, id: int = -1,
@ -168,7 +168,7 @@ class Uniform(Function):
return np.random.uniform(*lst) return np.random.uniform(*lst)
class Normal(Function): class Normal(Distribution):
_sub_classes = [] _sub_classes = []
def __init__(self, id: int = -1, def __init__(self, id: int = -1,
@ -188,7 +188,7 @@ class Normal(Function):
return np.random.normal(*lst) return np.random.normal(*lst)
class Poisson(Function): class Poisson(Distribution):
_sub_classes = [] _sub_classes = []
def __init__(self, id: int = -1, def __init__(self, id: int = -1,
@ -208,7 +208,7 @@ class Poisson(Function):
return np.random.poisson(*lst) return np.random.poisson(*lst)
class Custom(Function): class Custom(Distribution):
_sub_classes = [] _sub_classes = []
def __init__(self, id: int = -1, def __init__(self, id: int = -1,
@ -224,7 +224,7 @@ class Custom(Function):
def random(self, params, nb): def random(self, params, nb):
try: try:
# Run script to (re)define the sample function # Run script to (re)define the sample distribution
f = eval(self._script) f = eval(self._script)
return f(params, nb) return f(params, nb)
except Exception as e: except Exception as e:

View File

@ -1,4 +1,4 @@
# FunctionList.py -- Pamhyr # DistributionList.py -- Pamhyr
# Copyright (C) 2026 INRAE # Copyright (C) 2026 INRAE
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@ -19,25 +19,25 @@
from tools import trace, timer from tools import trace, timer
from Model.Tools.PamhyrListExt import PamhyrModelList from Model.Tools.PamhyrListExt import PamhyrModelList
from Model.Ensembles.Function import * from Model.Ensembles.Distribution import *
class FunctionList(PamhyrModelList): class DistributionList(PamhyrModelList):
_sub_classes = [Function] _sub_classes = [Distribution]
@classmethod @classmethod
def _db_load(cls, execute, data=None): def _db_load(cls, execute, data=None):
new = cls(status=data['status']) new = cls(status=data['status'])
# Default functions # Default distributions
new._lst = [ new._lst = [
Uniform(status=data['status']), Uniform(status=data['status']),
Normal(status=data['status']), Normal(status=data['status']),
Poisson(status=data['status']), Poisson(status=data['status']),
] ]
# DB custom functions # DB custom distributions
new._lst += Function._db_load( new._lst += Distribution._db_load(
execute, data execute, data
) )
@ -45,7 +45,7 @@ class FunctionList(PamhyrModelList):
def _db_save(self, execute, data={}): def _db_save(self, execute, data={}):
execute( execute(
"DELETE FROM ensemble_function" "DELETE FROM ensemble_distribution"
) )
for fun in self._lst: for fun in self._lst:

View File

@ -24,7 +24,7 @@ import numpy as np
from Model.Tools.PamhyrDB import SQLSubModel from Model.Tools.PamhyrDB import SQLSubModel
from Model.Scenario import Scenario from Model.Scenario import Scenario
from Model.Ensembles.Function import Uniform from Model.Ensembles.Distribution import Uniform
logger = logging.getLogger() logger = logging.getLogger()
@ -33,7 +33,7 @@ class Ensemble(SQLSubModel):
_sub_classes = [] _sub_classes = []
def __init__(self, id: int = -1, name: str = "", def __init__(self, id: int = -1, name: str = "",
function=None, params=[0., 100.], distribution=None, params=[0., 100.],
data_type=None, target_data=None, data_type=None, target_data=None,
status=None, owner_scenario=-1): status=None, owner_scenario=-1):
super(Ensemble, self).__init__( super(Ensemble, self).__init__(
@ -43,7 +43,7 @@ class Ensemble(SQLSubModel):
self._name = name self._name = name
self._data_type = data_type self._data_type = data_type
self._function = function self._distribution = distribution
self._params = params self._params = params
self._target_data = target_data self._target_data = target_data
@ -55,8 +55,8 @@ class Ensemble(SQLSubModel):
deleted BOOLEAN NOT NULL DEFAULT FALSE, deleted BOOLEAN NOT NULL DEFAULT FALSE,
name TEXT NOT NULL, name TEXT NOT NULL,
type VARCHAR(8) NOT NULL, type VARCHAR(8) NOT NULL,
function INTEGER NOT NULL, distribution INTEGER NOT NULL,
function_name VARCHAR(32) NOT NULL, distribution_name VARCHAR(32) NOT NULL,
params BLOB NOT NULL, params BLOB NOT NULL,
params_len INTEGER NOT NULL, params_len INTEGER NOT NULL,
data_pid INTEGER NOT NULL, data_pid INTEGER NOT NULL,
@ -86,13 +86,13 @@ class Ensemble(SQLSubModel):
def _db_load(cls, execute, data=None): def _db_load(cls, execute, data=None):
new = [] new = []
scenario = data["scenario"] scenario = data["scenario"]
functions = data["ens_functions"] distributions = data["ens_distributions"]
stricklers = data["stricklers"] stricklers = data["stricklers"]
loaded = data['loaded_pid'] loaded = data['loaded_pid']
table = execute( table = execute(
"SELECT pamhyr_id, deleted, name, type, " + "SELECT pamhyr_id, deleted, name, type, " +
"function, function_name, params, params_len, data_pid, " + "distribution, distribution_name, params, params_len, data_pid, " +
"scenario " + "scenario " +
"FROM ensemble " + "FROM ensemble " +
f"WHERE scenario = {scenario.id} " + f"WHERE scenario = {scenario.id} " +
@ -117,8 +117,8 @@ class Ensemble(SQLSubModel):
if fid != -1: if fid != -1:
def fn(f): return f._pamhyr_id == fid def fn(f): return f._pamhyr_id == fid
function = next( distribution = next(
filter(fn, functions.lst), filter(fn, distributions.lst),
None None
) )
@ -134,7 +134,7 @@ class Ensemble(SQLSubModel):
new_ensemble = cls( new_ensemble = cls(
id, name=name, id, name=name,
function=function, distribution=distribution,
params=rdata, params=rdata,
data_type=data_type, data_type=data_type,
target_data=target_data, target_data=target_data,
@ -161,14 +161,14 @@ class Ensemble(SQLSubModel):
bparams, length = self._encode_params() bparams, length = self._encode_params()
if self._function is None: if self._distribution is None:
fid = -1 fid = -1
fname = "NULL" fname = "NULL"
else: else:
fid = self._function._pamhyr_id fid = self._distribution._pamhyr_id
fname = self._function._name fname = self._distribution._name
if self._function._type == "generic": if self._distribution._type == "generic":
fid = -1 fid = -1
data_pid = -1 data_pid = -1
@ -178,7 +178,7 @@ class Ensemble(SQLSubModel):
execute( execute(
"INSERT INTO " + "INSERT INTO " +
"ensemble(pamhyr_id, deleted, name, type, " + "ensemble(pamhyr_id, deleted, name, type, " +
" function, function_name, params, params_len, " + " distribution, distribution_name, params, params_len, " +
" data_pid, scenario) " + " data_pid, scenario) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
self.pamhyr_id, self.is_deleted(), self.pamhyr_id, self.is_deleted(),
@ -203,7 +203,7 @@ class Ensemble(SQLSubModel):
def random(self, nb): def random(self, nb):
return np.nditer( return np.nditer(
self._function.random( self._distribution.random(
self._params, nb self._params, nb
) )
) )
@ -218,12 +218,12 @@ class Ensemble(SQLSubModel):
self._status.modified() self._status.modified()
@property @property
def function(self): def distribution(self):
return self._function return self._distribution
@function.setter @distribution.setter
def function(self, function): def distribution(self, distribution):
self._function = function self._distribution = distribution
self._status.modified() self._status.modified()
@property @property

View File

@ -33,7 +33,7 @@ from Model.Status import StudyStatus
from Model.Except import NotImplementedMethodeError from Model.Except import NotImplementedMethodeError
from Model.River import River from Model.River import River
from Model.Geometry.Reach import Reach from Model.Geometry.Reach import Reach
from Model.Ensembles.FunctionList import FunctionList from Model.Ensembles.DistributionList import DistributionList
from Model.HydraulicStructures.HydraulicStructures import ( from Model.HydraulicStructures.HydraulicStructures import (
HydraulicStructure HydraulicStructure
) )
@ -51,7 +51,7 @@ class Study(SQLModel):
_sub_classes = [ _sub_classes = [
Scenario, Scenario,
FunctionList, DistributionList,
River, River,
] ]
@ -87,7 +87,7 @@ class Study(SQLModel):
self.scenarios[0] = s0 self.scenarios[0] = s0
self.status.scenario = s0 self.status.scenario = s0
self._ens_functions = FunctionList(status=self.status) self._ens_distributions = DistributionList(status=self.status)
self._river = River(status=self.status) self._river = River(status=self.status)
else: else:
@ -399,12 +399,12 @@ class Study(SQLModel):
data["scenario"] = scenario data["scenario"] = scenario
data["loaded_pid"] = set() data["loaded_pid"] = set()
# Get ensemble function # Get ensemble distribution
new._ens_functions = FunctionList._db_load( new._ens_distributions = DistributionList._db_load(
sql_exec, data=data sql_exec, data=data
) )
data["ens_functions"] = new._ens_functions data["ens_distributions"] = new._ens_distributions
# Load river data # Load river data
new._river = River._db_load( new._river = River._db_load(
@ -468,7 +468,7 @@ class Study(SQLModel):
if self.status.scenario.is_ensemble(): if self.status.scenario.is_ensemble():
lst = [ lst = [
self.scenarios, self._ens_functions, self.scenarios, self._ens_distributions,
self._river._ensembles, self._river._ensembles,
] ]
for solv in self._river._results: for solv in self._river._results:
@ -484,7 +484,7 @@ class Study(SQLModel):
self._save_submodel( self._save_submodel(
[ [
self.scenarios, self._ens_functions, self.scenarios, self._ens_distributions,
self._river self._river
], ],
data=progress data=progress
@ -605,7 +605,7 @@ class Study(SQLModel):
"status": self.status, "status": self.status,
"loaded_pid": set(), "loaded_pid": set(),
"scenario": scenario, "scenario": scenario,
"ens_functions": self._ens_functions, "ens_distributions": self._ens_distributions,
} }
self.status.start_loading() self.status.start_loading()

View File

@ -36,7 +36,7 @@ from PyQt5.QtWidgets import (
from View.Ensembles.UndoCommand import ( from View.Ensembles.UndoCommand import (
SetNameCommand, SetTypeCommand, SetDataCommand, SetNameCommand, SetTypeCommand, SetDataCommand,
SetFunctionCommand, SetDistributionCommand,
AddCommand, DelCommand, AddCommand, DelCommand,
) )
@ -96,13 +96,13 @@ class ComboBoxDelegate(QItemDelegate):
) )
) )
) )
elif self._mode == "function": elif self._mode == "distribution":
self.editor.addItems( self.editor.addItems(
[self._trad["not_defined"]] + [self._trad["not_defined"]] +
list( list(
map( map(
lambda f: f.name, lambda f: f.name,
self._study._ens_functions.lst self._study._ens_distributions.lst
) )
) )
) )
@ -133,11 +133,11 @@ class ComboBoxDelegate(QItemDelegate):
), ),
None None
) )
elif self._mode == "function": elif self._mode == "distribution":
value = next( value = next(
filter( filter(
lambda f: f.name == text, lambda f: f.name == text,
self._study._ens_functions.lst self._study._ens_distributions.lst
), ),
None None
) )
@ -182,8 +182,8 @@ class EnsembleTableModel(PamhyrTableModel):
if value is None: if value is None:
return self._trad["not_defined"] return self._trad["not_defined"]
return str(value) return str(value)
elif self._headers[column] == "function": elif self._headers[column] == "distribution":
value = self._lst.get(row).function value = self._lst.get(row).distribution
if value is None: if value is None:
return self._trad["not_defined"] return self._trad["not_defined"]
return value.name return value.name
@ -222,9 +222,9 @@ class EnsembleTableModel(PamhyrTableModel):
self._lst, row, value self._lst, row, value
) )
) )
elif self._headers[column] == "function": elif self._headers[column] == "distribution":
self._undo.push( self._undo.push(
SetFunctionCommand( SetDistributionCommand(
self._lst, row, value self._lst, row, value
) )
) )

View File

@ -45,6 +45,6 @@ class EnsemblesTranslate(MainTranslate):
"name": self._dict["name"], "name": self._dict["name"],
"type": _translate("Ensembles", "Type"), "type": _translate("Ensembles", "Type"),
"target_data": _translate("Ensembles", "Target data"), "target_data": _translate("Ensembles", "Target data"),
"function": _translate("Ensembles", "Function"), "distribution": _translate("Ensembles", "Distribution"),
"parameters": _translate("Ensembles", "Parameters"), "parameters": _translate("Ensembles", "Parameters"),
} }

View File

@ -77,20 +77,20 @@ class SetDataCommand(QUndoCommand):
self._ensembles.get(self._index).target_data = self._new self._ensembles.get(self._index).target_data = self._new
class SetFunctionCommand(QUndoCommand): class SetDistributionCommand(QUndoCommand):
def __init__(self, ensembles, index, function): def __init__(self, ensembles, index, distribution):
QUndoCommand.__init__(self) QUndoCommand.__init__(self)
self._ensembles = ensembles self._ensembles = ensembles
self._index = index self._index = index
self._old = self._ensembles.get(self._index).function self._old = self._ensembles.get(self._index).distribution
self._new = function self._new = distribution
def undo(self): def undo(self):
self._ensembles.get(self._index).function = self._old self._ensembles.get(self._index).distribution = self._old
def redo(self): def redo(self):
self._ensembles.get(self._index).function = self._new self._ensembles.get(self._index).distribution = self._new
class AddCommand(QUndoCommand): class AddCommand(QUndoCommand):

View File

@ -94,10 +94,10 @@ class EnsemblesWindow(PamhyrWindow):
parent=self parent=self
) )
self._delegate_function = ComboBoxDelegate( self._delegate_distribution = ComboBoxDelegate(
data=self._ensembles, data=self._ensembles,
study=self._study, study=self._study,
mode="function", mode="distribution",
trad=self._trad, trad=self._trad,
parent=self parent=self
) )
@ -105,7 +105,7 @@ class EnsemblesWindow(PamhyrWindow):
return { return {
"type": self._delegate_data_type, "type": self._delegate_data_type,
"target_data": self._delegate_stricklers, "target_data": self._delegate_stricklers,
"function": self._delegate_function, "distribution": self._delegate_distribution,
} }
def setup_table(self): def setup_table(self):
@ -114,7 +114,7 @@ class EnsemblesWindow(PamhyrWindow):
delegates = self.setup_table_delegate() delegates = self.setup_table_delegate()
editable_headers = [ editable_headers = [
"name", "type", "function", "target_data" "name", "type", "distribution", "target_data"
] ]
table = self.find(QTableView, f"tableView") table = self.find(QTableView, f"tableView")
@ -185,7 +185,7 @@ class EnsemblesWindow(PamhyrWindow):
for row in rows: for row in rows:
try: try:
ens = self._ensembles.get(row) ens = self._ensembles.get(row)
len_params = len(ens.function.labels) len_params = len(ens.distribution.labels)
if len_params == 1: if len_params == 1:
dlg = Ensemble1ParamsDialog( dlg = Ensemble1ParamsDialog(
@ -221,7 +221,7 @@ class Ensemble1ParamsDialog(PamhyrDialog):
) )
self._ensemble = ensemble self._ensemble = ensemble
self._labels = ensemble.function.labels self._labels = ensemble.distribution.labels
self._init_default_labels() self._init_default_labels()
self._init_default_values() self._init_default_values()
@ -263,7 +263,7 @@ class Ensemble2ParamsDialog(PamhyrDialog):
) )
self._ensemble = ensemble self._ensemble = ensemble
self._labels = ensemble.function.labels self._labels = ensemble.distribution.labels
self._init_default_labels() self._init_default_labels()
self._init_default_values() self._init_default_values()