from cobra.core import Metabolite, Reaction, Model

model = Model('simple_model')

A = Metabolite('A')
B = Metabolite('B')
C = Metabolite('C')
D = Metabolite('D')
E = Metabolite('E')
P = Metabolite('P')

R1 = Reaction('R1')
R2 = Reaction('R2')
R3 = Reaction('R3')
R4 = Reaction('R4')
R5 = Reaction('R5')
R6 = Reaction('R6')
R7 = Reaction('R7')
R8 = Reaction('R8')
R9 = Reaction('R9')
R10 = Reaction('R10')

model.add_metabolites([A, B, C, D, E, P])
model.add_reactions([R1, R2, R3, R4, R5, R6, R7, R8, R9, R10])

model.reactions.R1.build_reaction_from_string('--> A')
model.reactions.R2.build_reaction_from_string('<--> B')
model.reactions.R3.build_reaction_from_string('P -->')
model.reactions.R4.build_reaction_from_string('E -->')
model.reactions.R5.build_reaction_from_string('A --> B')
model.reactions.R6.build_reaction_from_string('A --> C')
model.reactions.R7.build_reaction_from_string('A --> D')
model.reactions.R8.build_reaction_from_string('B <--> C')
model.reactions.R9.build_reaction_from_string('B --> P')
model.reactions.R10.build_reaction_from_string('C + D --> E + P')

"""
Explanation: Simple d3.js based flux visualizations
Here we build a simple metabolic modeling using cobra
End of explanation
"""


from d3flux import flux_map
flux_map(model, display_name_format=lambda x: str(x.id), figsize=(300,250),
         flux_dict={rxn.id: None for rxn in model.reactions})

"""
Explanation: Simple visualizations without starting positions
Without specifying locations for each metabolite and/or reaction, the map will use d3.js to display the network as  a force-directed layout.
End of explanation
"""


A.notes['map_info']['x'] = 150.
A.notes['map_info']['y'] = 50.

B.notes['map_info']['x'] = 80.
B.notes['map_info']['y'] = 130.

C.notes['map_info']['x'] = 150.
C.notes['map_info']['y'] = 130.

D.notes['map_info']['x'] = 220.
D.notes['map_info']['y'] = 130.

P.notes['map_info']['x'] = 150.
P.notes['map_info']['y'] = 200.

E.notes['map_info']['x'] = 220.
E.notes['map_info']['y'] = 200.

flux_map(model, display_name_format=lambda x: str(x.id), figsize=(300,250),
         flux_dict={rxn.id: None for rxn in model.reactions})

"""
Explanation: Nodes and reactions can be dragged into position, where they will 'stick'. Double-clicking a stuck node releases it.
The coordinates (and other visualization properties) of the nodes are saved in the 'map_info' field of the metabolite.notes dictionary.
The positions can be passed manually:
End of explanation
"""


from cobra.io import load_json_model
new_model = load_json_model('simple_model.json')
flux_map(new_model, figsize=(300,250),
         flux_dict={rxn.id: None for rxn in model.reactions})

"""
Explanation: Saving the model using the Save JSON button will include the updated map info if nodes are dragged to their desired locations
End of explanation
"""


new_model.objective = model.reactions.R4
new_model.optimize()

flux_map(new_model, figsize=(300,250))

"""
Explanation: Plotting metabolic flux results
A model with a valid solution dictionary will have the reaction arrows scaled by their corresponding flux.
End of explanation
"""


new_model.reactions.R8.knock_out()
new_model.optimize()
flux_map(new_model, figsize=(300,250))

"""
Explanation: Simulating flux knockouts
The flux_map will also show reactions which have been knocked out
End of explanation
"""


