report_html 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/make_table.rb +127 -0
- data/bin/report_html +84 -0
- data/bin/setup +8 -0
- data/js/canvasXpress.css +2181 -0
- data/js/canvasXpress.js +55 -0
- data/js/canvasXpress.min.js +448 -0
- data/js/canvasXpress_license +11 -0
- data/lib/report_html.rb +6 -0
- data/lib/report_html/report_html.rb +561 -0
- data/lib/report_html/version.rb +3 -0
- data/report_html.gemspec +36 -0
- metadata +96 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
CanvasXpress - JavaScript Canvas Library Copyright (c) 2009-2015 Isaac Neuhaus imnphd@gmail.com
|
2
|
+
|
3
|
+
Redistributions of the source code must retain this copyright notice and the following disclaimer.
|
4
|
+
|
5
|
+
CanvasXpress is licensed under the terms of the Open Source GPL version 3.0 license.
|
6
|
+
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
8
|
+
|
9
|
+
Please see a copy of the GNU General Public License at http://www.gnu.org/licenses.
|
10
|
+
|
11
|
+
Commercial use may be granted to the extent that this source code does NOT become part of any other Open Source or Commercially licensed development library or toolkit without explicit permission.
|
data/lib/report_html.rb
ADDED
@@ -0,0 +1,561 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'json'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
JS_FOLDER = File.expand_path(File.join(__FILE__, '..', '..', '..', 'js'))
|
7
|
+
|
8
|
+
class Report_html
|
9
|
+
def initialize(hash_vars, title = "report", data_from_files = false)
|
10
|
+
@all_report = ""
|
11
|
+
@title = title
|
12
|
+
@hash_vars = hash_vars
|
13
|
+
@data_from_files = data_from_files
|
14
|
+
@plots_data = []
|
15
|
+
@count_objects = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def build(template)
|
19
|
+
renderered_template = ERB.new(template).result(binding)
|
20
|
+
@all_report = "<HTML>\n"
|
21
|
+
make_head
|
22
|
+
build_body do
|
23
|
+
renderered_template
|
24
|
+
end
|
25
|
+
@all_report << "\n</HTML>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_body
|
29
|
+
@all_report << "<body onload=\"initPage();\">\n#{yield}\n</body>\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def make_head
|
33
|
+
@all_report << "\t<title>#{@title}</title>
|
34
|
+
<head>
|
35
|
+
<meta http-equiv=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE\">
|
36
|
+
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
|
37
|
+
<meta http-equiv=\"Content-Language\" content=\"en-us\" />
|
38
|
+
|
39
|
+
<link rel=\"stylesheet\" href=\"js/canvasXpress.css\" type=\"text/css\"/>
|
40
|
+
<script type=\"text/javascript\" src=\"js/canvasXpress.min.js\"></script>
|
41
|
+
<script>
|
42
|
+
var initPage = function () {
|
43
|
+
<% @plots_data.each do |plot_data| %>
|
44
|
+
<%= plot_data %>
|
45
|
+
<% end %>
|
46
|
+
}
|
47
|
+
</script>
|
48
|
+
</head>\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_report #return all html string
|
52
|
+
renderer = ERB.new(@all_report)
|
53
|
+
return renderer.result(binding) #binding does accesible all the current ruby enviroment to erb
|
54
|
+
end
|
55
|
+
|
56
|
+
def write(file)
|
57
|
+
dir = File.dirname(file)
|
58
|
+
string_report = get_report
|
59
|
+
FileUtils.cp_r(JS_FOLDER, dir)
|
60
|
+
File.open(file, 'w'){|f| f.puts string_report}
|
61
|
+
end
|
62
|
+
|
63
|
+
# REPORT SYNTAX METHODS
|
64
|
+
###################################################################################
|
65
|
+
|
66
|
+
# DATA MANIPULATION METHODS
|
67
|
+
#-------------------------------------------------------------------------------------
|
68
|
+
def get_data(options)
|
69
|
+
data = []
|
70
|
+
data = extract_data(options)
|
71
|
+
if !data.empty?
|
72
|
+
if @data_from_files # If data on container is loaded using html_report as lib, we don't care about data format
|
73
|
+
# if data comes from files and is loaded as strings. We need to format correctly the data.
|
74
|
+
rows = data.length
|
75
|
+
cols = data.first.length
|
76
|
+
if !options[:text]
|
77
|
+
rows.times do |r|
|
78
|
+
cols.times do |c|
|
79
|
+
next if r == 0 && options[:header]
|
80
|
+
next if c == 0 && options[:row_names]
|
81
|
+
data[r][c] = data[r][c].to_f
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
add_header_row_names(data, options)
|
87
|
+
data = data.transpose if options[:transpose]
|
88
|
+
end
|
89
|
+
return data
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_header_row_names(data, options)
|
93
|
+
if options[:add_header_row_names] # This check if html object needs a default header/row_names or not
|
94
|
+
if !options[:header]
|
95
|
+
range = 0..(data.first.length - 1)
|
96
|
+
data.unshift(range.to_a)
|
97
|
+
end
|
98
|
+
if !options[:row_names]
|
99
|
+
data.each_with_index do |row, i|
|
100
|
+
row.unshift(i)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def extract_data(options)
|
107
|
+
data = []
|
108
|
+
ids = options[:id]
|
109
|
+
fields = options[:fields]
|
110
|
+
ids = ids.split(',') if ids.class == String && ids.include?(',') # String syntax
|
111
|
+
if ids.class == Array
|
112
|
+
fields = fields.split(';').map{|data_fields| data_fields.split(',').map{|fields| fields.to_i} } if fields.class == String # String syntax
|
113
|
+
ids.each_with_index do |id, n|
|
114
|
+
data_file = extract_fields(id, fields[n])
|
115
|
+
if data.empty?
|
116
|
+
data.concat(data_file)
|
117
|
+
else
|
118
|
+
data.each_with_index do |row, n|
|
119
|
+
data[n] = row + data_file[n]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
else
|
124
|
+
fields = fields.first if fields.class == Array
|
125
|
+
data = extract_fields(ids, options[:fields])
|
126
|
+
end
|
127
|
+
return data
|
128
|
+
end
|
129
|
+
|
130
|
+
def extract_fields(id, fields)
|
131
|
+
data = []
|
132
|
+
@hash_vars[id].each do |row|
|
133
|
+
if fields.empty?
|
134
|
+
data << row.dup # Dup generates a array copy that avoids to modify original objects on data manipulation creating graphs
|
135
|
+
else
|
136
|
+
data << fields.map{|field| row[field]} #Map without bang do the same than dup
|
137
|
+
end
|
138
|
+
end
|
139
|
+
return data
|
140
|
+
end
|
141
|
+
|
142
|
+
# TABLE METHODS
|
143
|
+
#-------------------------------------------------------------------------------------
|
144
|
+
def table(user_options = {}, &block)
|
145
|
+
options = {
|
146
|
+
id: nil,
|
147
|
+
header: false,
|
148
|
+
row_names: false,
|
149
|
+
add_header_row_names: false,
|
150
|
+
transpose: false,
|
151
|
+
fields: [],
|
152
|
+
border: 1,
|
153
|
+
cell_align: [],
|
154
|
+
attrib: {}
|
155
|
+
}
|
156
|
+
options.merge!(user_options)
|
157
|
+
table_attr = prepare_table_attribs(options[:attrib])
|
158
|
+
array_data = get_data(options)
|
159
|
+
block.call(array_data) if !block.nil?
|
160
|
+
rowspan, colspan = get_col_n_row_span(array_data)
|
161
|
+
html = "
|
162
|
+
<table border=\"#{options[:border]}\" #{table_attr}>
|
163
|
+
<% array_data.each_with_index do |row, i| %>
|
164
|
+
<tr>
|
165
|
+
<% row.each_with_index do |cell, j|
|
166
|
+
if cell != 'colspan' && cell != 'rowspan'
|
167
|
+
if i == 0 && options[:header] %>
|
168
|
+
<th <%= get_span(colspan, rowspan, i, j) %>><%= cell %></th>
|
169
|
+
<% else %>
|
170
|
+
<td <%= get_cell_align(options[:cell_align], j) %> <%= get_span(colspan, rowspan, i, j) %>><%= cell %></td>
|
171
|
+
<% end
|
172
|
+
end %>
|
173
|
+
<% end %>
|
174
|
+
</tr>
|
175
|
+
<% end %>
|
176
|
+
</table>
|
177
|
+
"
|
178
|
+
return ERB.new(html).result(binding)
|
179
|
+
end
|
180
|
+
|
181
|
+
def get_span(colspan, rowspan, row, col)
|
182
|
+
span = []
|
183
|
+
colspan_value = colspan[row][col]
|
184
|
+
rowspan_value = rowspan[row][col]
|
185
|
+
if colspan_value > 1
|
186
|
+
span << "colspan=\"#{colspan_value}\""
|
187
|
+
end
|
188
|
+
if rowspan_value > 1
|
189
|
+
span << "rowspan=\"#{rowspan_value}\""
|
190
|
+
end
|
191
|
+
return span.join(' ')
|
192
|
+
end
|
193
|
+
|
194
|
+
def get_col_n_row_span(table)
|
195
|
+
colspan = []
|
196
|
+
rowspan = []
|
197
|
+
last_row = 0
|
198
|
+
table.each_with_index do |row, r|
|
199
|
+
rowspan << Array.new(row.length, 1)
|
200
|
+
colspan << Array.new(row.length, 1)
|
201
|
+
last_col = 0
|
202
|
+
row.each_with_index do |col, c|
|
203
|
+
if col == 'colspan'
|
204
|
+
colspan[r][last_col] += 1
|
205
|
+
else
|
206
|
+
last_col = c
|
207
|
+
end
|
208
|
+
if col == 'rowspan'
|
209
|
+
rowspan[last_row][c] += 1
|
210
|
+
else
|
211
|
+
last_row = r
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
return rowspan, colspan
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
def get_cell_align(align_vector, position)
|
220
|
+
cell_align = ''
|
221
|
+
if !align_vector.empty?
|
222
|
+
align = align_vector[position]
|
223
|
+
cell_align = "align=\"#{align}\""
|
224
|
+
end
|
225
|
+
return cell_align
|
226
|
+
end
|
227
|
+
|
228
|
+
def prepare_table_attribs(attribs)
|
229
|
+
attribs_string = ''
|
230
|
+
if !attribs.empty?
|
231
|
+
attribs.each do |attrib, value|
|
232
|
+
attribs_string << "#{attrib}= \"#{value}\" "
|
233
|
+
end
|
234
|
+
end
|
235
|
+
return attribs_string
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
# CANVASXPRESS METHODS
|
240
|
+
#-------------------------------------------------------------------------------------
|
241
|
+
def add_sample_attributes(data_structure, options)
|
242
|
+
parsed_sample_attributes = {}
|
243
|
+
options[:sample_attributes].each do |key, col|
|
244
|
+
data = get_data({id: options[:id], fields: [col], text: true})
|
245
|
+
data.shift if options[:header]
|
246
|
+
parsed_sample_attributes[key] = data.flatten
|
247
|
+
end
|
248
|
+
data_structure['x'] = parsed_sample_attributes
|
249
|
+
end
|
250
|
+
|
251
|
+
def tree_from_file(file)
|
252
|
+
string_tree = File.open(file).read.gsub("\n", '')
|
253
|
+
return string_tree
|
254
|
+
end
|
255
|
+
|
256
|
+
def set_tree(options, config)
|
257
|
+
tree = tree_from_file(options[:tree])
|
258
|
+
if options[:treeBy] == 's'
|
259
|
+
config['smpDendrogramNewick'] = tree
|
260
|
+
config['samplesClustered'] = true
|
261
|
+
elsif options[:treeBy] == 'v'
|
262
|
+
config['varDendrogramNewick'] = tree
|
263
|
+
config['variablesClustered'] = true
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def canvasXpress_main(user_options, block = nil)
|
268
|
+
# Handle arguments
|
269
|
+
#------------------------------------------
|
270
|
+
options = {
|
271
|
+
id: nil,
|
272
|
+
fields: [],
|
273
|
+
data_format: 'one_axis',
|
274
|
+
responsive: true,
|
275
|
+
height: '600px',
|
276
|
+
width: '600px',
|
277
|
+
header: false,
|
278
|
+
row_names: false,
|
279
|
+
add_header_row_names: true,
|
280
|
+
transpose: true,
|
281
|
+
x_label: 'x_axis',
|
282
|
+
title: 'Title',
|
283
|
+
sample_attributes: {},
|
284
|
+
config: {},
|
285
|
+
after_render: [],
|
286
|
+
treeBy: 's'
|
287
|
+
}
|
288
|
+
options.merge!(user_options)
|
289
|
+
config = {
|
290
|
+
'toolbarPermanent' => true,
|
291
|
+
'xAxisTitle' => options[:x_label],
|
292
|
+
'title' => options[:title]
|
293
|
+
}
|
294
|
+
if !options[:tree].nil?
|
295
|
+
set_tree(options, config)
|
296
|
+
end
|
297
|
+
config.merge!(options[:config])
|
298
|
+
# Data manipulation
|
299
|
+
#------------------------------------------
|
300
|
+
no_data_string = ERB.new("<div width=\"#{options[:width]}\" height=\"#{options[:height]}\" > <p>NO DATA<p></div>").result(binding)
|
301
|
+
data_array = get_data(options)
|
302
|
+
return no_data_string if data_array.empty?
|
303
|
+
block.call(data_array) if !block.nil?
|
304
|
+
object_id = "obj_#{@count_objects}_"
|
305
|
+
raise("ID #{options[:id]} has not data") if data_array.nil?
|
306
|
+
row_length = data_array.first.length
|
307
|
+
samples = data_array.shift[1..row_length]
|
308
|
+
return no_data_string if data_array.empty?
|
309
|
+
vars = []
|
310
|
+
data_array.each do |row|
|
311
|
+
vars << row.shift
|
312
|
+
end
|
313
|
+
values = data_array
|
314
|
+
|
315
|
+
yield(options, config, samples, vars, values, object_id)
|
316
|
+
# Build JSON objects and Javascript code
|
317
|
+
#-----------------------------------------------
|
318
|
+
@count_objects += 1
|
319
|
+
data_structure = {
|
320
|
+
'y' => {
|
321
|
+
'vars' => vars,
|
322
|
+
'smps' => samples,
|
323
|
+
'data' => values
|
324
|
+
}
|
325
|
+
}
|
326
|
+
events = false
|
327
|
+
info = false
|
328
|
+
afterRender = options[:after_render]
|
329
|
+
if options[:mod_data_structure] == 'boxplot'
|
330
|
+
data_structure['y']['smps'] = nil
|
331
|
+
data_structure.merge!({ 'x' => {'Factor' => samples}})
|
332
|
+
elsif options[:mod_data_structure] == 'circular'
|
333
|
+
data_structure.merge!({ 'z' => {'Ring' => options[:ring_assignation]}})
|
334
|
+
end
|
335
|
+
add_sample_attributes(data_structure, options) if !options[:sample_attributes].empty?
|
336
|
+
extracode = "#{options[:extracode]}\n"
|
337
|
+
extracode << "C#{object_id}.groupSamples(#{options[:group_samples]})\n" if !options[:group_samples].nil?
|
338
|
+
plot_data = "
|
339
|
+
var data = #{data_structure.to_json};
|
340
|
+
var conf = #{config.to_json};
|
341
|
+
var events = #{events.to_json};
|
342
|
+
var info = #{info.to_json};
|
343
|
+
var afterRender = #{afterRender.to_json};
|
344
|
+
var C#{object_id} = new CanvasXpress(\"#{object_id}\", data, conf, events, info, afterRender);\n#{extracode}"
|
345
|
+
@plots_data << plot_data
|
346
|
+
|
347
|
+
responsive = ''
|
348
|
+
responsive = "responsive='true'" if options[:responsive]
|
349
|
+
html = "<canvas id=\"#{object_id}\" width=\"#{options[:width]}\" height=\"#{options[:height]}\" aspectRatio='1:1' #{responsive}></canvas>"
|
350
|
+
return ERB.new(html).result(binding)
|
351
|
+
end
|
352
|
+
|
353
|
+
def line(user_options = {}, &block)
|
354
|
+
default_options = {
|
355
|
+
row_names: true
|
356
|
+
}.merge!(user_options)
|
357
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
358
|
+
config['graphType'] = 'Line'
|
359
|
+
end
|
360
|
+
return html_string
|
361
|
+
end
|
362
|
+
|
363
|
+
def stacked(user_options = {}, &block)
|
364
|
+
default_options = {
|
365
|
+
row_names: true,
|
366
|
+
}.merge!(user_options)
|
367
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
368
|
+
config['graphType'] = 'Stacked'
|
369
|
+
end
|
370
|
+
return html_string
|
371
|
+
end
|
372
|
+
|
373
|
+
def barplot(user_options = {}, &block)
|
374
|
+
default_options = {
|
375
|
+
row_names: true
|
376
|
+
}.merge!(user_options)
|
377
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
378
|
+
config['graphType'] = 'Bar'
|
379
|
+
end
|
380
|
+
return html_string
|
381
|
+
end
|
382
|
+
|
383
|
+
def heatmap(user_options = {}, &block)
|
384
|
+
default_options = {
|
385
|
+
row_names: true
|
386
|
+
}.merge!(user_options)
|
387
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
388
|
+
config['graphType'] = 'Heatmap'
|
389
|
+
end
|
390
|
+
return html_string
|
391
|
+
end
|
392
|
+
|
393
|
+
def boxplot(user_options = {}, &block)
|
394
|
+
default_options = {
|
395
|
+
row_names: true,
|
396
|
+
header: true
|
397
|
+
}.merge!(user_options)
|
398
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
399
|
+
config['graphType'] = 'Boxplot'
|
400
|
+
options[:mod_data_structure] = 'boxplot'
|
401
|
+
if options[:extracode].nil?
|
402
|
+
options[:extracode] = "C#{object_id}.groupSamples([\"Factor\"]);"
|
403
|
+
end
|
404
|
+
end
|
405
|
+
return html_string
|
406
|
+
end
|
407
|
+
|
408
|
+
def pie(user_options = {}, &block)
|
409
|
+
default_options = {
|
410
|
+
transpose: false
|
411
|
+
}.merge!(user_options)
|
412
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
413
|
+
config['graphType'] = 'Pie'
|
414
|
+
if samples.length > 1
|
415
|
+
config['showPieGrid'] = true
|
416
|
+
config['xAxis'] = samples
|
417
|
+
config['layout'] = "#{(samples.length.to_f/2).ceil}X2" if config['layout'].nil?
|
418
|
+
config['showPieSampleLabel'] = true if config['showPieSampleLabel'].nil?
|
419
|
+
end
|
420
|
+
end
|
421
|
+
return html_string
|
422
|
+
end
|
423
|
+
|
424
|
+
def sccater2D(user_options = {}, &block)
|
425
|
+
default_options = {
|
426
|
+
row_names: false,
|
427
|
+
transpose: false
|
428
|
+
}.merge!(user_options)
|
429
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
430
|
+
config['graphType'] = 'Scatter2D'
|
431
|
+
config['xAxis'] = [samples.first] if config['xAxis'].nil?
|
432
|
+
config['yAxis'] = samples[1..samples.length-1] if config['yAxis'].nil?
|
433
|
+
if default_options[:y_label].nil?
|
434
|
+
config['yAxisTitle'] = 'y_axis'
|
435
|
+
else
|
436
|
+
config['yAxisTitle'] = default_options[:y_label]
|
437
|
+
end
|
438
|
+
if options[:regressionLine]
|
439
|
+
options[:extracode] = "C#{object_id}.addRegressionLine();"
|
440
|
+
end
|
441
|
+
end
|
442
|
+
return html_string
|
443
|
+
end
|
444
|
+
|
445
|
+
def scatterbubble2D(user_options = {}, &block)
|
446
|
+
default_options = {
|
447
|
+
row_names: true,
|
448
|
+
transpose: false
|
449
|
+
}.merge!(user_options)
|
450
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
451
|
+
config['graphType'] = 'ScatterBubble2D'
|
452
|
+
if options[:xAxis].nil?
|
453
|
+
config['xAxis'] = [samples[0]]
|
454
|
+
else
|
455
|
+
config['xAxis'] = options[:xAxis]
|
456
|
+
end
|
457
|
+
if options[:yAxis].nil?
|
458
|
+
config['yAxis'] = [samples[1]]
|
459
|
+
else
|
460
|
+
config['yAxis'] = options[:yAxis]
|
461
|
+
end
|
462
|
+
if options[:zAxis].nil?
|
463
|
+
config['zAxis'] = [samples[2]]
|
464
|
+
else
|
465
|
+
config['zAxis'] = options[:zAxis]
|
466
|
+
end
|
467
|
+
if default_options[:y_label].nil?
|
468
|
+
config['yAxisTitle'] = 'y_axis'
|
469
|
+
else
|
470
|
+
config['yAxisTitle'] = default_options[:y_label]
|
471
|
+
end
|
472
|
+
if default_options[:z_label].nil?
|
473
|
+
config['zAxisTitle'] = 'z_axis'
|
474
|
+
else
|
475
|
+
config['zAxisTitle'] = default_options[:z_label]
|
476
|
+
end
|
477
|
+
if !options[:upper_limit].nil? && !options[:lower_limit].nil? && !options[:ranges].nil?
|
478
|
+
diff = (options[:upper_limit] - options[:lower_limit]).to_f/options[:ranges]
|
479
|
+
sizes = Array.new(options[:ranges]) {|index| options[:lower_limit] + index * diff}
|
480
|
+
config['sizes'] = sizes
|
481
|
+
end
|
482
|
+
end
|
483
|
+
return html_string
|
484
|
+
end
|
485
|
+
|
486
|
+
def circular(user_options = {}, &block)
|
487
|
+
default_options = {
|
488
|
+
ring_assignation: [],
|
489
|
+
ringsType: [],
|
490
|
+
ringsWeight: []
|
491
|
+
}.merge!(user_options)
|
492
|
+
html_string = canvasXpress_main(default_options, block) do |options, config, samples, vars, values, object_id|
|
493
|
+
options[:mod_data_structure] = 'circular'
|
494
|
+
config['graphType'] = 'Circular'
|
495
|
+
config['segregateVariablesBy'] = ['Ring']
|
496
|
+
if default_options[:ringsType].empty?
|
497
|
+
config['ringsType'] = Array.new(vars.length, 'heatmap')
|
498
|
+
else
|
499
|
+
config['ringsType'] = default_options[:ringsType]
|
500
|
+
end
|
501
|
+
if default_options[:ringsWeight].empty?
|
502
|
+
size = 100/vars.length
|
503
|
+
config['ringsWeight'] = Array.new(vars.length, size)
|
504
|
+
else
|
505
|
+
config['ringsWeight'] = default_options[:ringsWeight]
|
506
|
+
end
|
507
|
+
if default_options[:ring_assignation].empty?
|
508
|
+
options[:ring_assignation] = Array.new(vars.length) {|index| (index + 1).to_s}
|
509
|
+
else
|
510
|
+
options[:ring_assignation] = default_options[:ring_assignation].map{|item| item.to_s}
|
511
|
+
end
|
512
|
+
if !default_options[:links].nil?
|
513
|
+
if !@hash_vars[default_options[:links]].nil? && !@hash_vars[default_options[:links]].empty?
|
514
|
+
link_data = get_data({id: default_options[:links], fields: [], add_header_row_names: false, text: true, transpose: false})
|
515
|
+
config['connections'] = assign_rgb(link_data)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
return html_string
|
520
|
+
end
|
521
|
+
|
522
|
+
def assign_rgb(link_data)
|
523
|
+
colors = {
|
524
|
+
'red' => [255, 0, 0],
|
525
|
+
'green' => [0, 255, 0],
|
526
|
+
'black' => [0, 0, 0],
|
527
|
+
'yellow' => [255, 255, 0],
|
528
|
+
'blue' => [0, 0, 255],
|
529
|
+
'gray' => [128, 128, 128],
|
530
|
+
'orange' => [255, 165, 0],
|
531
|
+
'cyan' => [0, 255, 255],
|
532
|
+
'magenta' => [255, 0, 255]
|
533
|
+
}
|
534
|
+
link_data.each do |link|
|
535
|
+
code = colors[link[0]]
|
536
|
+
if !code.nil?
|
537
|
+
link[0] = "rgb(#{code.join(',')})"
|
538
|
+
else
|
539
|
+
raise "Color link #{link} is not allowed. The allowed color names are: #{colors.keys.join(' ')}"
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
# EMBED FILES
|
545
|
+
###################################################################################
|
546
|
+
|
547
|
+
def embed_img(img_file, img_attribs = nil)
|
548
|
+
img_content = File.open(img_file).read
|
549
|
+
img_base64 = Base64.encode64(img_content)
|
550
|
+
format = File.basename(img_file).split('.').last
|
551
|
+
img_string = "<img #{img_attribs} src=\"data:image/#{format};base64,#{img_base64}\">"
|
552
|
+
return img_string
|
553
|
+
end
|
554
|
+
|
555
|
+
def embed_pdf(pdf_file, pdf_attribs = nil)
|
556
|
+
pdf_content = File.open(pdf_file).read
|
557
|
+
pdf_base64 = Base64.encode64(pdf_content)
|
558
|
+
pdf_string = "<embed #{pdf_attribs} src=\"data:application/pdf;base64,#{pdf_base64}\" type=\"application/pdf\"></embed>"
|
559
|
+
return pdf_string
|
560
|
+
end
|
561
|
+
end
|