Commit 5c2ec4e5 authored by MARTINEZ Thierry 's avatar MARTINEZ Thierry

More robust graph API

parent 1f4edde9
:- module(
graph_editor,
[
% Grammars
edge/1,
edgeref/1,
% Commands
new_graph/0,
delete_graph/1,
set_graph_name/1,
......@@ -8,9 +12,7 @@
select_graph/1,
add_vertex/1,
delete_vertex/1,
edge/1,
add_edge/1,
edgeref/1,
delete_edge/1,
list_edges/0,
list_isolated_vertices/0,
......@@ -22,21 +24,51 @@
list_attributes/1,
place/1,
transition/1,
% Public API
new_graph/1,
set_graph_name/2,
get_current_graph/1,
set_current_graph/1,
get_graph_name/2,
get_attribute/2
get_attribute/2,
get_attribute/3,
set_attribute/3,
place/2,
transition/2,
kind/3,
add_vertex/3,
add_edge/3
]
).
:- devdoc('\\section{Grammars}').
:- grammar(edge).
edge(From -> To) :-
name(From),
name(To).
:- grammar(edgeref).
edgeref(Edge) :-
edge(Edge).
:- devdoc('\\section{Commands}').
new_graph :-
biocham_command,
doc('Creates a new graph.'),
add_item([kind: graph, key: new_graph, id: Id]),
new_graph(Id),
set_current_graph(Id).
......@@ -52,7 +84,7 @@ set_graph_name(Name) :-
type(Name, name),
doc('Sets the name of the current graph.'),
get_current_graph(Id),
replace_item(Id, graph, Name, Name).
set_graph_name(Id, Name).
list_graphs :-
......@@ -73,10 +105,11 @@ add_vertex(NameList) :-
biocham_command(*),
type(NameList, '*'(name)),
doc('Adds new vertices to the current graph.'),
get_current_graph(GraphId),
\+ (
member(Name, NameList),
\+ (
add_vertex(Name, _VertexId)
add_vertex(GraphId, Name, _VertexId)
)
).
......@@ -94,14 +127,6 @@ delete_vertex(NameList) :-
).
:- grammar(edge).
edge(From -> To) :-
name(From),
name(To).
add_edge(EdgeList) :-
biocham_command(*),
type(EdgeList, '*'(edge)),
......@@ -109,21 +134,15 @@ add_edge(EdgeList) :-
Adds the given set of edges to the current graph.
The vertices are added if needed.
'),
get_current_graph(GraphId),
\+ (
member(Edge, EdgeList),
\+ (
add_edge(Edge, _EdgeId)
add_edge(GraphId, Edge, _EdgeId)
)
).
:- grammar(edgeref).
edgeref(Edge) :-
edge(Edge).
delete_edge(EdgeRefList) :-
biocham_command(*),
type(EdgeRefList, '*'(edgeref)),
......@@ -186,6 +205,33 @@ attribute(Name) :-
name(Name).
set_attribute(Id, Attribute) :-
integer(Id),
!,
(
Attribute = Key: _Value
->
true
;
Key = Attribute
),
(
item(
[parent: Id, kind: attribute, key: Key, item: Item, id: AttributeId]
)
->
(
Item = Attribute
->
true
;
replace_item(AttributeId, attribute, Key, Attribute)
)
;
add_item([parent: Id, kind: attribute, key: Key, item: Attribute])
).
set_attribute(GraphObjectSet, Attribute) :-
biocham_command,
type(GraphObjectSet, {graph_object}),
......@@ -194,34 +240,8 @@ set_attribute(GraphObjectSet, Attribute) :-
Adds an attribute to every vertex or edge in the given set.
The vertices and the edges are added if needed.
'),
\+ (
member(GraphObject, GraphObjectSet),
\+ (
add_graph_object(GraphObject, Id),
(
Attribute = Key: _Value
->
true
;
Key = Attribute
),
(
item(
[parent: Id, kind: attribute, key: Key, item: Item, id: AttributeId]
)
->
(
Item = Attribute
->
true
;
replace_item(AttributeId, attribute, Key, Attribute)
)
;
add_item([parent: Id, kind: attribute, key: Key, item: Attribute])
)
)
).
get_current_graph(GraphId),
set_attribute(GraphId, GraphObjectSet, Attribute).
place(NameList) :-
......@@ -230,9 +250,8 @@ place(NameList) :-
doc('
Sets that the vertices \\argument{NameList} are places.
'),
add_vertex(NameList),
set_attribute(NameList, kind: place).
get_current_graph(Id),
place(Id, NameList).
transition(NameList) :-
......@@ -241,30 +260,45 @@ transition(NameList) :-
doc('
Sets that the vertices \\argument{NameList} are transitions.
'),
add_vertex(NameList),
set_attribute(NameList, kind: transition).
get_current_graph(Id),
transition(Id, NameList).
delete_attribute(Id, Attribute) :-
integer(Id),
!,
delete_item([parent: Id, kind: attribute, key: Attribute]).
delete_attribute(GraphObject, Attribute) :-
biocham_command,
type(GraphObject, graph_object),
type(Attribute, name),
doc('Removes an attribute from \\argument{GraphObject}.'),
find_graph_object(GraphObject, Id),
delete_item([parent: Id, kind: attribute, key: Attribute]).
get_current_graph(GraphId),
find_graph_object(GraphId, GraphObject, Id),
delete_attribute(Id, Attribute).
list_attributes(GraphObject) :-
biocham_command,
type(GraphObject, graph_object),
doc('List the attributes of \\argument{GraphObject}.'),
find_graph_object(GraphObject, Id),
get_current_graph(GraphId),
find_graph_object(GraphId, GraphObject, Id),
list_items([parent: Id, kind: attribute]).
:- devdoc('\\section{Public API}').
new_graph(Id) :-
add_item([kind: graph, key: new_graph, id: Id]).
set_graph_name(Id, Name) :-
replace_item(Id, graph, Name, Name).
get_current_graph(Id) :-
get_selection(current_model, current_graph, [Id]).
......@@ -290,41 +324,103 @@ get_attribute(Id, Attribute) :-
item([parent: Id, kind: attribute, key: Key, item: Attribute]).
get_attribute(GraphObject, Attribute) :-
find_graph_object(GraphObject, Id),
get_attribute(GraphId, GraphObject, Attribute) :-
get_current_graph(GraphId),
find_graph_object(GraphId, GraphObject, Id),
get_attribute(Id, Attribute).
set_attribute(GraphId, GraphObjectSet, Attribute) :-
list(GraphObjectSet),
!,
\+ (
member(GraphObject, GraphObjectSet),
\+ (
set_attribute(GraphId, GraphObject, Attribute)
)
).
set_attribute(GraphId, GraphObject, Attribute) :-
add_graph_object(GraphId, GraphObject, Id),
set_attribute(Id, Attribute).
place(GraphId, NameList) :-
kind(GraphId, NameList, place).
transition(GraphId, NameList) :-
kind(GraphId, NameList, transition).
kind(GraphId, NameList, Kind) :-
list(NameList),
!,
\+ (
member(Name, NameList),
\+ (
kind(GraphId, Name, Kind)
)
).
kind(GraphId, Name, Kind) :-
add_vertex(GraphId, Name, VertexId),
set_attribute(VertexId, kind: Kind).
add_vertex(GraphId, Name, VertexId) :-
(
item([parent: GraphId, kind: vertex, key: Name, id: VertexId])
->
true
;
add_item([parent: GraphId, kind: vertex, key: Name, id: VertexId])
).
add_edge(GraphId, Edge, EdgeId) :-
Edge = (From -> To),
add_vertex(GraphId, From, FromId),
add_vertex(GraphId, To, ToId),
(
item([parent: GraphId, kind: edge, key: Edge, id: EdgeId])
->
true
;
add_item([parent: GraphId, kind: edge, key: Edge, id: EdgeId]),
add_dependency(EdgeId, FromId),
add_dependency(EdgeId, ToId)
).
:- devdoc('\\section{Private predicates}').
find_vertex(Name, Id) :-
get_current_graph(GraphId),
find_vertex(GraphId, Name, Id) :-
find_item([parent: GraphId, kind: vertex, key: Name, id: Id]).
find_edge(Edge, Id) :-
get_current_graph(GraphId),
find_edge(GraphId, Edge, Id) :-
find_item([parent: GraphId, kind: edge, key: Edge, id: Id]).
find_graph_object(GraphObject, Id) :-
find_graph_object(GraphId, GraphObject, Id) :-
(
GraphObject = (_From->_To)
->
find_edge(GraphObject, Id)
find_edge(GraphId, GraphObject, Id)
;
find_vertex(GraphObject, Id)
find_vertex(GraphId, GraphObject, Id)
).
add_graph_object(GraphObject, Id) :-
add_graph_object(GraphId, GraphObject, Id) :-
(
GraphObject = (_From->_To)
->
add_edge(GraphObject, Id)
add_edge(GraphId, GraphObject, Id)
;
add_vertex(GraphObject, Id)
add_vertex(GraphId, GraphObject, Id)
).
......@@ -355,30 +451,3 @@ isolated_or_attributed_vertices(GraphId, VerticesId) :-
),
VerticesId
).
add_vertex(Name, VertexId) :-
get_current_graph(GraphId),
(
item([parent: GraphId, kind: vertex, key: Name, id: VertexId])
->
true
;
add_item([parent: GraphId, kind: vertex, key: Name, id: VertexId])
).
add_edge(Edge, EdgeId) :-
get_current_graph(GraphId),
Edge = (From -> To),
add_vertex(From, FromId),
add_vertex(To, ToId),
(
item([parent: GraphId, kind: edge, key: Edge, id: EdgeId])
->
true
;
add_item([parent: GraphId, kind: edge, key: Edge, id: EdgeId]),
add_dependency(EdgeId, FromId),
add_dependency(EdgeId, ToId)
).
......@@ -174,6 +174,7 @@ test('get_attribute', [true(Kind == transition)]) :-
clear_model,
new_graph,
command(transition('A')),
once(get_attribute('A', kind: Kind)).
get_current_graph(GraphId),
once(get_attribute(GraphId, 'A', kind: Kind)).
:- end_tests(graph_editor).
:- module(
graphviz,
[
% Commands
draw_graph/0,
export_graph/1,
% Public API
draw_graph/1,
export_graph/2,
set_draw_graph_driver/1
]
).
......@@ -14,8 +18,8 @@
draw_graph :-
biocham_command,
doc('Draws the current graph.'),
get_draw_graph_driver(Driver),
Driver.
get_current_graph(Id),
draw_graph(Id).
export_graph(OutputFile) :-
......@@ -28,13 +32,23 @@ export_graph(OutputFile) :-
\ttexttt{.png} or \ttexttt{.svg}
-- assuming no extension is \\texttt{.dot}.
'),
file_name_extension(_, Suffix, OutputFile),
export_graph(Suffix, OutputFile).
get_current_graph(Id),
export_graph(Id, OutputFile).
:- devdoc('\\section{Public API}').
draw_graph(Id) :-
nb_getval(draw_graph_driver, Driver),
call(Driver, Id).
export_graph(Id, OutputFile) :-
file_name_extension(_, Suffix, OutputFile),
export_graph(Suffix, Id, OutputFile).
set_draw_graph_driver(Driver) :-
nb_setval(draw_graph_driver, Driver).
......@@ -42,53 +56,46 @@ set_draw_graph_driver(Driver) :-
:- devdoc('\\section{Internal predicates}').
export_graph('', OutputFile) :-
export_graph('', Id, OutputFile) :-
!,
atom_concat(OutputFile, '.dot', FilenameDot),
export_graph('.dot', FilenameDot).
export_graph('.dot', Id, FilenameDot).
export_graph('dot', OutputFile) :-
get_current_graph(GraphId),
create_cgraph(GraphId, Graph),
export_graph('dot', Id, OutputFile) :-
!,
create_cgraph(Id, Graph),
agwrite(Graph, OutputFile),
agclose(Graph).
export_graph('pdf', OutputFile) :-
render_current_graph('pdf', OutputFile).
export_graph('eps', OutputFile) :-
render_current_graph('eps', OutputFile).
export_graph('ps', OutputFile) :-
render_current_graph('ps', OutputFile).
export_graph(Format, Id, OutputFile) :-
graphviz_format(Format),
!,
create_cgraph(Id, Graph),
gvLayout(Graph, dot),
gvRenderFilename(Graph, Format, OutputFile),
gvFreeLayout(Graph),
agclose(Graph).
export_graph('png', OutputFile) :-
render_current_graph('png', OutputFile).
export_graph('svg', OutputFile) :-
render_current_graph('svg', OutputFile).
graphviz_format('pdf').
graphviz_format('eps').
get_draw_graph_driver(Driver) :-
nb_getval(draw_graph_driver, Driver).
graphviz_format('ps').
graphviz_format('png').
render_current_graph(Format, OutputFile) :-
get_current_graph(GraphId),
create_cgraph(GraphId, Graph),
gvLayout(Graph, dot),
gvRenderFilename(Graph, Format, OutputFile),
gvFreeLayout(Graph),
agclose(Graph).
graphviz_format('svg').
create_cgraph(GraphId, Graph) :-
get_graph_name(GraphId, GraphName),
create_cgraph(Id, Graph) :-
get_graph_name(Id, GraphName),
agopen(GraphName, directed, Graph),
agattr(Graph, graph, size, '7.5,11', _),
agattr(Graph, graph, ratio, fill, _),
agattr(Graph, node, shape, ellipse, _),
\+ (
item([parent: GraphId, kind: vertex, item: VertexName, id: VertexId]),
item([parent: Id, kind: vertex, item: VertexName, id: VertexId]),
\+ (
agnode(Graph, VertexName, true, Node),
(
......@@ -101,7 +108,7 @@ create_cgraph(GraphId, Graph) :-
)
),
\+ (
item([parent: GraphId, kind: edge, item: Edge]),
item([parent: Id, kind: edge, item: Edge]),
\+ (
format(atom(EdgeName), '~w', [Edge]),
Edge = (VertexA -> VertexB),
......@@ -112,22 +119,22 @@ create_cgraph(GraphId, Graph) :-
).
graph_png :-
graph_png(Id) :-
count(graph_png, Index),
format(atom(Filename), 'graph~d.png', [Index]),
export_graph(Filename),
export_graph(Id, Filename),
view_image(Filename).
graph_svg :-
graph_svg(Id) :-
count(graph_svg, Index),
format(atom(Filename), 'graph~d.svg', [Index]),
export_graph(Filename),
export_graph(Id, Filename),
view_image(Filename).
graph_pdf :-
graph_pdf(Id) :-
count(graph_pdf, Index),
format(atom(Filename), 'graph~d.pdf', [Index]),
export_graph(Filename),
export_graph(Id, Filename),
open_file(Filename).
......@@ -82,9 +82,9 @@ find_invar_aux(ForcedMax, Type, OtherType, Operator) :-
arc(A, B, C) :-
get_current_graph(GraphId),
item([parent: GraphId, item: (A -> B)]),
item([parent: GraphId, item: (A -> B), id: Id]),
(
get_attribute(A -> B, stoichiometry: C)
get_attribute(Id, stoichiometry: C)
->
true
;
......@@ -94,8 +94,8 @@ arc(A, B, C) :-
is_type(P, Type) :-
get_current_graph(GraphId),
item([parent: GraphId, item: P, kind: vertex]),
get_attribute(P, kind: Type).
item([parent: GraphId, item: P, kind: vertex, id: Id]),
get_attribute(Id, kind: Type).
is_place(P) :-
......
:- module(
reaction_graphs,
[
% Commands
reaction_graph/0,
import_reactions_from_graph/0,
draw_reactions/0
draw_reactions/0,
% Public API
reaction_graph/1
]
).
......@@ -17,6 +20,40 @@ reaction_graph :-
delete_items([kind: graph, key: reaction_graph]),
new_graph,
set_graph_name(reaction_graph),
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) :-
set_counter(reaction, 0),
\+ (
item([kind: reaction, item: Item]),
......@@ -24,11 +61,11 @@ reaction_graph :-
\+ (
count(reaction, ReactionCount),
format(atom(ReactionCounter), 'reaction~d', [ReactionCount]),
transition([ReactionCounter]),
transition(GraphId, [ReactionCounter]),
(
Reversible = true
->
set_attribute([ReactionCounter], reversible: Reversible)
set_attribute(GraphId, [ReactionCounter], reversible: Reversible)
;
true
),
......@@ -37,7 +74,7 @@ reaction_graph :-
->
true
;
set_attribute([ReactionCounter], kinetics: Kinetics)
set_attribute(GraphId, [ReactionCounter], kinetics: Kinetics)
),
\+ (
(
......@@ -50,10 +87,10 @@ reaction_graph :-
To = Object
),
\+ (
place([Object]),
add_edge([From -> To]),
place(GraphId, Object),
add_edge(GraphId, From -> To, EdgeId),
(
get_attribute((From -> To), stoichiometry: OldStoichiometry)
get_attribute(EdgeId, stoichiometry: OldStoichiometry)
->
NewStoichiometry is OldStoichiometry + Stoichiometry
;
......@@ -63,12 +100,12 @@ reaction_graph :-
NewStoichiometry = 1
->
catch(
delete_attribute([From -> To], stoichiometry),
delete_attribute(EdgeId, stoichiometry),
error(unknown_item),
true
)
;
set_attribute([From -> To], stoichiometry: NewStoichiometry)
set_attribute(EdgeId, stoichiometry: NewStoichiometry)
)
)
)
......@@ -76,32 +113,6 @@ reaction_graph :-
).
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{Private predicates}').
......@@ -219,8 +230,8 @@ make_reactions :-
\+ (
vertex_transition(Reaction),
\+ (
get_kinetics(Reaction, Kinetics),
get_reversible(Reaction, Reversible),
get_kinetics(GraphId, Reaction, Kinetics),
get_reversible(GraphId, Reaction, Reversible),
findall(
Stoichiometry * Reactant,
(
......@@ -254,9 +265,9 @@ make_reactions :-
).
get_kinetics(Vertex, Kinetics) :-
get_kinetics(GraphId, Vertex, Kinetics) :-