@@ -458,7 +458,7 @@ def free_symbols(self) -> set[sp.Symbol]:
458458
459459class ExperimentPeriod (BaseModel ):
460460 """A period of a timecourse or experiment defined by a start time
461- and a condition ID .
461+ and a list of condition IDs .
462462
463463 This corresponds to a row of the PEtab experiments table.
464464 """
@@ -467,20 +467,19 @@ class ExperimentPeriod(BaseModel):
467467 time : Annotated [float , AfterValidator (_is_finite_or_neg_inf )] = Field (
468468 alias = C .TIME
469469 )
470- #: The ID of the condition to be applied at the start time.
471- condition_id : str | None = Field (alias = C . CONDITION_ID , default = None )
470+ #: The IDs of the conditions to be applied at the start time.
471+ condition_ids : list [ str ] = Field (default_factory = list )
472472
473473 #: :meta private:
474474 model_config = ConfigDict (populate_by_name = True , extra = "allow" )
475475
476- @field_validator ("condition_id " , mode = "before" )
476+ @field_validator ("condition_ids " , mode = "before" )
477477 @classmethod
478- def _validate_id (cls , condition_id ):
479- if pd .isna (condition_id ) or not condition_id :
480- return None
481- if not is_valid_identifier (condition_id ):
482- raise ValueError (f"Invalid ID: { condition_id } " )
483- return condition_id
478+ def _validate_ids (cls , condition_ids ):
479+ for condition_id in condition_ids :
480+ if not is_valid_identifier (condition_id ):
481+ raise ValueError (f"Invalid ID: { condition_id } " )
482+ return condition_ids
484483
485484
486485class Experiment (BaseModel ):
@@ -531,12 +530,20 @@ def from_df(cls, df: pd.DataFrame) -> ExperimentTable:
531530
532531 experiments = []
533532 for experiment_id , cur_exp_df in df .groupby (C .EXPERIMENT_ID ):
534- periods = [
535- ExperimentPeriod (
536- time = row [C .TIME ], condition_id = row [C .CONDITION_ID ]
533+ periods = []
534+ for timepoint in cur_exp_df [C .TIME ].unique ():
535+ condition_ids = [
536+ cid
537+ for cid in cur_exp_df .loc [
538+ cur_exp_df [C .TIME ] == timepoint , C .CONDITION_ID
539+ ]
540+ if not pd .isna (cid )
541+ ]
542+ periods .append (
543+ ExperimentPeriod (
544+ time = timepoint , condition_ids = condition_ids
545+ )
537546 )
538- for _ , row in cur_exp_df .iterrows ()
539- ]
540547 experiments .append (Experiment (id = experiment_id , periods = periods ))
541548
542549 return cls (experiments = experiments )
@@ -546,10 +553,12 @@ def to_df(self) -> pd.DataFrame:
546553 records = [
547554 {
548555 C .EXPERIMENT_ID : experiment .id ,
549- ** period .model_dump (by_alias = True ),
556+ C .TIME : period .time ,
557+ C .CONDITION_ID : condition_id ,
550558 }
551559 for experiment in self .experiments
552560 for period in experiment .periods
561+ for condition_id in period .condition_ids or ["" ]
553562 ]
554563 return (
555564 pd .DataFrame (records )
0 commit comments