SED-ML / sed-ml

Simulation Experiment Description Markup Language (SED-ML)
http://sed-ml.org
5 stars 2 forks source link

Add ListOfChanges to SubTask to support changes on all subtasks #128

Closed matthiaskoenig closed 3 years ago

matthiaskoenig commented 3 years ago

Currently it is impossible to apply changes to individual SubTasks. Moving the ListOfChanges to the SubTask would allow to cover much more use cases. Most of my simulation experiments I run in research require multiple SubTasks on which I have to set changes individually. This would make things much more intuitive and more powerful. This is the main bottleneck for using SED-ML in all my workflows.

I.e.

RepeatedTask
- ListOfRanges
  - Range[0]
  - Range[1]
  - ....
- ListOfSubTasks  
  - SubTask1
    - ListOfChanges
      - SetValue[0]
      - ...
  - SubTask2
    - ListOfChanges
      - SetValue[0]
      - ...

The common use case for this are timecourses consisting of multiple subsimulations (subtasks). I.e.

Often one requiers different changes on subtasks. This is completely backwards compatible. In L1V3 the ListOfChanges is applied on the first SubTask so only the storage of the information would change. At the same time many additional use cases would be possible.

matthiaskoenig commented 3 years ago

Here an example simulation experiment consisting of multiple subtasks with changes applied on all the subtasks. This are ~80% of the simulations I am running and None of them can be encoded in SED-ML easily. Here multiple infusions of GIP and/or GLP-1 are given. The complete simulation is one concatenated timecourse, with changes applied at the beginning of every timecourse (subtask).

image

    def simulations(self) -> Dict[str, TimecourseSim]:
        Q_ = self.Q_
        sims = {}
        bodyweight = Q_(70, "kg")
        ri_gip = Q_(1.5, "pmol/min/kg") * bodyweight * self.Mr.gip
        ri_glp1 = Q_(0.33, "pmol/min/kg") * bodyweight * self.Mr.glp1

        changes_bolus = {
            "saline": {},
            "gip": {"Ri_gip": ri_gip},
            "glp1": {"Ri_glp1": ri_glp1},
        }
        for key_bolus in changes_bolus:
            sims[key_bolus] = TimecourseSim(
                [
                    self.presimulation_timecourse(),
                    Timecourse(start=0, end=60, steps=1800, changes={
                        **self.default_init_conditions(),
                        "glc_clamp": Q_(1.0, "dimensionless"),
                        "glc_clamp_value": Q_(5.0, "mM"),
                    }),
                    Timecourse(
                        start=0, end=30, steps=60, changes=changes_bolus[key_bolus]
                    ),
                    Timecourse(
                        start=0, end=30, steps=60, changes={
                            "Ri_gip": Q_(0, "mg/min"),
                            "Ri_glp1": Q_(0, "mg/min"),
                        }
                    ),
                    Timecourse(start=0, end=30, steps=60, changes={
                        "glc_clamp": Q_(1.0, "dimensionless"),
                        "glc_clamp_value": Q_(6.0, "mM"),
                    }),
                    Timecourse(
                        start=0, end=30, steps=60, changes=changes_bolus[key_bolus]
                    ),
                    Timecourse(
                        start=0, end=30, steps=60, changes={
                            "Ri_gip": Q_(0, "mg/min"),
                            "Ri_glp1": Q_(0, "mg/min"),
                        }
                    ),
                    Timecourse(start=0, end=30, steps=60, changes={
                        "glc_clamp": Q_(1.0, "dimensionless"),
                        "glc_clamp_value": Q_(7.0, "mM"),
                    }),
                    Timecourse(
                        start=0, end=30, steps=60, changes=changes_bolus[key_bolus]
                    ),
                    Timecourse(
                        start=0, end=30, steps=60, changes={
                            "Ri_gip": Q_(0, "mg/min"),
                            "Ri_glp1": Q_(0, "mg/min"),
                        }
                    ),
                ],
                reset=True,
                time_offset=-30,
            )

        return sims
luciansmith commented 3 years ago

Adding a ListOfChanges to SubTask was approved at the last SED-ML Editor's Meeting (https://docs.google.com/document/d/1PgZ9bVZHhUYzxKcpZROmx4qaNDpYdyvRJpVBktOJdKA/edit) but removing it from the RepeatedTask itself was not. (Doing so would probably break backwards compatibility, so it's probably for the best, even though it makes things Even More Complicated.) Updating the issue accordingly.

luciansmith commented 3 years ago

Added to SubTask:

"It may contain a child ListOfChanges to specify any changes that apply at the beginning of the particular subtask, in contrast to the ListOfChanges child of the RepeatedTask itself, which specifies changes that apply before any of the subtasks"

and later:

listOfChanges The SetValue children of the ListOfChanges of this SubTask define changes to apply to the model state before this SubTask is carried out. This allows model changes between individual SubTask elements, perhaps based on the changed state of the model itself. The set of all SetValue children of the first SubTask are applied after the set of SetValue children of the RepeatedTask itself.