2424
2525from sbmlsim .sensitivity .parameters import SensitivityParameter
2626from sbmlsim .sensitivity .outputs import SensitivityOutput
27+ from sbmlsim .sensitivity .plots import heatmap
2728
2829
2930class SensitivitySimulation :
@@ -112,9 +113,10 @@ def __init__(self,
112113 self .samples : Optional [xr .DataArray ] = None
113114 # outputs for given samples; shape: (num_samples x num_outputs)
114115 self .results : Optional [xr .DataArray ] = None
116+
117+ # multiple sensitivities are stored
115118 # sensitivity matrix; shape: (num_parameters x num_outputs); could be multiple
116- self .sensitivity : Optional [xr .DataArray ] = None
117- self .sensitivity_normalized : Optional [xr .DataArray ] = None
119+ self .sensitivity : dict [str , xr .DataArray ] = {}
118120
119121
120122 @property
@@ -156,12 +158,19 @@ def simulate_samples(self) -> None:
156158 outputs = self .sensitivity_simulation .simulate (changes = changes )
157159 self .results [k , :] = list (outputs .values ())
158160
159-
160161 def calculate_sensitivity (self ):
161- """Calculate the sensitivity matrix ."""
162+ """Calculate the sensitivity matrices ."""
162163
163164 raise NotImplemented
164165
166+ def sensitivity_df (self , key = "normalized" ) -> pd .DataFrame :
167+ """Convert sensitivity information to dataframe."""
168+
169+ return pd .DataFrame (
170+ self .sensitivity [key ].values ,
171+ columns = self .sensitivity [key ].coords ["output" ],
172+ index = self .sensitivity [key ].coords ["parameter" ]
173+ )
165174
166175
167176class LocalSensitivityAnalysis (SensitivityAnalysis ):
@@ -174,7 +183,7 @@ def __init__(self, sensitivity_simulation: SensitivitySimulation,
174183 parameters : list [SensitivityParameter ], difference : float = 0.01 ):
175184
176185 super ().__init__ (sensitivity_simulation , parameters )
177- self . sensitivity : np . ndarray = np . zeros ( shape = ( self . num_parameters , self . num_outputs ))
186+
178187 self .difference : float = difference
179188 self .create_samples ()
180189
@@ -224,24 +233,19 @@ def calculate_sensitivity(self):
224233 """Calculate the two-sided local sensitivity matrix."""
225234
226235 # num_parameters x num_outputs
227- # empty sensitivity
228- self .sensitivity = xr .DataArray (
236+ for key in [ "raw" , "normalized" ]:
237+ self .sensitivity [ key ] = xr .DataArray (
229238 np .full ((self .num_parameters , self .num_outputs ), np .nan ),
230239 dims = ["parameter" , "output" ],
231240 coords = {"parameter" : self .parameter_ids ,
232241 "output" : self .output_ids },
233- name = "sensitivity"
234- )
235- self .sensitivity_normalized = xr .DataArray (
236- np .full ((self .num_parameters , self .num_outputs ), np .nan ),
237- dims = ["parameter" , "output" ],
238- coords = {"parameter" : self .parameter_ids ,
239- "output" : self .output_ids },
240- name = "sensitivity"
242+ name = key
241243 )
242244
245+ sensitivity_raw = self .sensitivity ["raw" ]
246+ sensitivity_normalized = self .sensitivity ["normalized" ]
247+
243248 for kp , p in enumerate (self .parameters ):
244- pid = self .parameters [kp ].uid
245249 p_ref = self .samples [- 1 , kp ]
246250 p_up = self .samples [2 * kp , kp ]
247251 p_down = self .samples [2 * kp + 1 , kp ]
@@ -253,21 +257,13 @@ def calculate_sensitivity(self):
253257 q_down = self .results [2 * kp + 1 , ko ]
254258
255259 # two-sided sensitivity
256- self . sensitivity [kp , ko ] = (q_up - q_down ) / (p_up - p_down )
260+ sensitivity_raw [kp , ko ] = (q_up - q_down ) / (p_up - p_down )
257261 # normalized: relative change in output per relative change in parameter
258- self . sensitivity_normalized [kp , ko ] = self . sensitivity [kp , ko ] * p_ref / q_ref
262+ sensitivity_normalized [kp , ko ] = sensitivity_raw [kp , ko ] * p_ref / q_ref
259263
260- @property
261- def sensitivity_df (self ) -> pd .DataFrame :
262- """Convert sensitivity information to dataframe."""
263- return pd .DataFrame (
264- self .sensitivity_normalized .values ,
265- columns = self .sensitivity .coords ["output" ],
266- index = self .sensitivity .coords ["parameter" ]
267- )
268264
269265 def plot_sensitivity (self , cutoff = 0.1 , cluster_rows : bool = True , title : Optional [str ] = None ):
270- df = self .sensitivity_df
266+ df = self .sensitivity_df ( key = "normalized" )
271267 self .plot_sensitivity_df (
272268 df = df ,
273269 parameter_labels = {p .uid : p .name for p in self .parameters },
@@ -285,7 +281,6 @@ def plot_sensitivity_df(
285281 cutoff = 0.1 , cluster_rows : bool = True ,
286282 title : Optional [str ] = None ,
287283 ):
288- from sbmlsim .sensitivity .plots import heatmap
289284 console .print (df )
290285
291286 heatmap (
@@ -310,9 +305,13 @@ class SobolSensitivityAnalysis:
310305
311306 sensitivity_simulation : SensitivitySimulation
312307
313- def __init__ (self , sensitivity_simulation : SensitivitySimulation ):
308+ def __init__ (self ,
309+ sensitivity_simulation : SensitivitySimulation ,
310+ parameters : list [SensitivityParameter ],
311+ ):
314312 # assign simulation
315313 self .sensitivity_simulation = sensitivity_simulation
314+ self .parameters = parameters
316315
317316 self .sensitivity = np .zeros (shape = (self .num_parameters , self .num_outputs ))
318317
0 commit comments