rbbt-rest 1.6.28 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rbbt/rest/entity.rb +71 -1
  3. data/lib/rbbt/rest/entity/render.rb +3 -2
  4. data/lib/rbbt/rest/knowledge_base.rb +81 -28
  5. data/lib/rbbt/rest/main.rb +3 -0
  6. data/lib/rbbt/rest/workflow.rb +1 -1
  7. data/lib/rbbt/rest/workflow/jobs.rb +5 -4
  8. data/share/views/compass/app.sass +21 -11
  9. data/share/views/layout/footer.haml +0 -1
  10. data/share/views/layout/header.haml +9 -6
  11. data/share/views/layout/top_menu.haml +1 -0
  12. data/share/views/partials/table.haml +7 -1
  13. data/share/views/public/js/_ajax_replace.js +2 -0
  14. data/share/views/public/js/defer.js +1 -1
  15. data/share/views/public/js/helpers.js +89 -18
  16. data/share/views/public/js/rbbt.aesthetics.js +145 -34
  17. data/share/views/public/js/rbbt.basic.js +20 -0
  18. data/share/views/public/js/rbbt.entity.js +12 -2
  19. data/share/views/public/js/rbbt.entity_list.js +51 -5
  20. data/share/views/public/js/rbbt.exception.js +9 -1
  21. data/share/views/public/js/rbbt.job.js +2 -2
  22. data/share/views/public/js/rbbt.js +5 -1
  23. data/share/views/public/js/rbbt.knowledge_base.js +40 -0
  24. data/share/views/public/js/rbbt.modal.js +82 -75
  25. data/share/views/public/js/rbbt.plots.js +276 -0
  26. data/share/views/public/js/rbbt/list.js +2 -2
  27. data/share/views/public/plugins/cola/js/cola.v3.min.js +3 -0
  28. data/share/views/public/plugins/d3js/js/d3.js +9503 -0
  29. data/share/views/public/plugins/d3js/js/d3js.min.js +5 -0
  30. data/share/views/public/plugins/mithril-node-render/js/index.js +115 -0
  31. data/share/views/public/plugins/mithril/js/mithril.js +212 -77
  32. data/share/views/public/plugins/mithril/js/mithril.min.js +2 -2
  33. data/share/views/public/plugins/mithril/js/mithril.min.js.map +1 -1
  34. data/share/views/public/plugins/nvd3/css/nv.d3.css +641 -0
  35. data/share/views/public/plugins/nvd3/js/nv.d3.js +13298 -0
  36. data/share/views/public/plugins/svg-pan-zoom/js/svg-pan-zoom.js +1861 -0
  37. data/share/views/tools/nvd3.haml +16 -0
  38. data/share/views/tools/nvd3/chart.haml +55 -0
  39. data/share/views/tools/nvd3/histogram.haml +19 -0
  40. data/share/views/tools/nvd3/pie.haml +24 -0
  41. data/share/views/tools/nvd3/scatter.haml +33 -0
  42. data/share/views/wait.haml +2 -2
  43. metadata +15 -3
  44. data/share/views/public/plugins/d3js/d3js.min.js +0 -5
@@ -6,7 +6,15 @@ rbbt.exception.null = function(variable, text){
6
6
 
7
7
  rbbt.exception.report = function(err){
8
8
  console.log("Error: " + err)
9
- rbbt.modal.controller().error(err, "Application Error")
9
+ var stack = err.stack
10
+ console.log(stack)
11
+ if (rbbt.modal){
12
+ stack = "<ul><li>" + stack.replace(/\n/g, '</li><li>') + '<li/></ul>'
13
+ stack = stack.replace(/<li><li\/>/g,'').replace(/<li>(.*?)@(.*?):(\d+:\d+)<\/li>/g, '<li>$2<span style="font-weight:bold">$3</span><br/><em>$1</em></li>')
14
+ rbbt.modal.controller.error(m('.ui.error.message', [m('.header', err), m('.description', m.trust(stack))]), "Application Error")
15
+ }else{
16
+ console.log(stack)
17
+ }
10
18
  }
11
19
 
12
20
  rbbt.try = function(func){
@@ -159,9 +159,9 @@ rbbt.Job = function(workflow, task, inputs){
159
159
 
160
160
  }
161
161
 
162
- rbbt.job = function(workflow, task, inputs){
162
+ rbbt.job = function(workflow, task, inputs,json){
163
163
  var job = new rbbt.Job(workflow, task, inputs)
164
- return job.run()
164
+ return job.run(json)
165
165
  }
166
166
 
167
167
  rbbt_job = function(workflow, task, inputs, complete){
@@ -23,6 +23,10 @@ rbbt.post.asFormUrlEncoded = function(xhr){
23
23
  }
24
24
 
25
25
  rbbt.log = function(obj){
26
- console.log(obj)
26
+ console.log((new Date()).toString() + ' => ' + obj)
27
27
  }
28
28
 
29
+ rbbt.mount = function(obj, component){
30
+ obj.className = obj.className + ' mithril-mount'
31
+ m.mount(obj, component)
32
+ }
@@ -14,6 +14,46 @@ KB.parents = function(database, entity){
14
14
  return m.request({url: url, method: "GET", type: Entity})
15
15
  }
16
16
 
17
+ KB.list_parents = function(database, list){
18
+ return list.get().then(function(list_info){
19
+ var url = '/knowledge_base/user/' + database + '/collection_parents'
20
+
21
+ collection = {}
22
+ collection[list.type] = list_info.entities
23
+ url = add_parameter(url, 'collection', JSON.stringify(collection))
24
+ url = add_parameter(url, '_format', 'tsv_json')
25
+ return m.request({url: url, method: "POST"})
26
+ })
27
+ }
28
+
29
+ KB.list_children = function(database, list){
30
+ return list.get().then(function(list_info){
31
+ var url = '/knowledge_base/user/' + database + '/collection_children'
32
+
33
+ var collection = {}
34
+ collection[list.type] = list_info.entities
35
+ var data = {}
36
+ data.collection = JSON.stringify(collection)
37
+ data._format = 'tsv_json'
38
+
39
+ return rbbt.post(url, data)
40
+ })
41
+ }
42
+
43
+ KB.list_subset = function(database, list, target){
44
+ return list.get().then(function(list_info){
45
+ var url = '/knowledge_base/user/' + database + '/subset'
46
+
47
+ var data = {}
48
+ var source = list_info.entities.join(",")
49
+ data._format = 'tsv_json'
50
+ data.source = source
51
+ if (target) data.target = target.join(",")
52
+
53
+ return rbbt.post(url, data)
54
+ })
55
+ }
56
+
17
57
  Entity.prototype.children = function(database){
18
58
  return KB.children(database, this)
19
59
  }
@@ -1,90 +1,97 @@
1
- rbbt.modal = {}
2
- rbbt.modal.element = document.getElementById('modal')
3
-
4
- rbbt.modal.vm = (function(){
5
- var vm = {}
6
- vm.init = function(){
7
- console.log(m)
8
- vm.visible = m.prop(false)
9
- vm.content = m.prop("")
10
- vm.title = m.prop("")
11
- }
12
1
 
13
- return vm
14
- }())
15
-
16
- rbbt.modal.controller = function(){
17
- var controller = rbbt.modal.controller
18
- var vm = rbbt.modal.vm
19
- vm.init()
20
-
21
- controller._set = function(content, title){
22
- vm.content(content)
23
- if (undefined !== title)
24
- vm.title(title)
25
- else
26
- vm.title("")
27
- vm.visible(true)
28
- }
29
2
 
30
- controller.show = function(content, title){
31
- controller._set(content, title)
32
- $(rbbt.modal.element).addClass('active')
33
- m.redraw()
34
- update_rbbt()
35
- }
3
+ ModalComponent = function(element){
4
+ var component = {}
36
5
 
37
- controller.error = function(content, title){
38
- controller._set(content, title)
39
- $(rbbt.modal.element).addClass('active')
40
- $(rbbt.modal.element).addClass('error')
41
- m.redraw()
42
- update_rbbt()
6
+ component.vm = {
7
+ element: element,
8
+ init: function(){
9
+ this.visible = m.prop(false)
10
+ this.content = m.prop("")
11
+ this.title = m.prop("")
12
+ }
43
13
  }
44
14
 
15
+ component.controller = function(){
16
+ var ctrl = component.controller
17
+ ctrl.vm = component.vm;
18
+ ctrl.vm.init();
45
19
 
46
- controller.show_url = function(url, title){
47
- if (typeof url == 'string') params = {url: url, method: 'GET',deserialize: function(v){return v}}
48
- else params = url
49
- vm.visible(true)
50
- vm.title("loading")
51
- vm.content(m('.ui.loading.basic.segment'))
52
- $(rbbt.modal.element).addClass('loading')
53
- $(rbbt.modal.element).addClass('active')
54
- m.redraw()
55
- return rbbt.insist_request(params).then(function(content){
56
- $(rbbt.modal.element).removeClass('loading')
57
- controller.show(content, title)
58
- })
59
- }
20
+ ctrl._set = function(content, title){
21
+ this.vm.content(content)
22
+ if (undefined !== title)
23
+ this.vm.title(title)
24
+ else
25
+ this.vm.title("")
26
+ this.vm.visible(true)
27
+ }
60
28
 
61
- controller.close = function(){
62
- vm.visible(false)
63
- $(rbbt.modal.element).removeClass('error')
64
- $(rbbt.modal.element).removeClass('active')
65
- m.redraw()
66
- }
29
+ ctrl.show = function(content, title){
30
+ this._set(content, title)
31
+ $(this.vm.element).addClass('active')
32
+ m.redraw()
33
+ update_rbbt()
34
+ }
67
35
 
68
- return controller
69
- }
36
+ ctrl.error = function(content, title){
37
+ this._set(content, title)
38
+ $(this.vm.element).addClass('active')
39
+ $(this.vm.element).addClass('error')
40
+ m.redraw()
41
+ update_rbbt()
42
+ }
70
43
 
71
- rbbt.modal.view = function(controller){
72
- if (rbbt.modal.vm.visible()){
73
- var title
74
- if ('object' == typeof rbbt.modal.vm.title()) title = rbbt.modal.vm.title()
75
- else title = m.trust(rbbt.modal.vm.title())
44
+ ctrl.show_url = function(url, title){
45
+ if (typeof url == 'string') params = {url: url, method: 'GET',deserialize: function(v){return v}}
46
+ else params = url
76
47
 
77
- var content
78
- if ('object' == typeof rbbt.modal.vm.content()) content = rbbt.modal.vm.content()
79
- else content = m.trust(rbbt.modal.vm.content())
48
+ this.vm.visible(true)
49
+ this.vm.title("loading")
50
+ this.vm.content(m('.ui.loading.basic.segment'))
51
+ $(this.vm.element).addClass('loading')
52
+ $(this.vm.element).addClass('active')
53
+ m.redraw()
54
+ return rbbt.insist_request(params).then(function(content){
55
+ $(ctrl.vm.element).removeClass('loading')
56
+ ctrl.show(content, title)
57
+ })
58
+ }
80
59
 
60
+ ctrl.close = function(){
61
+ ctrl.vm.visible(false)
62
+ $(ctrl.vm.element).removeClass('error')
63
+ $(ctrl.vm.element).removeClass('active')
64
+ m.redraw()
65
+ }
81
66
 
82
- var header = [title, rbbt.mview.ibutton({onclick: rbbt.modal.controller.close, class:'small close', style: 'margin-top: -4px'}, m('i.icon.close'))]
83
- var modal_content = [m('.header', header), m('.content', content)]
84
- return modal_content
85
- }else{
86
- return ""
67
+ return ctrl
87
68
  }
69
+
70
+ component.view = function(ctrl){
71
+ if (ctrl.vm.visible()){
72
+ var title
73
+ if ('object' == typeof ctrl.vm.title()) title = ctrl.vm.title();
74
+ else title = m.trust(ctrl.vm.title());
75
+
76
+ var content
77
+ if ('object' == typeof ctrl.vm.content()) content = ctrl.vm.content();
78
+ else content = m.trust(ctrl.vm.content());
79
+
80
+
81
+ var header = [title, rbbt.mview.ibutton({onclick: ctrl.close, class:'small close', style: 'margin-top: -4px'}, m('i.icon.close'))];
82
+ var modal_content = [m('.header', header), m('.content', content)];
83
+ return modal_content;
84
+ }else{
85
+ return "";
86
+ }
87
+ }
88
+
89
+
90
+ return component;
88
91
  }
89
92
 
90
- if (rbbt.modal.element) m.module(rbbt.modal.element, rbbt.modal)
93
+ if (document.getElementById('modal')){
94
+ rbbt.modal = new ModalComponent(document.getElementById('modal'))
95
+
96
+ m.mount(document.getElementById('modal'), rbbt.modal)
97
+ }
@@ -0,0 +1,276 @@
1
+ rbbt.plots = {}
2
+
3
+ rbbt.plots.list_plot = function(list, rules, create_obj){
4
+ var component = {}
5
+ component.create_obj = create_obj
6
+
7
+ component.vm = {
8
+ list: list,
9
+ rules: rules,
10
+
11
+ node_aesthetics: m.prop(),
12
+ update_aesthetics: function(){
13
+ rbbt.log('update-aesthetics')
14
+ //return rbbt.aesthetics.get_list_aesthetics(component.vm.list,component.vm.rules)
15
+ rbbt.aesthetics.get_list_aesthetics(component.vm.list,component.vm.rules)
16
+ .then(component.vm.node_aesthetics).then(component.vm.update_nodes)
17
+ m.redraw()
18
+ },
19
+
20
+ nodes: m.prop(),
21
+ no_layout: m.prop(false),
22
+ update_nodes: function(node_aesthetics){
23
+ rbbt.log('update-nodes')
24
+ var deferred = m.deferred()
25
+
26
+ component.vm.list.get().then(function(list_info){
27
+ var aes = list_info.entities.map(function(entity, i){
28
+ var e_aes = {id: entity, index: i}
29
+ forHash(node_aesthetics, function(key, value){
30
+ e_aes[key] = value[i]
31
+ })
32
+ return e_aes
33
+ })
34
+ rbbt.log('update-nodes:done')
35
+ return aes
36
+ }).then(component.vm.nodes).then(component.vm.update_layout).then(deferred.resolve)
37
+ return deferred.promise
38
+ },
39
+
40
+ associations: m.prop(),
41
+ graph: function(){
42
+ if (undefined === component.vm.associations() || undefined === component.vm.nodes()) return {links:[],nodes:[]}
43
+ var links = rbbt.plots.association_network(component.vm.nodes(), component.vm.associations())
44
+ var graph = {links: links, nodes: component.vm.nodes()}
45
+ return(graph)
46
+ },
47
+ update_layout: function(nodes){
48
+ rbbt.log('update-layout')
49
+
50
+ if (component.vm.no_layout() || undefined === component.vm.associations()){
51
+ var deferred = m.deferred()
52
+ deferred.resolve(nodes)
53
+ return deferred.promise
54
+ }
55
+
56
+ rbbt.log('update-layout:force')
57
+
58
+ return rbbt.plots.force_layout(component.vm.graph()).then(function(graph){return graph.nodes})
59
+ },
60
+
61
+ init: function(){
62
+ rbbt.log('init')
63
+ component.vm.update_aesthetics()
64
+ },
65
+ }
66
+
67
+ component.controller = function(){
68
+ var ctrl = this
69
+ this.vm = component.vm;
70
+ this.vm.init()
71
+ this.onunload = function() {
72
+ console.log("unloading component");
73
+ }
74
+ }
75
+
76
+ component.wrapper = function(objs){
77
+ if (undefined === objs){
78
+ rbbt.log("Loading")
79
+ return m('.ui.basic.segment.plot.loading', "Loading")
80
+ }else{
81
+ rbbt.log("Wrap")
82
+ return m('.ui.basic.segment.plot', objs)
83
+ }
84
+ }
85
+
86
+ component.view = function(ctrl){
87
+ rbbt.log('View')
88
+ if (ctrl.vm.nodes()){
89
+ var objs = ctrl.vm.nodes().map(function(aes,i){
90
+ return component.create_obj(aes)
91
+ })
92
+ return component.wrapper(objs)
93
+ }else{
94
+ return component.wrapper()
95
+ }
96
+ }
97
+
98
+ return component;
99
+ }
100
+
101
+ //{{{ PLOTS
102
+
103
+
104
+ //{{{ FORCE LAYOUT
105
+
106
+ rbbt.plots.force_layout = function(graph){
107
+ var deferred = m.deferred()
108
+ m.startComputation()
109
+ rbbt.log("force-start")
110
+ var force = d3.layout.force()
111
+ .charge(-5200)
112
+ .linkDistance(5000)
113
+ .size([10000, 10000])
114
+ .nodes(graph.nodes)
115
+ .links(graph.links)
116
+ .start();
117
+
118
+ force.on("end", function() {
119
+ m.endComputation()
120
+ rbbt.log("force-end")
121
+ deferred.resolve(graph)
122
+ })
123
+ return deferred.promise
124
+ }
125
+
126
+ rbbt.plots.association_network = function(nodes, associations){
127
+ var indices = {}
128
+ for (i = 0; i < nodes.length; i++){
129
+ var entity = nodes[i]
130
+ indices[entity.id] = i
131
+ }
132
+
133
+ var edges = []
134
+ forHash(associations, function(key,value){
135
+ var source = value[0]
136
+ var target = value[1]
137
+ var source_index = indices[source]
138
+ var target_index = indices[target]
139
+ edges.push({source: source_index, target: target_index, id: key})
140
+ })
141
+
142
+ return edges
143
+ }
144
+
145
+ //{{{ BASIC RULES
146
+
147
+
148
+ rbbt.plots.basic_rules = function(study){
149
+ var rules = []
150
+ rules.push({aes:'label', property: 'link', extract: m.trust})
151
+ rules.push({aes:'description', property: 'long_name'})
152
+ rules.push({aes:'highlight', property: 'significant_in_study', args:study})
153
+ rules.push({aes:'order', property: 'damage_bias_in_study', args:study})
154
+ rules.push({aes:'color_class', workflow: 'GEO', task: 'differential', args:{threshold: 0.05, dataset: 'GSE13507', to_gene: true, main:"/Primary/", contrast: "/ontrol/"}, extract: function(result, entity){
155
+ if (undefined === result[entity]) return ""
156
+ var pvalue = result[entity][result[entity].length-1]
157
+ if (pvalue > 0 && pvalue < 0.05){
158
+ return "green"
159
+ }else{
160
+ if (pvalue < 0 && pvalue > -0.05){
161
+ return "red"
162
+ }else{
163
+ return ""
164
+ }
165
+ }
166
+ }})
167
+ rules.push({aes:'color', workflow: 'GEO', task: 'differential', mapper: 'sign-gradient', args:{threshold: 0.05, dataset: 'GSE13507', to_gene: true, main:"/Primary/", contrast: "/ontrol/"}, extract: function(result, entity){
168
+ if (undefined === result[entity]) return ""
169
+ var pvalue = result[entity][result[entity].length-1]
170
+ return pvalue_score(pvalue)
171
+ }})
172
+
173
+ return rules
174
+ }
175
+
176
+ rbbt.plots.svg_wrapper = function(objs){
177
+ if (undefined === objs){
178
+ return m(".ui.basic.segment.loading", "Loading")
179
+ }else{
180
+ var cell_svg = m('image',{"xlink:href": 'https://upload.wikimedia.org/wikipedia/commons/1/1a/Biological_cell.svg',x:0,y:0,height:100, width:100})
181
+ objs.unshift(cell_svg)
182
+ return m("svg[height='800px'][width='100%'][viewPort='0 0 10000 10000'][xmlns:xlink='http://www.w3.org/1999/xlink']",{config: svgPanZoom}, objs)
183
+ }
184
+ }
185
+
186
+ rbbt.plots.tile_obj = function(aes){
187
+ var class_names = ""
188
+
189
+ if (aes.color_class){
190
+ class_names = class_names + ' ' + aes.color_class
191
+ aes.color_class = undefined
192
+ }
193
+
194
+ var title = aes.label
195
+ if (aes.highlight)
196
+ title = [m('i.icon.star',{style:"display:inline;font-size:1em"}), title]
197
+
198
+ var content = aes.description
199
+
200
+ var header = m('.ui.header', title)
201
+ var colors = m('.ui.segment', {"style":"background-color:" + aes.color})
202
+ aes.color = undefined
203
+ var body = m('.ui.description',[content, colors])
204
+
205
+ return m('.tile.ui.segment', {style: aes, class: class_names},
206
+ [header, body]
207
+ )
208
+ }
209
+
210
+ rbbt.plots.svg_obj = function(aes){
211
+ aes.width = '300px'
212
+ aes.height = '200px'
213
+ var tile = rbbt.plots.tile_obj(aes)
214
+
215
+ var location = {x: aes.x, y: aes.y}
216
+ if (undefined === location.x) location.x = Math.random() * 1000
217
+ if (undefined === location.y) location.y = Math.random() * 1000
218
+ location.width = aes.width
219
+ location.height = aes.height
220
+ location.requiredExtensions="http://www.w3.org/1999/xhtml"
221
+ location.class="node"
222
+
223
+ return m('foreignObject', location, m('body[xmlns="http://www.w3.org/1999/xhtml"]',tile))
224
+ }
225
+
226
+ rbbt.plots.d3js_graph = function(graph, object){
227
+ var xsize = 300, ysize = 200
228
+ var width = 1200
229
+ height = 800
230
+
231
+ var color = d3.scale.category20();
232
+
233
+ var svg = d3.select(object)
234
+ .attr("width", "100%")
235
+ .attr("height", height)
236
+
237
+ var force = d3.layout.force()
238
+ .charge(-20*xsize)
239
+ .linkDistance(3*xsize)
240
+ .size([width, height])
241
+ .nodes(graph.nodes)
242
+ .links(graph.links)
243
+
244
+ force.start()
245
+ force.on("tick", function() {
246
+ link.attr("x1", function(d) { return d.source.x + xsize/2; })
247
+ .attr("y1", function(d) { return d.source.y + ysize/2; })
248
+ .attr("x2", function(d) { return d.target.x + xsize/2; })
249
+ .attr("y2", function(d) { return d.target.y + ysize/2; });
250
+
251
+ node.attr("x", function(d) { return d.x; })
252
+ .attr("y", function(d) { return d.y; });
253
+ })
254
+
255
+ var link = svg.selectAll(".link")
256
+ .data(graph.links)
257
+ .enter().append("line")
258
+ .attr("class", "link")
259
+ .style("stroke-width", function(d) { return Math.sqrt(d.value); });
260
+
261
+ var node = svg.selectAll(".node")
262
+ .data(graph.nodes)
263
+ .enter().append("foreignObject").attr('width',xsize).attr('height',ysize).call(force.drag)
264
+ .attr("class", "node")
265
+ .html(function(d) { return mrender(rbbt.plots.tile_obj(d)) });
266
+
267
+ rbbt.log("force:warmup")
268
+ for(i=0; i<100; i++) force.tick()
269
+
270
+ rbbt.log("force:panZoom")
271
+ svgPanZoom(object)
272
+ }
273
+
274
+ rbbt.mrender = function(mobj){
275
+ return render(mobj)
276
+ }