@@ -104,14 +104,23 @@ def petab_files_1to2(yaml_config: Path | str, output_dir: Path | str):
104104 # sub-problems
105105 for problem_config in new_yaml_config .problems :
106106 # copy files that don't need conversion
107- # (models, observables, visualizations)
107+ # (models, visualizations)
108108 for file in chain (
109- problem_config .observable_files ,
110109 (model .location for model in problem_config .model_files .values ()),
111110 problem_config .visualization_files ,
112111 ):
113112 _copy_file (get_src_path (file ), Path (get_dest_path (file )))
114113
114+ # Update observable table
115+ for observable_file in problem_config .observable_files :
116+ observable_df = v1 .get_observable_df (get_src_path (observable_file ))
117+ observable_df = v1v2_observable_df (
118+ observable_df ,
119+ )
120+ v2 .write_observable_df (
121+ observable_df , get_dest_path (observable_file )
122+ )
123+
115124 # Update condition table
116125 for condition_file in problem_config .condition_files :
117126 condition_df = v1 .get_condition_df (get_src_path (condition_file ))
@@ -339,3 +348,48 @@ def v1v2_condition_df(
339348 )
340349
341350 return condition_df
351+
352+
353+ def v1v2_observable_df (observable_df : pd .DataFrame ) -> pd .DataFrame :
354+ """Convert observable table from petab v1 to v2.
355+
356+ Perform all updates that can be done solely on the observable table:
357+ * drop observableTransformation, update noiseDistribution
358+ """
359+ df = observable_df .copy ().reset_index ()
360+
361+ # drop observableTransformation, update noiseDistribution
362+ # if there is no observableTransformation, no need to update
363+ if v1 .C .OBSERVABLE_TRANSFORMATION in df .columns :
364+ df [v1 .C .OBSERVABLE_TRANSFORMATION ] = df [
365+ v1 .C .OBSERVABLE_TRANSFORMATION
366+ ].fillna (v1 .C .LIN )
367+
368+ if v1 .C .NOISE_DISTRIBUTION in df :
369+ df [v1 .C .NOISE_DISTRIBUTION ] = df [v1 .C .NOISE_DISTRIBUTION ].fillna (
370+ v1 .C .NORMAL
371+ )
372+ else :
373+ df [v1 .C .NOISE_DISTRIBUTION ] = v1 .C .NORMAL
374+
375+ # merge observableTransformation into noiseDistribution
376+ def update_noise_dist (row ):
377+ dist = row .get (v1 .C .NOISE_DISTRIBUTION )
378+ trans = row .get (v1 .C .OBSERVABLE_TRANSFORMATION )
379+
380+ if trans == v1 .C .LIN :
381+ new_dist = dist
382+ else :
383+ new_dist = f"{ trans } -{ dist } "
384+
385+ if new_dist not in v2 .C .NOISE_DISTRIBUTIONS :
386+ raise NotImplementedError (
387+ f"Noise distribution `{ new_dist } ' for "
388+ f"observable `{ row [v1 .C .OBSERVABLE_ID ]} '"
389+ f" is not supported in PEtab v2."
390+ )
391+
392+ df [v2 .C .NOISE_DISTRIBUTION ] = df .apply (update_noise_dist , axis = 1 )
393+ df .drop (columns = [v1 .C .OBSERVABLE_TRANSFORMATION ], inplace = True )
394+
395+ return df
0 commit comments