Support PEtab SciML problems and enable linting#482
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #482 +/- ##
==========================================
- Coverage 75.29% 75.21% -0.08%
==========================================
Files 62 64 +2
Lines 6946 6755 -191
Branches 1229 1153 -76
==========================================
- Hits 5230 5081 -149
+ Misses 1245 1218 -27
+ Partials 471 456 -15 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
dilpath
left a comment
There was a problem hiding this comment.
Thanks! Overall it would be good to try to separate as much of the SciML things into separate files or subdirectory if possible. This will help later on when we design a nicer extension interface for libpetab-python, I think. It will also help with maintenance immediately.
| return sum(p.estimate for p in self.parameters) | ||
|
|
||
|
|
||
| class Hybridization(BaseModel): |
There was a problem hiding this comment.
Move SciML-specific things to a separate file or subdirectory e.g. sciml/core.py and import them here? Just for organization; might help to keep SciML things as separate as possible. e.g. do not import petab_sciml here, rather only in the separated file.
Nevermind this if it will lead to circular imports etc.
There was a problem hiding this comment.
I've split out the sciml specific classes and introduced petab/v2/base.py to resolve circular imports. Let me know what you think.
There is still a fair amount of sciml related code left in petab/v2/core.py because the sciml fields have been added to the Problem class. We could consider an inheritance pattern in the future i.e.
class SciMLProblem(Problem):
...
IMO that would be worth considering if/when we want to support another PEtab extension that requires more fields in Problem.
There was a problem hiding this comment.
Thanks a lot, that was very helpful. And I agree, no need to fully implement now.
| config: ProblemConfig = None, | ||
| ): | ||
| from ..v2.lint import default_validation_tasks | ||
| from ..v2.lint import default_validation_tasks, sciml_validation_tasks |
There was a problem hiding this comment.
Also this, import from ..v2.sciml.lint for example, for separation.
| for mapping in problem.mappings: | ||
| # petabEntityId is not referenced in any model | ||
| for model in problem.models: | ||
| if model.has_entity_with_id(mapping.petab_id): | ||
| messages.append( | ||
| f"`{mapping.petab_id}` is used in the mapping " | ||
| "table and referenced directly in the model " | ||
| f"`{model.model_id}`." | ||
| ) |
There was a problem hiding this comment.
The spec currently says that the petabEntityId can be the same as a modelEntityId, hence the petabEntityIds can appear in the model, right? @dweindl what do you think?
The petabEntityId may be the same as the modelEntityId, but it must not be used to alias an entity that already has a valid PEtab identifier. This restriction is to avoid unnecessary complexity in the PEtab problem files.
There was a problem hiding this comment.
There is some discussion of this here PEtab-dev/PEtab#669
There was a problem hiding this comment.
I added another clause to the conditional here and below to allow the case where petabEntityId == modelEntityId. Please double check that I've understood the nuance correctly.
| # Add petab ids from mapping table if they are used for aliasing | ||
| for mapping in problem.mappings: | ||
| if mapping.model_id and mapping.model_id in parameter_ids.keys(): | ||
| if mapping.petab_id not in invalid: | ||
| parameter_ids[mapping.petab_id] = None | ||
| # An aliased model id is not a valid parameter id | ||
| if mapping.model_id and mapping.model_id in parameter_ids: | ||
| del parameter_ids[mapping.model_id] |
There was a problem hiding this comment.
As above, I think it's OK to map a model ID to a PEtab ID in the mapping table as long as it's not an alias, i.e. only in the special case where petabEntityId == modelEntityId. I think the reason for this in the spec is for support use of the mapping table for annotation, i.e. via additional user-defined annotation columns.
dilpath
left a comment
There was a problem hiding this comment.
Thanks very much! I would be happy to get @dweindl 's approval before merging, since it touches his v2 code a bit.
Currently I don't think CheckHybridizationTable is properly tested, but fine for now since it's just a placeholder before we implement all SciML checks.
| @property | ||
| def hybridizations(self) -> list[Hybridization]: | ||
| """List of hybridizations in the hybridization table(s).""" | ||
| return list( | ||
| chain.from_iterable( | ||
| ht.hybridizations for ht in self.hybridization_tables | ||
| ) | ||
| ) | ||
|
|
||
| @property | ||
| def hybridization_df(self) -> pd.DataFrame | None: | ||
| """Combined SciML hybridization tables as DataFrame.""" | ||
| return ( | ||
| HybridizationTable(hybridizations).to_df() | ||
| if (hybridizations := self.hybridizations) | ||
| else None | ||
| ) | ||
|
|
||
| @hybridization_df.setter | ||
| def hybridization_df(self, value: pd.DataFrame): | ||
| self.hybridization_tables = [HybridizationTable.from_df(value)] |
There was a problem hiding this comment.
Add some "Specific to PEtab SciML." comment to all docstrings of methods that are implemented in core PEtab?
Co-authored-by: Dilan Pathirana <59329744+dilpath@users.noreply.github.com>
WIP