rbbt-rest 1.6.2 → 1.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rbbt/rest/common/misc.rb +10 -0
- data/lib/rbbt/rest/workflow/jobs.rb +8 -7
- data/share/views/compass/app.sass +278 -3
- data/share/views/compass/base/color.sass +66 -0
- data/share/views/compass/blocks.sass +0 -0
- data/share/views/compass/mixins/_blocks.sass +76 -80
- data/share/views/compass/mixins/_compass.sass +0 -0
- data/share/views/compass/mixins/_hide.sass +76 -1
- data/share/views/compass/table.sass +142 -0
- data/share/views/compass/variables/colors.sass +7 -0
- data/share/views/compass/variables/sizes.sass +5 -0
- data/share/views/entity_partials/action_card.haml +5 -5
- data/share/views/entity_partials/action_controller.haml +31 -33
- data/share/views/entity_partials/entity_card.haml +28 -27
- data/share/views/entity_partials/entity_list_card.haml +30 -42
- data/share/views/entity_partials/entity_map_card.haml +35 -43
- data/share/views/entity_partials/list_container.haml +6 -6
- data/share/views/layout.haml +53 -59
- data/share/views/layout/coda.haml +1 -0
- data/share/views/layout/doctype.haml +8 -0
- data/share/views/layout/footer.haml +36 -10
- data/share/views/layout/header.haml +47 -0
- data/share/views/layout/top_menu.haml +27 -13
- data/share/views/partials/form.haml +4 -4
- data/share/views/partials/table.haml +2 -1
- data/share/views/partials/table/column.haml +8 -9
- data/share/views/partials/table/files.haml +2 -2
- data/share/views/partials/table/filters.haml +16 -16
- data/share/views/partials/table/page.haml +9 -15
- data/share/views/public/js/ng-favourites.js +13 -0
- data/share/views/public/js/rbbt.aesthetics.js +51 -0
- data/share/views/public/js/rbbt.entity.js +62 -0
- data/share/views/public/js/rbbt.entity_list.js +54 -0
- data/share/views/public/js/rbbt.entity_map.js +52 -0
- data/share/views/public/js/rbbt.favourites.js +286 -0
- data/share/views/public/js/rbbt.favourites.js.old +195 -0
- data/share/views/public/js/rbbt.js +40 -0
- data/share/views/public/js/rbbt.knowledge_base.js +24 -0
- data/share/views/public/js/rbbt.page.js +32 -0
- data/share/views/public/js/rbbt/actions.js +15 -14
- data/share/views/public/js/rbbt/table.js +6 -4
- data/share/views/tools/cytoscape.haml +310 -0
- data/share/views/tools/protein_tool.haml +383 -0
- data/share/views/tools/protein_tool/controls.haml +315 -0
- metadata +23 -2
@@ -0,0 +1,383 @@
|
|
1
|
+
- position = nil unless defined? position
|
2
|
+
- sequence = protein.sequence
|
3
|
+
- jmol_id = 'Jmol-' << protein
|
4
|
+
- select_id = jmol_id + '-select'
|
5
|
+
- pdbs = protein.pdbs
|
6
|
+
- position = nil unless defined? position
|
7
|
+
- colors = %w(red blue green yellow black white purple)
|
8
|
+
|
9
|
+
- organism = protein.organism
|
10
|
+
- uni = Organism.protein_identifiers(organism).index :target => "UniProt/SwissProt Accession", :persist => true
|
11
|
+
|
12
|
+
:sass
|
13
|
+
.protein_tool > .controls
|
14
|
+
float: right
|
15
|
+
margin-bottom: -1px
|
16
|
+
.tabular.menu
|
17
|
+
width: 300px
|
18
|
+
|
19
|
+
.protein_tool.very.basic.ui.segment(id=id)
|
20
|
+
.controls
|
21
|
+
.ui.action.input
|
22
|
+
%input(placeholder='Position' type='text' name='position')
|
23
|
+
.mark.submit.ui.button Mark
|
24
|
+
.clear.submit.ui.button Clear
|
25
|
+
.align.submit.ui.button Align
|
26
|
+
.ui.tabular.menu.top.attached
|
27
|
+
.item.active(data-tab='Sequence') Sequence
|
28
|
+
.item(data-tab='JMol') JMol
|
29
|
+
.item(data-tab='COSMIC') COSMIC
|
30
|
+
.window.bottom.attached.ui.segment
|
31
|
+
.secondary_structure.active.very.basic.ui.segment.tab(data-tab='Sequence' style='background:white')
|
32
|
+
.svg(data-sequence_length='#{sequence.length}')
|
33
|
+
- log :svg, "Downloading SVG"
|
34
|
+
- begin
|
35
|
+
= protein.marked_svg([])
|
36
|
+
- rescue Exception
|
37
|
+
%p.error.ui.message
|
38
|
+
Could not download protein SVG, try again later.
|
39
|
+
%pre=$!.message
|
40
|
+
.sequence(style='width: 677px; overflow-x: auto;font-family: monospace;margin-left:123px')
|
41
|
+
%span.sequence(width="100%")= sequence
|
42
|
+
%span.marks(width="100%")
|
43
|
+
- size = sequence.length
|
44
|
+
- marks = size / 10
|
45
|
+
- str = ""
|
46
|
+
- marks.times do |mark|
|
47
|
+
- txt = "|"
|
48
|
+
- str << ("_" * (10 - txt.length)) << txt
|
49
|
+
= str
|
50
|
+
%span.counts(width="100%")
|
51
|
+
- size = sequence.length
|
52
|
+
- marks = size / 10
|
53
|
+
- str = ""
|
54
|
+
- marks.times do |mark|
|
55
|
+
- mark = (mark + 1) * 10
|
56
|
+
- txt = mark.to_s
|
57
|
+
- str << ("_" * (10 - txt.length)) << txt
|
58
|
+
= str
|
59
|
+
%p.scroll.ui.message
|
60
|
+
Scroll horizontaly across the sequence
|
61
|
+
|
62
|
+
.jmol.very.basic.ui.segment.tab(data-tab='JMol')
|
63
|
+
|
64
|
+
.ui.field
|
65
|
+
%label(for=select_id) Load a structure PDB
|
66
|
+
%select.pdb(id=select_id style='width: 200px')
|
67
|
+
%option(selected="selected") Select a PDB
|
68
|
+
- (pdbs || []).each do |pdb, info|
|
69
|
+
%option(attr-pdb="=#{pdb}")= "#{pdb}"
|
70
|
+
- uniprot = uni[protein]
|
71
|
+
|
72
|
+
- if uniprot and Structure::I3D_PROTEINS.include? uniprot
|
73
|
+
- filepos = Structure::I3D_PROTEINS.identify_field "FILENAME"
|
74
|
+
- Structure::I3D_PROTEINS[uniprot][filepos].each do |filename|
|
75
|
+
- type = filename =~ /EXP/ ? :pdb : :model
|
76
|
+
- url = "http://interactome3d.irbbarcelona.org/pdb.php?dataset=human&type1=proteins&type2=#{ type }&pdb=#{ filename }"
|
77
|
+
-# url = "http://darthcaedus:28873/" << ["Structure", "get_protein_pdb"] * "/" << "?" << Misc.hash2GET_params(:_format => :raw, :filename => filename)
|
78
|
+
%option.protein(attr-pdb=url)= "#{filename}"
|
79
|
+
|
80
|
+
- if uniprot and Structure::I3D_INTERACTIONS.include? uniprot
|
81
|
+
- filepos = Structure::I3D_INTERACTIONS.identify_field "FILENAME"
|
82
|
+
- Structure::I3D_INTERACTIONS[uniprot][filepos].each do |filename|
|
83
|
+
- type = filename =~ /EXP/ ? :pdb : :model
|
84
|
+
- url = "http://interactome3d.irbbarcelona.org/pdb.php?dataset=human&type1=interactions&type2=#{ type }&pdb=#{ filename }"
|
85
|
+
-# url = "http://darthcaedus:28873/" << ["Structure", "get_interaction_pdb"] * "/" << "?" << Misc.hash2GET_params(:_format => :raw, :filename => filename)
|
86
|
+
%option.interaction(attr-pdb=url)= "#{filename}"
|
87
|
+
.window
|
88
|
+
|
89
|
+
.COSMIC.very.basic.ui.segment.tab(data-tab='COSMIC')
|
90
|
+
= fragment do
|
91
|
+
.highlight.submit.ui.button Highlight
|
92
|
+
.ui.message
|
93
|
+
In JMol positions with 1 mutation are white, with 2 are green, with 3 are orange, and with more than 3 are red
|
94
|
+
-#%select(name='color')
|
95
|
+
- colors.each do |c|
|
96
|
+
%option(value=c)= c
|
97
|
+
|
98
|
+
|
99
|
+
- header "Genomic Mutation", "GenomicMutation", {:organism => Organism.default_code("Hsa"), :watson => false}
|
100
|
+
- filter "Primary site"
|
101
|
+
= table :table_id => "COSMIC mutations for #{ protein.name || protein }", :row_ids => :consume do
|
102
|
+
- association_items = COSMIC.knowledge_base.subset(:mutation_protein_changes, :target => [protein], :source => :all)
|
103
|
+
- associations = association_items.tsv.to_double
|
104
|
+
|
105
|
+
- log :sample_mutations
|
106
|
+
- sample_mutations = COSMIC.knowledge_base.get_database(:sample_mutations, :type => :double, :merge => true, :target => "Sample name=~Sample", :source => "Genomic Mutation")
|
107
|
+
- sample_mutations.fields = ["Sample"]
|
108
|
+
|
109
|
+
- associations = associations.attach(sample_mutations)
|
110
|
+
|
111
|
+
- log :sample_info
|
112
|
+
- sample_info = COSMIC.sample_info.find.tsv
|
113
|
+
- sample_info.key_field = "Sample"
|
114
|
+
|
115
|
+
- associations = associations.attach(sample_info)
|
116
|
+
|
117
|
+
- good_fields = associations.fields - ["Ensembl Protein ID"]
|
118
|
+
|
119
|
+
- log :slice_and_show
|
120
|
+
- associations.slice(good_fields)
|
121
|
+
|
122
|
+
:deferjs
|
123
|
+
|
124
|
+
$('.highlight.submit').click(function(){
|
125
|
+
var link = $(this);
|
126
|
+
var COSMIC = link.parents('.COSMIC').first();
|
127
|
+
var protein_tool = COSMIC.parents('.protein_tool').first();
|
128
|
+
var svg_element = protein_tool.find('.svg').first();
|
129
|
+
var jmol_element = protein_tool.find('.jmol').first();
|
130
|
+
|
131
|
+
var table = COSMIC.find('table');
|
132
|
+
var url = table.attr('attr-url');
|
133
|
+
var filter = table.attr('attr-filter');
|
134
|
+
|
135
|
+
url = add_parameter(url, '_format', 'json')
|
136
|
+
url = add_parameter(url, '_page', 'all')
|
137
|
+
url = add_parameter(url, '_column', 'Change')
|
138
|
+
if (undefined != filter){ url = add_parameter(url, '_filter', escape(filter)) }
|
139
|
+
|
140
|
+
var color = 'red'
|
141
|
+
|
142
|
+
$.ajax({
|
143
|
+
url: url,
|
144
|
+
success: function(data){
|
145
|
+
data = JSON.parse(data);
|
146
|
+
var change_positions = [];
|
147
|
+
for (mutation in data){
|
148
|
+
var change = data[mutation][0];
|
149
|
+
var samples = data[mutation][1];
|
150
|
+
if (m = change.match(/[A-Z*](\d*)[A-Z*]/)){
|
151
|
+
change_positions.push(parseInt(m[1]));
|
152
|
+
}
|
153
|
+
}
|
154
|
+
var change_counts = []
|
155
|
+
|
156
|
+
for (i in change_positions){
|
157
|
+
var position = change_positions[i]
|
158
|
+
if (change_counts[position] === undefined){
|
159
|
+
change_counts[position] = 1
|
160
|
+
}else{
|
161
|
+
change_counts[position] = change_counts[position] + 1
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
var protein_tool = $('.protein_tool#' + '#{id}');
|
166
|
+
rbbt.svg.mark_positions(svg_element, change_positions, color);
|
167
|
+
for (position in change_counts){
|
168
|
+
var jcolor = 'white';
|
169
|
+
if (change_counts[position] > 1) jcolor = 'green'
|
170
|
+
if (change_counts[position] > 2) jcolor = 'organge'
|
171
|
+
if (change_counts[position] > 3) jcolor = 'red'
|
172
|
+
|
173
|
+
rbbt.jmol.mark_position(jmol_element, position, jcolor);
|
174
|
+
}
|
175
|
+
|
176
|
+
}
|
177
|
+
})
|
178
|
+
return false;
|
179
|
+
})
|
180
|
+
|
181
|
+
:sass
|
182
|
+
.jmol:not(.active)
|
183
|
+
display: block !important
|
184
|
+
visibility: hidden
|
185
|
+
height: 0px
|
186
|
+
|
187
|
+
:deferjs
|
188
|
+
rbbt.sequence = {}
|
189
|
+
$('.tabular.menu .item').tab()
|
190
|
+
|
191
|
+
$('svg').attr('viewport-fill', 'white')
|
192
|
+
rbbt.sequence.clear = function(element){
|
193
|
+
var seq = element.find('span.sequence');
|
194
|
+
var marked_chars = seq.find('.sequence_char_position')
|
195
|
+
marked_chars.each(function(marked_char){ marked_char = $(this); marked_char.replaceWith(marked_char.html()) })
|
196
|
+
}
|
197
|
+
|
198
|
+
rbbt.sequence.mark_position = function(element, position, color){
|
199
|
+
if (undefined === color) color = 'red';
|
200
|
+
var seq = element.find('span.sequence');
|
201
|
+
var str = seq.html();
|
202
|
+
var char_pos = position - 1;
|
203
|
+
str = str.slice(0, char_pos) + $('<span class="sequence_char_position" data-sequence_position=' + position + ' style="color:' + color + '">' + str[char_pos] + '</span>')[0].outerHTML + str.slice(char_pos+1)
|
204
|
+
seq.html(str)
|
205
|
+
}
|
206
|
+
|
207
|
+
rbbt.svg = {}
|
208
|
+
|
209
|
+
rbbt.svg.clear = function(element){
|
210
|
+
var svg = element.find('svg');
|
211
|
+
var vlines = svg.find('.rbbt-vline')
|
212
|
+
vlines.remove()
|
213
|
+
var vregions = svg.find('.rbbt-region')
|
214
|
+
vregions.remove()
|
215
|
+
}
|
216
|
+
|
217
|
+
rbbt.svg.position_offset = function(element, position){
|
218
|
+
var svg = element.find('svg');
|
219
|
+
var width = parseInt(svg.attr('width'));
|
220
|
+
var start = parseInt(svg.find('rect.ac').attr('x'));
|
221
|
+
var seq_len = parseInt(element.attr('data-sequence_length'));
|
222
|
+
return start + position * (width - start)/seq_len
|
223
|
+
}
|
224
|
+
|
225
|
+
rbbt.svg.mark_position = function(element, position, color){
|
226
|
+
if (undefined === color) color = 'red';
|
227
|
+
var svg = element.find('svg');
|
228
|
+
|
229
|
+
var width = parseInt(svg.attr('width'));
|
230
|
+
var height = parseInt(svg.attr('height'));
|
231
|
+
var offset = rbbt.svg.position_offset(element, position)
|
232
|
+
|
233
|
+
var line = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
234
|
+
line.setAttributeNS(null, "x1", offset);
|
235
|
+
line.setAttributeNS(null, "y1", 5);
|
236
|
+
line.setAttributeNS(null, "x2", offset);
|
237
|
+
line.setAttributeNS(null, "y2", height - 5);
|
238
|
+
line.setAttributeNS(null, "class", 'rbbt-vline');
|
239
|
+
line.setAttributeNS(null, "style", "stroke:" + color + ";opacity:0.5;stroke-width:1;");
|
240
|
+
|
241
|
+
svg.append(line);
|
242
|
+
}
|
243
|
+
|
244
|
+
rbbt.svg.mark_positions = function(element, positions, color){
|
245
|
+
for ( i in positions){
|
246
|
+
var position = positions[i]
|
247
|
+
rbbt.svg.mark_position(element, position, color)
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
rbbt.svg.mark_region = function(element, first, last, color){
|
252
|
+
var svg = element.find('svg')
|
253
|
+
var width = parseInt(svg.attr('width'));
|
254
|
+
var height = parseInt(svg.attr('height'));
|
255
|
+
var start = parseInt(svg.find('rect.ac').attr('x'));
|
256
|
+
var seq_len = parseInt(element.attr('data-sequence_length'));
|
257
|
+
|
258
|
+
var offset_start = rbbt.svg.position_offset(element, first)
|
259
|
+
var offset_end = rbbt.svg.position_offset(element, last)
|
260
|
+
|
261
|
+
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
262
|
+
|
263
|
+
rect.setAttributeNS(null, "x", offset_start);
|
264
|
+
rect.setAttributeNS(null, "class", 'rbbt-region');
|
265
|
+
rect.setAttributeNS(null, "y", 10);
|
266
|
+
rect.setAttributeNS(null, "width", offset_end - offset_start);
|
267
|
+
rect.setAttributeNS(null, "height", height - 30);
|
268
|
+
rect.setAttributeNS(null, "style", "stroke:black;stroke-width: 2; opacity:0.3;fill:" + color + ";");
|
269
|
+
|
270
|
+
svg.append(rect);
|
271
|
+
}
|
272
|
+
|
273
|
+
rbbt.svg.mark_aligned_region = function(element, map, color){
|
274
|
+
if (undefined === color) color = 'blue'
|
275
|
+
|
276
|
+
var positions = []
|
277
|
+
for(seq_pos in map){
|
278
|
+
positions.push(parseInt(seq_pos))
|
279
|
+
}
|
280
|
+
|
281
|
+
positions = positions.sort();
|
282
|
+
console.log(positions)
|
283
|
+
var last = -1
|
284
|
+
var start = -1;
|
285
|
+
for (var i = 0; i < positions.length; i++){
|
286
|
+
if (positions[i] != last + 1){
|
287
|
+
if (start != -1) { rbbt.svg.mark_region(element, start, last, color); }
|
288
|
+
start = positions[i]
|
289
|
+
}
|
290
|
+
last = positions[i]
|
291
|
+
}
|
292
|
+
if (start != -1) { rbbt.svg.mark_region(element, start, last, color); }
|
293
|
+
}
|
294
|
+
|
295
|
+
|
296
|
+
rbbt.jmol = {}
|
297
|
+
rbbt.jmol.clear = function(element){
|
298
|
+
element.jmol_tool('clear')
|
299
|
+
}
|
300
|
+
rbbt.jmol.mark_position = function(element, position, color){
|
301
|
+
if (undefined === color) color = 'red'
|
302
|
+
element.jmol_tool('mark_position', position, color)
|
303
|
+
}
|
304
|
+
|
305
|
+
rbbt.jmol.mark_positions = function(element, positions, color){
|
306
|
+
for (i in positions){
|
307
|
+
var position = positions[i]
|
308
|
+
rbbt.jmol.mark_position(element, position, color)
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
312
|
+
require_js("/js/jmol.js", function(){
|
313
|
+
var position = #{position ? position : "undefined"}
|
314
|
+
var tool = $('.jmol').last().jmol_tool({protein:"#{ protein }", sequence: "#{protein.sequence}"});
|
315
|
+
|
316
|
+
$('select.pdb').change(function(){
|
317
|
+
var option = $(this).find('option:selected');
|
318
|
+
var pdb = option.attr('attr-pdb');
|
319
|
+
if (pdb == "Select a pdb") return false
|
320
|
+
tool.jmol_tool("load_pdb", pdb)
|
321
|
+
clean = pdb.replace(/=/,'')
|
322
|
+
tool.find('.pdb_info > dd.pdbfile').html(clean)
|
323
|
+
|
324
|
+
if (position !== undefined){
|
325
|
+
tool.jmol_tool("clear")
|
326
|
+
tool.jmol_tool("mark_position", position, 'red')
|
327
|
+
}
|
328
|
+
})
|
329
|
+
})
|
330
|
+
|
331
|
+
|
332
|
+
$('.clear.submit').click(function(){
|
333
|
+
var link = $(this);
|
334
|
+
var controls = link.parents('.controls').first();
|
335
|
+
var protein_tool = controls.parents('.protein_tool').first();
|
336
|
+
var sequence_element = protein_tool.find('.sequence').first();
|
337
|
+
var svg_element = protein_tool.find('.svg').first();
|
338
|
+
var jmol_element = protein_tool.find('.jmol').first();
|
339
|
+
|
340
|
+
rbbt.sequence.clear(sequence_element)
|
341
|
+
rbbt.svg.clear(svg_element)
|
342
|
+
rbbt.jmol.clear(jmol_element)
|
343
|
+
})
|
344
|
+
|
345
|
+
$('.mark.submit').click(function(){
|
346
|
+
var link = $(this);
|
347
|
+
var controls = link.parents('.controls').first();
|
348
|
+
var protein_tool = controls.parents('.protein_tool').first();
|
349
|
+
var sequence_element = protein_tool.find('.sequence').first();
|
350
|
+
var svg_element = protein_tool.find('.svg').first();
|
351
|
+
var jmol_element = protein_tool.find('.jmol').first();
|
352
|
+
|
353
|
+
var position = parseInt(controls.find('input[name=position]').val());
|
354
|
+
|
355
|
+
if (! position > 0) return alert("No position specified")
|
356
|
+
|
357
|
+
rbbt.sequence.clear(sequence_element)
|
358
|
+
rbbt.svg.clear(svg_element)
|
359
|
+
|
360
|
+
rbbt.sequence.mark_position(sequence_element, position)
|
361
|
+
rbbt.svg.mark_position(svg_element, position)
|
362
|
+
rbbt.jmol.mark_position(jmol_element, position)
|
363
|
+
})
|
364
|
+
|
365
|
+
|
366
|
+
$('.align.submit').click(function(){
|
367
|
+
var link = $(this);
|
368
|
+
var controls = link.parents('.controls').first();
|
369
|
+
var protein_tool = controls.parents('.protein_tool').first();
|
370
|
+
var svg_element = protein_tool.find('.svg').first();
|
371
|
+
|
372
|
+
var jmol = $('.jmol');
|
373
|
+
|
374
|
+
if(jmol.jmol_tool('is_pdb_loaded')){
|
375
|
+
var map = jmol.jmol_tool('alignment_map');
|
376
|
+
jmol.jmol_tool('mark_aligned_region', 'blue');
|
377
|
+
rbbt.svg.mark_aligned_region(svg_element, map, 'blue');
|
378
|
+
}else{
|
379
|
+
alert("Select a PDB")
|
380
|
+
}
|
381
|
+
return false;
|
382
|
+
})
|
383
|
+
|
@@ -0,0 +1,315 @@
|
|
1
|
+
- colors = %w(red blue green yellow black white purple)
|
2
|
+
|
3
|
+
.tool_menu.top.attached.tabular.ui.menu
|
4
|
+
- if user
|
5
|
+
.item(data-tab='Controls') Controls
|
6
|
+
|
7
|
+
.item(data-tab='Appris') Appris
|
8
|
+
|
9
|
+
.item(data-tab='COSMIC') COSMIC
|
10
|
+
|
11
|
+
|
12
|
+
- if user
|
13
|
+
.controls.bottom.attached.ui.tab.segment(data-tab='Controls')
|
14
|
+
= action_parameters nil, {:klass => ''}, :action => '#' do
|
15
|
+
- input :list, :select, "Genomic Mutation list", nil, :html_options => {:class => 'favourite_lists', :type => 'GenomicMutation'}
|
16
|
+
- input :color, :select, "Color to use", 'green', :select_options => colors
|
17
|
+
|
18
|
+
.appris.bottom.attached.ui.tab.segment(data-tab='Appris')
|
19
|
+
.controls.ui.form
|
20
|
+
.ui.field
|
21
|
+
%label Highlight color
|
22
|
+
%select.ui.select(name='color')
|
23
|
+
- colors.each do |c|
|
24
|
+
%option(value=c)= c
|
25
|
+
%dl
|
26
|
+
- (protein.appris_residues || []).each do |type, list|
|
27
|
+
%dt= Misc.humanize type
|
28
|
+
%dd
|
29
|
+
%ul.clean_list
|
30
|
+
- list.each do |range|
|
31
|
+
%li
|
32
|
+
%a.appris_highlight.ui.button(href="#" attr-start="#{range['start']}" attr-end="#{range['end']}") Highlight
|
33
|
+
== (#{range['start']}..#{range['end']})
|
34
|
+
|
35
|
+
:deferjs
|
36
|
+
$('a.appris_highlight, a.feature_highlight').click(function(){
|
37
|
+
var link = $(this)
|
38
|
+
var color = link.parents('dd').find('select').first().val();
|
39
|
+
var start = parseInt(link.attr('attr-start'));
|
40
|
+
var end = parseInt(link.attr('attr-end'));
|
41
|
+
|
42
|
+
var protein_tool = $(this).parents('.protein_tool').first()
|
43
|
+
|
44
|
+
if (start == end){
|
45
|
+
protein_tool.protein_tool('mark_position', start, color)
|
46
|
+
}else{
|
47
|
+
protein_tool.protein_tool('mark_region', start, end, color)
|
48
|
+
}
|
49
|
+
return false
|
50
|
+
})
|
51
|
+
|
52
|
+
.COSMIC.bottom.attached.ui.tab.segment(data-tab='COSMIC')
|
53
|
+
= fragment do
|
54
|
+
|
55
|
+
.highlight.ui.form
|
56
|
+
.ui.field
|
57
|
+
%label Highlight color
|
58
|
+
%select.ui.select(name='color')
|
59
|
+
- colors.each do |c|
|
60
|
+
%option(value=c)= c
|
61
|
+
%a.highlight.ui.button(href="#") highlight
|
62
|
+
|
63
|
+
- header "Genomic Mutation", "GenomicMutation", {:organism => Organism.default_code("Hsa"), :watson => false}
|
64
|
+
- filter "Primary site"
|
65
|
+
= table :table_id => "COSMIC mutations for #{ protein.name || protein }", :row_ids => :consume do
|
66
|
+
- association_items = COSMIC.knowledge_base.subset(:mutation_protein_changes, :target => [protein], :source => :all)
|
67
|
+
- associations = association_items.tsv.to_double
|
68
|
+
|
69
|
+
- log :sample_mutations
|
70
|
+
- sample_mutations = COSMIC.knowledge_base.get_database(:sample_mutations, :type => :double, :merge => true, :target => "Sample name=~Sample", :source => "Genomic Mutation")
|
71
|
+
- sample_mutations.fields = ["Sample"]
|
72
|
+
|
73
|
+
- associations = associations.attach(sample_mutations)
|
74
|
+
|
75
|
+
- log :sample_info
|
76
|
+
- sample_info = COSMIC.sample_info.find.tsv
|
77
|
+
- sample_info.key_field = "Sample"
|
78
|
+
|
79
|
+
- associations = associations.attach(sample_info)
|
80
|
+
|
81
|
+
- good_fields = associations.fields - ["Ensembl Protein ID"]
|
82
|
+
|
83
|
+
- log :slice_and_show
|
84
|
+
- associations.slice(good_fields)
|
85
|
+
|
86
|
+
:deferjs
|
87
|
+
$('.COSMIC ul.highlight > li > a.highlight').click(function(){
|
88
|
+
|
89
|
+
var table = $(this).parents('dd').first().find('table');
|
90
|
+
var url = table.attr('attr-url');
|
91
|
+
var filter = table.attr('attr-filter');
|
92
|
+
|
93
|
+
url = add_parameter(url, '_format', 'json')
|
94
|
+
url = add_parameter(url, '_page', 'all')
|
95
|
+
url = add_parameter(url, '_column', 'Change')
|
96
|
+
if (undefined != filter){ url = add_parameter(url, '_filter', escape(filter)) }
|
97
|
+
|
98
|
+
var color = $(this).parents('dd').first().find('select[name=color]').val();
|
99
|
+
|
100
|
+
$.ajax({
|
101
|
+
url: url,
|
102
|
+
success: function(data){
|
103
|
+
data = JSON.parse(data);
|
104
|
+
var change_positions = [];
|
105
|
+
for (mutation in data){
|
106
|
+
var change = data[mutation][0];
|
107
|
+
if (m = change.match(/[A-Z*](\d*)[A-Z*]/)){
|
108
|
+
change_positions.push(parseInt(m[1]));
|
109
|
+
}
|
110
|
+
}
|
111
|
+
var protein_tool = $('.protein_tool#' + '#{id}');
|
112
|
+
protein_tool.protein_tool('mark_positions', change_positions, color);
|
113
|
+
}
|
114
|
+
})
|
115
|
+
return false;
|
116
|
+
})
|
117
|
+
|
118
|
+
|
119
|
+
:deferjs
|
120
|
+
$('.tabular.menu > .item').tab()
|
121
|
+
-#
|
122
|
+
|
123
|
+
%dd.COSMIC
|
124
|
+
= fragment do
|
125
|
+
|
126
|
+
%ul.highlight
|
127
|
+
%li.button
|
128
|
+
%a.highlight(href="#") highlight
|
129
|
+
%li
|
130
|
+
%select(name='color')
|
131
|
+
- colors.each do |c|
|
132
|
+
%option(value=c)= c
|
133
|
+
|
134
|
+
|
135
|
+
- header "Genomic Mutation", "GenomicMutation", {:organism => Organism.default_code("Hsa"), :watson => false}
|
136
|
+
- filter "Primary site"
|
137
|
+
= table :table_id => "COSMIC mutations for #{ protein.name || protein }", :row_ids => :consume do
|
138
|
+
- association_items = COSMIC.knowledge_base.subset(:mutation_protein_changes, :target => [protein], :source => :all)
|
139
|
+
- associations = association_items.tsv.to_double
|
140
|
+
|
141
|
+
- log :sample_mutations
|
142
|
+
- sample_mutations = COSMIC.knowledge_base.get_database(:sample_mutations, :type => :double, :merge => true, :target => "Sample name=~Sample", :source => "Genomic Mutation")
|
143
|
+
- sample_mutations.fields = ["Sample"]
|
144
|
+
|
145
|
+
- associations = associations.attach(sample_mutations)
|
146
|
+
|
147
|
+
- log :sample_info
|
148
|
+
- sample_info = COSMIC.sample_info.find.tsv
|
149
|
+
- sample_info.key_field = "Sample"
|
150
|
+
|
151
|
+
- associations = associations.attach(sample_info)
|
152
|
+
|
153
|
+
- good_fields = associations.fields - ["Ensembl Protein ID"]
|
154
|
+
|
155
|
+
- log :slice_and_show
|
156
|
+
- associations.slice(good_fields)
|
157
|
+
|
158
|
+
:deferjs
|
159
|
+
$('.COSMIC ul.highlight > li > a.highlight').click(function(){
|
160
|
+
|
161
|
+
var table = $(this).parents('dd').first().find('table');
|
162
|
+
var url = table.attr('attr-url');
|
163
|
+
var filter = table.attr('attr-filter');
|
164
|
+
|
165
|
+
url = add_parameter(url, '_format', 'json')
|
166
|
+
url = add_parameter(url, '_page', 'all')
|
167
|
+
url = add_parameter(url, '_column', 'Change')
|
168
|
+
if (undefined != filter){ url = add_parameter(url, '_filter', escape(filter)) }
|
169
|
+
|
170
|
+
var color = $(this).parents('dd').first().find('select[name=color]').val();
|
171
|
+
|
172
|
+
$.ajax({
|
173
|
+
url: url,
|
174
|
+
success: function(data){
|
175
|
+
data = JSON.parse(data);
|
176
|
+
var change_positions = [];
|
177
|
+
for (mutation in data){
|
178
|
+
var change = data[mutation][0];
|
179
|
+
if (m = change.match(/[A-Z*](\d*)[A-Z*]/)){
|
180
|
+
change_positions.push(parseInt(m[1]));
|
181
|
+
}
|
182
|
+
}
|
183
|
+
var protein_tool = $('.protein_tool#' + '#{id}');
|
184
|
+
protein_tool.protein_tool('mark_positions', change_positions, color);
|
185
|
+
}
|
186
|
+
})
|
187
|
+
return false;
|
188
|
+
})
|
189
|
+
|
190
|
+
- if protein.uniprot
|
191
|
+
- uniprot_alignment, ensembl_alignment = SmithWaterman.align(UniProt.sequence(protein.uniprot), protein.sequence)
|
192
|
+
- alignment_map = Structure.alignment_map(uniprot_alignment, ensembl_alignment)
|
193
|
+
|
194
|
+
%dt.next UniProt mutations
|
195
|
+
%dd.UniProt
|
196
|
+
= fragment do
|
197
|
+
|
198
|
+
%ul.highlight
|
199
|
+
%li
|
200
|
+
%a.highlight(href="#") highlight
|
201
|
+
%li
|
202
|
+
%select(name='color')
|
203
|
+
- colors.each do |c|
|
204
|
+
%option(value=c)= c
|
205
|
+
|
206
|
+
|
207
|
+
= table :id => "UniProt mutations for #{ protein }" do
|
208
|
+
- tsv = UniProt.annotated_variants.tsv(:persist => true, :type => :double, :key_field => "UniProt Variant ID", :zipped => true, :namespace => protein.organism)
|
209
|
+
- tsv = tsv.select("UniProt/SwissProt Accession" => protein.uniprot)
|
210
|
+
|
211
|
+
- tsv.add_field "Aligned Change" do |key, values|
|
212
|
+
- change = values["Amino Acid Mutation"]
|
213
|
+
- change = change.first if Array === change
|
214
|
+
- if change.nil? or change.empty?
|
215
|
+
- [""]
|
216
|
+
- else
|
217
|
+
- wt, pos, mut = change.match(/([A-Z])(\d+)([A-Z*])/).values_at 1, 2, 3
|
218
|
+
- pos = alignment_map[pos.to_i]
|
219
|
+
- [[wt, pos, mut] * ""]
|
220
|
+
- tsv
|
221
|
+
|
222
|
+
:deferjs
|
223
|
+
$('.UniProt a.highlight').click(function(){
|
224
|
+
var table = $(this).parents('dd').first().find('table');
|
225
|
+
var url = table.attr('attr-url');
|
226
|
+
var filter = table.attr('attr-filter');
|
227
|
+
|
228
|
+
url = add_parameter(url, '_format', 'json')
|
229
|
+
url = add_parameter(url, '_page', 'all')
|
230
|
+
url = add_parameter(url, '_column', 'Aligned Change')
|
231
|
+
if (undefined != filter){ url = add_parameter(url, '_filter', escape(filter)) }
|
232
|
+
|
233
|
+
var color = $(this).parents('dd').first().find('select[name=color]').val();
|
234
|
+
|
235
|
+
$.ajax({
|
236
|
+
url: url,
|
237
|
+
success: function(data){
|
238
|
+
data = JSON.parse(data);
|
239
|
+
var change_positions = [];
|
240
|
+
for (mutation in data){
|
241
|
+
var changes = data[mutation];
|
242
|
+
for (i in changes){
|
243
|
+
var c = changes[i];
|
244
|
+
if (m = c.match(/(\d+)/)){
|
245
|
+
change_positions.push(parseInt(m[1]));
|
246
|
+
}
|
247
|
+
}
|
248
|
+
}
|
249
|
+
var protein_tool = $('.protein_tool#' + '#{id}');
|
250
|
+
protein_tool.protein_tool('mark_positions', change_positions, color);
|
251
|
+
}
|
252
|
+
})
|
253
|
+
|
254
|
+
return false;
|
255
|
+
})
|
256
|
+
|
257
|
+
%dt.next UniProt features
|
258
|
+
%dd.UniProt_features
|
259
|
+
.controls
|
260
|
+
%ul.controls
|
261
|
+
%li
|
262
|
+
%select(name='color')
|
263
|
+
- colors.each do |c|
|
264
|
+
%option(value=c)= c
|
265
|
+
|
266
|
+
- features = UniProt.features(protein.uniprot)
|
267
|
+
- feature_types = {}
|
268
|
+
- features.each{|info| feature_types[info[:type]] ||= [] ; feature_types[info[:type]] << info}
|
269
|
+
%dl
|
270
|
+
- feature_types.sort_by{|k,v| k}.each do |type, list|
|
271
|
+
%dt= type
|
272
|
+
%dd
|
273
|
+
- list.sort_by{|info| info[:start].to_i}.each do |info|
|
274
|
+
- type, start, eend, description = info.values_at :type, :start, :end, :description
|
275
|
+
- start = alignment_map[start]
|
276
|
+
- eend = alignment_map[eend]
|
277
|
+
- next if start.nil? or eend.nil?
|
278
|
+
%li
|
279
|
+
%a.feature_highlight(href="#" attr-start="#{start}" attr-end="#{eend}") Highlight
|
280
|
+
== #{ type } (#{start}..#{eend}): #{description}
|
281
|
+
|
282
|
+
:deferjs
|
283
|
+
$('.UniProt a.highlight').click(function(){
|
284
|
+
var table = $(this).parents('dd').first().find('table');
|
285
|
+
var url = table.attr('attr-url');
|
286
|
+
var filter = table.attr('attr-filter');
|
287
|
+
|
288
|
+
url = add_parameter(url, '_format', 'json')
|
289
|
+
url = add_parameter(url, '_page', 'all')
|
290
|
+
url = add_parameter(url, '_column', 'Aligned Change')
|
291
|
+
if (undefined != filter){ url = add_parameter(url, '_filter', escape(filter)) }
|
292
|
+
|
293
|
+
$.ajax({
|
294
|
+
url: url,
|
295
|
+
success: function(data){
|
296
|
+
data = JSON.parse(data);
|
297
|
+
var change_positions = [];
|
298
|
+
for (mutation in data){
|
299
|
+
var changes = data[mutation];
|
300
|
+
for (i in changes){
|
301
|
+
var c = changes[i];
|
302
|
+
if (m = c.match(/(\d+)/)){
|
303
|
+
change_positions.push(parseInt(m[1]));
|
304
|
+
}
|
305
|
+
}
|
306
|
+
}
|
307
|
+
var protein_tool = $('.protein_tool#' + '#{id}');
|
308
|
+
protein_tool.protein_tool('mark_positions', change_positions, color);
|
309
|
+
}
|
310
|
+
})
|
311
|
+
|
312
|
+
return false;
|
313
|
+
})
|
314
|
+
|
315
|
+
|