1818from ..v1 .math import sympify_petab
1919from . import C
2020
21+ __all__ = [
22+ "Observable" ,
23+ "ObservablesTable" ,
24+ "ObservableTransformation" ,
25+ "NoiseDistribution" ,
26+ "Change" ,
27+ "ChangeSet" ,
28+ "ConditionsTable" ,
29+ "OperationType" ,
30+ "ExperimentPeriod" ,
31+ "Experiment" ,
32+ "ExperimentsTable" ,
33+ "Measurement" ,
34+ "MeasurementTable" ,
35+ "Mapping" ,
36+ "MappingTable" ,
37+ "Parameter" ,
38+ "ParameterScale" ,
39+ "ParameterTable" ,
40+ ]
41+
2142
2243class ObservableTransformation (str , Enum ):
2344 """Observable transformation types.
@@ -51,6 +72,44 @@ class NoiseDistribution(str, Enum):
5172 LAPLACE = C .LAPLACE
5273
5374
75+ class ObjectivePriorType (str , Enum ):
76+ """Objective prior types.
77+
78+ Objective prior types as used in the PEtab parameters table.
79+ """
80+
81+ NORMAL = C .NORMAL
82+ LAPLACE = C .LAPLACE
83+ UNIFORM = C .UNIFORM
84+ LOG_NORMAL = C .LOG_NORMAL
85+ LOG_LAPLACE = C .LOG_LAPLACE
86+ PARAMETER_SCALE_NORMAL = C .PARAMETER_SCALE_NORMAL
87+ PARAMETER_SCALE_LAPLACE = C .PARAMETER_SCALE_LAPLACE
88+ PARAMETER_SCALE_UNIFORM = C .PARAMETER_SCALE_UNIFORM
89+
90+
91+ assert set (C .PRIOR_TYPES ) == {e .value for e in ObjectivePriorType }, (
92+ "ObjectivePriorType enum does not match C.PRIOR_TYPES: "
93+ f"{ set (C .PRIOR_TYPES )} vs { {e .value for e in ObjectivePriorType } } "
94+ )
95+
96+
97+ class InitializationPriorType (str , Enum ):
98+ """Initialization prior types.
99+
100+ Initialization prior types as used in the PEtab parameters table.
101+ """
102+
103+ NORMAL = C .NORMAL
104+ LAPLACE = C .LAPLACE
105+ UNIFORM = C .UNIFORM
106+ LOG_NORMAL = C .LOG_NORMAL
107+ LOG_LAPLACE = C .LOG_LAPLACE
108+ PARAMETER_SCALE_NORMAL = C .PARAMETER_SCALE_NORMAL
109+ PARAMETER_SCALE_LAPLACE = C .PARAMETER_SCALE_LAPLACE
110+ PARAMETER_SCALE_UNIFORM = C .PARAMETER_SCALE_UNIFORM
111+
112+
54113class Observable (BaseModel ):
55114 """Observable definition."""
56115
@@ -148,6 +207,9 @@ class OperationType(str, Enum):
148207 SET_CURRENT_VALUE = "setCurrentValue"
149208 SET_RATE = "setRate"
150209 SET_ASSIGNMENT = "setAssignment"
210+ ADD_TO_RATE = "addToRate"
211+ ADD_TO_ASSIGNMENT = "addToAssignment"
212+ NO_CHANGE = "noChange"
151213 CONSTANT = "constant"
152214 INITIAL = "initial"
153215 ...
@@ -192,7 +254,7 @@ def sympify(cls, v):
192254class ChangeSet (BaseModel ):
193255 """A set of changes to the model or model state.
194256
195- A set of simultaneously occuring changes to the model or model state,
257+ A set of simultaneously occurring changes to the model or model state,
196258 corresponding to a perturbation of the underlying system. This corresponds
197259 to all rows of the PEtab conditions table with the same condition ID.
198260 """
@@ -262,11 +324,21 @@ class ExperimentPeriod(BaseModel):
262324 """
263325
264326 start : float = Field (alias = C .TIME )
265- conditions : list [ChangeSet ]
327+ condition_ids : list [str ] = Field ( alias = C . CONDITION_ID )
266328
267329 class Config :
268330 populate_by_name = True
269331
332+ @field_validator ("condition_ids" )
333+ @classmethod
334+ def validate_id (cls , v ):
335+ for condition_id in v :
336+ if not condition_id :
337+ raise ValueError ("ID must not be empty." )
338+ if not is_valid_identifier (condition_id ):
339+ raise ValueError (f"Invalid ID: { condition_id } " )
340+ return v
341+
270342
271343class Experiment (BaseModel ):
272344 """An experiment or a timecourse defined by an ID and a set of different
@@ -283,32 +355,35 @@ class Config:
283355 populate_by_name = True
284356 arbitrary_types_allowed = True
285357
358+ @field_validator ("id" )
359+ @classmethod
360+ def validate_id (cls , v ):
361+ if not v :
362+ raise ValueError ("ID must not be empty." )
363+ if not is_valid_identifier (v ):
364+ raise ValueError (f"Invalid ID: { v } " )
365+ return v
366+
286367
287368class ExperimentsTable (BaseModel ):
288369 """PEtab experiments table."""
289370
290371 experiments : list [Experiment ]
291372
292373 @classmethod
293- def from_dataframe (
294- cls , df : pd .DataFrame , conditions : ConditionsTable = None
295- ) -> ExperimentsTable :
374+ def from_dataframe (cls , df : pd .DataFrame ) -> ExperimentsTable :
296375 if df is None :
297376 return cls (experiments = [])
298377
299- if conditions is None :
300- conditions = {}
301-
302378 experiments = []
303379 for experiment_id , cur_exp_df in df .groupby (C .EXPERIMENT_ID ):
304380 periods = []
305381 for time , cur_period_df in cur_exp_df .groupby (C .TIME ):
306- period_conditions = [
307- conditions [row [C .CONDITION_ID ]]
308- for _ , row in cur_period_df .iterrows ()
309- ]
382+ period_conditions = list (cur_period_df [C .CONDITION_ID ])
310383 periods .append (
311- ExperimentPeriod (start = time , conditions = period_conditions )
384+ ExperimentPeriod (
385+ start = time , condition_ids = period_conditions
386+ )
312387 )
313388 experiments .append (Experiment (id = experiment_id , periods = periods ))
314389
@@ -334,7 +409,6 @@ class Measurement(BaseModel):
334409 experiment.
335410 """
336411
337- # TODO: ID vs object
338412 observable_id : str = Field (alias = C .OBSERVABLE_ID )
339413 experiment_id : str | None = Field (alias = C .EXPERIMENT_ID , default = None )
340414 time : float = Field (alias = C .TIME )
@@ -396,8 +470,6 @@ class MeasurementTable(BaseModel):
396470 def from_dataframe (
397471 cls ,
398472 df : pd .DataFrame ,
399- observables_table : ObservablesTable ,
400- experiments_table : ExperimentsTable ,
401473 ) -> MeasurementTable :
402474 if df is None :
403475 return cls (measurements = [])
0 commit comments