reaction_graphs.pl 6.33 KB
Newer Older
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
1 2 3
:- module(
  reaction_graphs,
  [
4
    % Commands
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
5
    reaction_graph/0,
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
6
    import_reactions_from_graph/0,
7 8 9
    draw_reactions/0,
    % Public API
    reaction_graph/1
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
10 11 12
  ]
).

MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
13

MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
14 15
:- devdoc('\\section{Commands}').

FAGES Francois's avatar
FAGES Francois committed
16 17 18 19 20
:- devcom('FF: It would be nice to have a notion of input/output and draw graphs accordingly, with inputs on top and outputs bottom in all (reaction or influence) graphs. 

The input species could be those present at initial_state. The output species could be those not reactant (nor catalyst) of any reaction, nor source of any nfluence.

Alternatively we could have input/output annotations on molecular species. It could be useful also for some analyses.').
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
21

MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
22 23
reaction_graph :-
  biocham_command,
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
24
  doc('Builds the reaction graph of the current model.'),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
25
  delete_items([kind: graph, key: reaction_graph]),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
26 27
  new_graph,
  set_graph_name(reaction_graph),
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
  get_current_graph(GraphId),
  reaction_graph(GraphId).


import_reactions_from_graph :-
  biocham_command,
  doc('
    Updates the set of reactions of the current model with the current graph.
  '),
  make_bipartite_graph,
  make_reactions.


draw_reactions :-
  biocham_command,
  doc('
    Draws the reaction graph of the current model.
    Equivalent to \\texttt{reaction_graph. draw_graph.}
    \\begin{example}
  '),
  biocham_silent(clear_model),
  biocham(load(library:examples/mapk/mapk)),
  biocham(draw_reactions),
  doc('
    \\end{example}
  '),
  reaction_graph,
  draw_graph.


:- devdoc('\\section{Public API}').


reaction_graph(GraphId) :-
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
62 63 64 65 66 67 68
  set_counter(reaction, 0),
  \+ (
    item([kind: reaction, item: Item]),
    reaction(Item, Kinetics, Reactants, Products, Reversible),
    \+ (
      count(reaction, ReactionCount),
      format(atom(ReactionCounter), 'reaction~d', [ReactionCount]),
69
      transition(GraphId, [ReactionCounter]),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
70
      (
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
71
        Reversible = true
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
72
      ->
73
        set_attribute(GraphId, [ReactionCounter], reversible = Reversible)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
74 75 76 77 78 79 80 81
      ;
        true
      ),
      (
        Kinetics = 'MA'(1)
      ->
        true
      ;
82
        set_attribute(GraphId, [ReactionCounter], kinetics = Kinetics)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
83 84 85
      ),
      \+ (
        (
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
86
          member(Stoichiometry * Object, Reactants),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
87 88 89
          From = Object,
          To = ReactionCounter
        ;
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
90
          member(Stoichiometry * Object, Products),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
91 92 93 94
          From = ReactionCounter,
          To = Object
        ),
        \+ (
95 96
          place(GraphId, Object),
          add_edge(GraphId, From -> To, EdgeId),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
97
          (
98
            get_attribute(EdgeId, stoichiometry = OldStoichiometry)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
99
          ->
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
100
            NewStoichiometry is OldStoichiometry + Stoichiometry
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
101
          ;
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
102
            NewStoichiometry is Stoichiometry
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
103 104
          ),
          (
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
105
            NewStoichiometry = 1
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
106 107
          ->
            catch(
108
              delete_attribute(EdgeId, stoichiometry),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
109 110 111 112
              error(unknown_item),
              true
            )
          ;
113
            set_attribute(EdgeId, stoichiometry = NewStoichiometry)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
114 115 116 117 118 119 120
          )
        )
      )
    )
  ).


121 122 123
:- devdoc('\\section{Private predicates}').


MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
:- dynamic(vertex_transition/1).


:- dynamic(vertex_place/1).


:- dynamic(fixpoint/0).


make_bipartite_graph :-
  get_current_graph(GraphId),
  retractall(vertex_transition(_)),
  retractall(vertex_place(_)),
  retractall(vertex_unknown(_)),
  \+ (
    item([parent: GraphId, kind: vertex, id: VertexId, item: Vertex]),
140
    get_attribute(VertexId, kind = Kind),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
    \+ (
      (
        Kind = place
      ->
        assertz(vertex_place(Vertex))
      ;
        Kind = transition
      ->
        assertz(vertex_transition(Vertex))
      ;
        true
      )
    )
  ),
  \+ \+ (
    repeat,
    assertz(fixpoint),
    \+ (
      item([parent: GraphId, kind: edge, item: (A -> B)]),
      \+ (
        reaction_object(A, B),
        object_reaction(A, B),
        reaction_object(B, A),
        object_reaction(B, A)
      )
    ),
    fixpoint
  ),
  check_bipartite_graph.


check_bipartite_graph :-
  get_current_graph(GraphId),
  findall(
    AmbiguousVertex,
    (
      vertex_transition(AmbiguousVertex),
      vertex_place(AmbiguousVertex)
    ),
    AmbiguousVertices
  ),
  (
    AmbiguousVertices = []
  ->
    true
  ;
    throw(error(ambiguous_vertices(AmbiguousVertices)))
  ),
  findall(
    AmbiguousEdge,
    (
      item([parent: GraphId, kind: edge, item: AmbiguousEdge]),
      AmbiguousEdge = (From -> _To),
      \+ vertex_transition(From),
      \+ vertex_place(From)
    ),
    AmbiguousEdges
  ),
  (
    AmbiguousEdges = []
  ->
    true
  ;
    throw(error(ambiguous_edges(AmbiguousEdges)))
  ).


reaction_object(A, B) :-
  (
    vertex_transition(A),
    \+ vertex_place(B)
  ->
    assertz(vertex_place(B)),
    retractall(fixpoint)
  ;
    true
  ).


object_reaction(A, B) :-
  (
    vertex_place(A),
    \+ vertex_transition(B)
  ->
    assertz(vertex_transition(B)),
    retractall(fixpoint)
  ;
    true
  ).


make_reactions :-
  delete_items([kind: reaction]),
  get_current_graph(GraphId),
  \+ (
    vertex_transition(Reaction),
    \+ (
238 239
      get_kinetics(GraphId, Reaction, Kinetics),
      get_reversible(GraphId, Reaction, Reversible),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
240
      findall(
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
241
        Stoichiometry * Reactant,
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
242 243 244 245 246 247 248 249
        (
          vertex_place(Reactant),
          item([
            parent: GraphId,
            kind: edge,
            item: (Reactant -> Reaction),
            id: EdgeId
          ]),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
250
          get_stoichiometry(EdgeId, Stoichiometry)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
251 252 253 254
        ),
        Left
      ),
      findall(
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
255
        Stoichiometry * Product,
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
256 257 258 259 260 261 262 263
        (
          vertex_place(Product),
          item([
            parent: GraphId,
            kind: edge,
            item: (Reaction -> Product),
            id: EdgeId
          ]),
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
264
          get_stoichiometry(EdgeId, Stoichiometry)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
265 266 267 268 269 270 271 272
        ),
        Right
      ),
      add_reaction(Kinetics, Left, Right, Reversible)
    )
  ).


273
get_kinetics(GraphId, Vertex, Kinetics) :-
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
274
  (
275
    get_attribute(GraphId, Vertex, kinetics = Kinetics)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
276 277 278 279 280 281 282
  ->
    true
  ;
    Kinetics = 'MA'(1)
  ).


283
get_reversible(GraphId, Vertex, Reversible) :-
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
284
  (
285
    get_attribute(GraphId, Vertex, reversible = Reversible)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
286 287 288
  ->
    (
      (
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
289
        Reversible = true
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
290
      ;
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
291
        Reversible = false
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
292 293 294 295
      )
    ->
      true
    ;
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
296
      throw(error(reversible_attribute_boolean))
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
297 298
    )
  ;
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
299
    Reversible = false
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
300 301 302
  ).


303
get_stoichiometry(EdgeId, Stoichiometry) :-
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
304
  (
305
    get_attribute(EdgeId, stoichiometry = Stoichiometry)
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
306 307 308
  ->
    true
  ;
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
309
    Stoichiometry = 1
MARTINEZ Thierry 's avatar
MARTINEZ Thierry committed
310
  ).