Skip to content

Conversation

@dweindl
Copy link
Member

@dweindl dweindl commented Jul 21, 2025

PEtab allows spreading conditions/observables/measurements/... across multiple tables. So far, the different tables of a certain type are merged when creating a Problem. This is convenient for simulation, but pretty inconvenient when loading/modifying/saving the problem, where one usually wants to maintain the old structure.

This replaces Problem.${type}_table: ${type}Table by Problem.${type}_tables: list[${type}Table] table and introduces a Problem.${type} property that combines them on demand.

Closes #404.

PEtab allows spreading conditions/observables/measurements/... across multiple tables. So far, the different tables of a certain type are merged when creating a `Problem`. This is convenient for simulation, but pretty inconvenient when loading/modifying/saving the problem, where one usually wants to maintain the old structure.

This replaces `Problem.${type}_table: ${type}Table` by `Problem.${type}_tables: list[${type}Table]` table and introduces a `Problem.${type}` property that combines them on demand.

Closes PEtab-dev#404.
@dweindl dweindl self-assigned this Jul 21, 2025
@codecov-commenter
Copy link

codecov-commenter commented Jul 21, 2025

Codecov Report

Attention: Patch coverage is 60.13514% with 59 lines in your changes missing coverage. Please review.

Project coverage is 73.86%. Comparing base (153f2bd) to head (7bc254d).

Files with missing lines Patch % Lines
petab/v2/problem.py 52.42% 40 Missing and 9 partials ⚠️
petab/v2/lint.py 73.68% 8 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #405      +/-   ##
==========================================
- Coverage   74.18%   73.86%   -0.32%     
==========================================
  Files          62       62              
  Lines        6794     6835      +41     
  Branches     1184     1199      +15     
==========================================
+ Hits         5040     5049       +9     
- Misses       1306     1328      +22     
- Partials      448      458      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dweindl dweindl marked this pull request as ready for review July 21, 2025 07:58
@dweindl dweindl requested a review from a team as a code owner July 21, 2025 07:58
Copy link
Member

@dilpath dilpath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good 👍

I am not sure about the naming of e.g. problem.conditions. Since it's read-only, a getter method, e.g. problem.get_conditions() seems more appropriate, so users are less likely to make the mistake of trying to set condition values with the output from problem.conditions. This might be a problem for older users especially, who are used to a single table.

def experiment_df(self) -> pd.DataFrame | None:
"""Experiment table as DataFrame."""
return self.experiment_table.to_df() if self.experiment_table else None
experiments = self.experiments
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use self.experiments directly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That requires building the list twice. Can be changed to an assignment expression, though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, nevermind then!

Comment on lines +931 to +932
If there are more than one condition tables, the condition
is added to the last one.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc mapping table?

Comment on lines 953 to 955
if not self.mapping_tables:
self.mapping_tables.append(core.MappingTable(mappings=[]))
self.mapping_tables[-1].mappings.append(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As self.add_mapping? But model_id is required there.

@dweindl
Copy link
Member Author

dweindl commented Jul 21, 2025

I am not sure about the naming of e.g. problem.conditions. Since it's read-only, a getter method, e.g. problem.get_conditions() seems more appropriate, so users are less likely to make the mistake of trying to set condition values with the output from problem.conditions. This might be a problem for older users especially, who are used to a single table.

I find that unnecessarily verbose. I think, Python users should not be too surprised about any read-only properties. Any decent IDE with static type-checking will flag such a mistake.

@dilpath
Copy link
Member

dilpath commented Jul 21, 2025

Python users should not be too surprised about any read-only properties. Any decent IDE with static type-checking will flag such a mistake.

A user might take the dataframe and start editing it without realizing that it doesn't edit the actual problem. e.g. problem.condition_df.loc[...] = 2 doesn't cause an issue? Or is this also flagged by the static type checker? Old code by users might have this kind of thing already, which might make migration confusing.

@dweindl
Copy link
Member Author

dweindl commented Jul 21, 2025

A user might take the dataframe and start editing it without realizing that it doesn't edit the actual problem. e.g. problem.conditions.loc[...] = 2 doesn't cause an issue? Or is this also flagged by the static type checker?

Do you mean Problem.conditions -> list[Condition] or Problem.condition_df -> pandas.DataFrame?

I'd be fine with removing the latter completely...

@dilpath
Copy link
Member

dilpath commented Jul 21, 2025

Do you mean Problem.conditions -> list[Condition] or Problem.condition_df -> pandas.DataFrame?

I'd be fine with removing the latter completely...

Sorry, makes sense now, I edited my last comment. Yes, Problem.condition_df would be confusing for old users IMO. The new Problem.conditions can be used to edit individual conditions so is intuitive like that 👍

@dweindl dweindl merged commit fb36efa into PEtab-dev:main Jul 21, 2025
6 checks passed
@dweindl dweindl deleted the feature_separate_tables branch July 21, 2025 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v2: Don't merge tables when creating Problem

3 participants