55
66from collections import Counter
77from ..C import (COPY_FROM , USE_DEFAULT , NO_DEFAULT , MIN_COLUMN , MAX_COLUMN ,
8- MODE , DEFAULT_VALUE , SOURCE_COLUMN , STRATEGIES_DEFAULT )
8+ MODE , DEFAULT_VALUE , SOURCE_COLUMN , SBML_LOOK )
99
1010
1111class DefaultHandlerModel :
12- def __init__ (self , model , config ):
12+ def __init__ (self , model , config , sbml_model = None ):
1313 """
1414 Initialize the handler for the model.
1515 :param model: The PandasTable Model containing the Data.
@@ -20,12 +20,21 @@ def __init__(self, model, config):
2020 self .model = model ._data_frame
2121 self .config = config
2222 self .model_index = self .model .index .name
23+ self ._sbml_model = sbml_model
2324
24- def get_default (self , column_name , row_index = None ):
25+ def get_default (
26+ self ,
27+ column_name ,
28+ row_index = None ,
29+ par_scale = None ,
30+ changed : dict | None = None ,
31+ ):
2532 """
2633 Get the default value for a column based on its strategy.
2734 :param column_name: The name of the column to compute the default for.
2835 :param row_index: Optional index of the row (needed for some strategies).
36+ :param par_scale: Optional parameter scale (needed for some strategies).
37+ :param changed: Optional tuple containing the column name and index of the changed cell.
2938 :return: The computed default value.
3039 """
3140 source_column = column_name
@@ -40,40 +49,64 @@ def get_default(self, column_name, row_index=None):
4049 default_value = column_config .get (DEFAULT_VALUE , "" )
4150
4251 if strategy == USE_DEFAULT :
52+ if self .model .dtypes [column_name ] == float :
53+ return float (default_value )
4354 return default_value
4455 elif strategy == NO_DEFAULT :
4556 return ""
4657 elif strategy == MIN_COLUMN :
47- return self ._min_column (column_name )
58+ return self ._min_column (column_name , par_scale )
4859 elif strategy == MAX_COLUMN :
49- return self ._max_column (column_name )
60+ return self ._max_column (column_name , par_scale )
5061 elif strategy == COPY_FROM :
51- return self ._copy_column (column_name , column_config , row_index )
62+ return self ._copy_column (
63+ column_name , column_config , row_index , changed
64+ )
5265 elif strategy == MODE :
5366 column_config [SOURCE_COLUMN ] = source_column
5467 return self ._majority_vote (column_name , column_config )
68+ elif strategy == SBML_LOOK :
69+ return self ._sbml_lookup (row_index )
5570 else :
5671 raise ValueError (f"Unknown strategy '{ strategy } ' for column '{ column_name } '." )
5772
58- def _min_column (self , column_name ):
59- if column_name in self .model :
60- column_data = self .model [column_name ].replace ("" , np .nan ).dropna ()
61- if not column_data .empty :
62- return column_data .min ()
63- return ""
73+ def _min_column (self , column_name , par_scale = None ):
74+ if column_name not in self .model :
75+ return ""
76+ column_data = self .model [column_name ].replace ("" , np .nan ).dropna ()
77+ if column_name in ["upperBound" , "lowerBound" ]:
78+ column_data = column_data .loc [
79+ self .model ["parameterScale" ] == par_scale
80+ ]
81+ if not column_data .empty :
82+ return column_data .min ()
6483
65- def _max_column (self , column_name ):
66- if column_name in self .model :
67- column_data = self .model [column_name ].replace ("" , np .nan ).dropna ()
68- if not column_data .empty :
69- return column_data .max ()
70- return ""
84+ def _max_column (self , column_name , par_scale = None ):
85+ if column_name not in self .model :
86+ return ""
87+ column_data = self .model [column_name ].replace ("" , np .nan ).dropna ()
88+ if column_name in ["upperBound" , "lowerBound" ]:
89+ column_data = column_data .loc [
90+ self .model ["parameterScale" ] == par_scale
91+ ]
92+ if not column_data .empty :
93+ return column_data .max ()
7194
72- def _copy_column (self , column_name , config , row_index ):
95+ def _copy_column (
96+ self ,
97+ column_name ,
98+ config ,
99+ row_index ,
100+ changed : dict | None = None
101+ ):
102+ """Copy the value from another column in the same row."""
73103 source_column = config .get (SOURCE_COLUMN , column_name )
74104 source_column_valid = (
75105 source_column in self .model or source_column == self .model_index
76106 )
107+ if changed :
108+ if source_column in changed .keys ():
109+ return changed [source_column ]
77110 if source_column and source_column_valid and row_index is not None :
78111 prefix = config .get ("prefix" , "" )
79112 if row_index in self .model .index :
@@ -100,3 +133,20 @@ def _majority_vote(self, column_name, config):
100133 value_counts = Counter (valid_values )
101134 return value_counts .most_common (1 )[0 ][0 ]
102135 return ""
136+
137+ def _sbml_lookup (self , row_key ):
138+ """Use the most frequent value in the column as the default.
139+
140+ Defaults to last used value in case of a tie.
141+ """
142+ if self ._sbml_model is None :
143+ return 1
144+ if row_key is None :
145+ return 1
146+ curr_model = self ._sbml_model .get_current_sbml_model ()
147+ if curr_model is None :
148+ return 1
149+ parameters = curr_model .get_valid_parameters_for_parameter_table ()
150+ if row_key not in list (parameters ):
151+ return 1
152+ return curr_model .get_parameter_value (row_key )
0 commit comments