Refactor workflow_image_generation and move to service class

This commit is contained in:
Urban Rotnik 2019-01-07 15:55:45 +01:00
parent 686f10cbd0
commit 47cc6a9d10
4 changed files with 103 additions and 116 deletions

View file

@ -221,123 +221,8 @@ class Experiment < ApplicationRecord
true
end
# This method generate the workflow image and saves it as
# experiment attachment
def generate_workflow_img
require 'graphviz'
graph = GraphViz.new(:G,
type: :digraph,
use: :neato)
graph[:size] = '4,4'
graph.node[color: Constants::COLOR_ALTO,
style: :filled,
fontcolor: Constants::COLOR_EMPEROR,
shape: 'circle',
fontname: 'Arial',
fontsize: '16.0']
graph.edge[color: Constants::COLOR_ALTO]
label = ''
subg = {}
# Draw orphan modules
my_modules.without_group.each do |my_module|
graph
.subgraph(rank: 'same')
.add_nodes("Orphan-#{my_module.id}",
label: label,
pos: "#{my_module.x / 10},-#{my_module.y / 10}!")
end
# Draw grouped modules
if my_module_groups.many?
my_module_groups.each_with_index do |group, gindex|
subgraph_name = "cluster-#{gindex}"
subg[subgraph_name] = graph.subgraph(rank: 'same')
group.ordered_modules.each_with_index do |my_module, index|
if my_module.outputs.any?
parent = subg[subgraph_name]
.add_nodes("#{subgraph_name}-#{index}",
label: label,
pos: "#{my_module.x / 10},-#{my_module.y / 10}!")
my_module.outputs.each_with_index do |output, i|
child_mod = MyModule.find_by_id(output.input_id)
child_node = subg[subgraph_name]
.add_nodes("#{subgraph_name}-O#{child_mod.id}-#{i}",
label: label,
pos: "#{child_mod.x / 10},-#{child_mod.y / 10}!")
subg[subgraph_name].add_edges(parent, child_node)
end
elsif my_module.inputs.any?
parent = subg[subgraph_name]
.add_nodes("#{subgraph_name}-#{index}",
label: label,
pos: "#{my_module.x / 10},-#{my_module.y / 10}!")
my_module.inputs.each_with_index do |input, i|
child_mod = MyModule.find_by_id(input.output_id)
child_node = subg[subgraph_name]
.add_nodes("#{subgraph_name}-I#{child_mod.id}-#{i}",
label: label,
pos: "#{child_mod.x / 10},-#{child_mod.y / 10}!")
subg[subgraph_name].add_edges(child_node, parent)
end
end
end
end
else
my_module_groups.each do |group|
group.ordered_modules.each_with_index do |my_module, index|
if my_module.outputs.any?
parent = graph.add_nodes("N-#{index}",
label: label,
pos: "#{my_module.x / 10},-#{ my_module.y / 10}!")
my_module.outputs.each_with_index do |output, i|
child_mod = MyModule.find_by_id(output.input_id)
child_node = graph
.add_nodes("N-O#{child_mod.id}-#{i}",
label: label,
pos: "#{child_mod.x / 10},-#{child_mod.y / 10}!")
graph.add_edges(parent, child_node)
end
elsif my_module.inputs.any?
parent = graph.add_nodes("N-#{index}",
label: label,
pos: "#{my_module.x / 10},-#{my_module.y / 10}!")
my_module.inputs.each_with_index do |input, i|
child_mod = MyModule.find_by_id(input.output_id)
child_node = graph
.add_nodes("N-I#{child_mod.id}-#{i}",
label: label,
pos: "#{child_mod.x / 10},-#{child_mod.y / 10}!")
graph.add_edges(child_node, parent)
end
end
end
end
end
file_location = Tempfile.open(['wimg', '.png'],
Rails.root.join('tmp'))
graph.output(png: file_location.path)
begin
file = File.open(file_location)
self.workflowimg = file
file.close
save
touch(:workflowimg_updated_at)
rescue => ex
logger.error ex.message
end
WorkflowImageGenerator.execute(experiment_id: id)
end
# Clone this experiment to given project

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
module ExecutableService
def execute(*args)
new(*args).execute
end
end

View file

@ -0,0 +1,89 @@
# frozen_string_literal: true
class WorkflowImageGenerator
extend ExecutableService
require 'graphviz'
attr_reader :errors
def initialize(experiment_id:)
@exp = Experiment.find experiment_id
@graph = GraphViz.new(:G, type: :digraph, use: :neato)
@graph[:size] = '4,4'
@graph.node[color: Constants::COLOR_ALTO,
style: :filled,
fontcolor: Constants::COLOR_EMPEROR,
shape: 'circle',
fontname: 'Arial',
fontsize: '16.0']
@graph.edge[color: Constants::COLOR_ALTO]
@errors = []
end
def execute
draw_diagram
save_file
self
end
def succeed?
@errors.none?
end
private
def draw_diagram
# Draw orphan nodes
@exp.my_modules.without_group.each do |my_module|
@graph.subgraph(rank: 'same').add_nodes(
"Orphan-#{my_module.id}",
label: '',
pos: "#{my_module.x / 10},-#{my_module.y / 10}!"
)
end
# Draw grouped modules
subg = {}
@exp.my_module_groups.each_with_index do |group, gindex|
subgraph_id = "cluster-#{gindex}"
subg[subgraph_id] = @graph.subgraph(rank: 'same')
nodes = {}
group.my_modules.workflow_ordered.each_with_index do |my_module, index|
# draw nodes
node = subg[subgraph_id].add_nodes(
"#{subgraph_id}-#{index}",
label: '',
pos: "#{my_module.x / 10},-#{my_module.y / 10}!"
)
nodes[my_module.id] = node
end
# draw edges
group.my_modules.workflow_ordered.each do |m|
m.outputs.each do |output|
parent_node = nodes[m.id]
child_node = nodes[output.input_id]
subg[subgraph_id].add_edges(parent_node, child_node)
end
end
end
end
def save_file
t_file = Tempfile.open(%w(wimg .png), Rails.root.join('tmp'))
@graph.output(png: t_file.path)
begin
file = File.open(t_file)
@exp.workflowimg = file
file.close
@exp.save
@exp.touch(:workflowimg_updated_at)
rescue StandardError => ex
logger.error ex.message
end
end
end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
require 'rails_helper'
describe WorkflowImageGenerator do
end