sequenceserver 0.6.8 → 0.6.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sequenceserver might be problematic. Click here for more details.
- data/bin/database_formatter +1 -3
- data/bin/sequenceserver +2 -4
- data/lib/sequenceserver.rb +7 -5
- data/public/css/custom.css +1 -0
- data/public/js/jquery.activity.js +224 -0
- data/public/js/search.js +17 -0
- data/sequenceserver.gemspec +2 -1
- data/views/search.erb +3 -2
- metadata +24 -8
data/bin/database_formatter
CHANGED
@@ -2,10 +2,8 @@
|
|
2
2
|
# copyright yannick . wurm at unil . ch
|
3
3
|
# Finds files, reads first char. if its '>', read 500 lines. Guess sequence type, ask user for title to format as blast database.
|
4
4
|
|
5
|
-
# ensure 'lib/' is in the load path
|
6
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
-
|
8
5
|
require 'rubygems'
|
6
|
+
require 'bundler/setup'
|
9
7
|
require 'ptools' # for File.binary?(file)
|
10
8
|
require 'find'
|
11
9
|
require 'logger'
|
data/bin/sequenceserver
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
# application root
|
4
|
-
root = File.dirname(File.dirname(__FILE__))
|
5
|
-
|
6
3
|
require 'rubygems'
|
7
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'sequenceserver'
|
8
6
|
|
9
7
|
# display name for tools like `ps`
|
10
8
|
$PROGRAM_NAME = 'sequenceserver'
|
data/lib/sequenceserver.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
# sequenceserver.rb
|
2
2
|
|
3
|
-
# ensure 'lib/' is in the load path
|
4
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
-
|
6
|
-
require 'rubygems'
|
7
3
|
require 'sinatra/base'
|
8
4
|
require 'yaml'
|
9
5
|
require 'logger'
|
@@ -233,8 +229,10 @@ module SequenceServer
|
|
233
229
|
# evaluate empty sequence as nil, otherwise as fasta
|
234
230
|
sequence = sequence.empty? ? nil : to_fasta(sequence)
|
235
231
|
|
232
|
+
# TODO: detect sequence type in the browser itself (no AJAX)
|
236
233
|
if request.xhr?
|
237
|
-
|
234
|
+
# if the AJAX request didn't specify a blast method, it must be interested in sequence type only
|
235
|
+
return (sequence && type_of_sequences(sequence)).to_s unless method
|
238
236
|
end
|
239
237
|
|
240
238
|
# Raise ArgumentError if there is no database selected
|
@@ -293,6 +291,10 @@ module SequenceServer
|
|
293
291
|
|
294
292
|
@blast = format_blast_results(blast.result, databases)
|
295
293
|
|
294
|
+
if request.xhr?
|
295
|
+
return @blast
|
296
|
+
end
|
297
|
+
|
296
298
|
erb :search
|
297
299
|
end
|
298
300
|
|
data/public/css/custom.css
CHANGED
@@ -0,0 +1,224 @@
|
|
1
|
+
/*!
|
2
|
+
* NETEYE Activity Indicator jQuery Plugin
|
3
|
+
*
|
4
|
+
* Copyright (c) 2010 NETEYE GmbH
|
5
|
+
* Licensed under the MIT license
|
6
|
+
*
|
7
|
+
* Author: Felix Gnass [fgnass at neteye dot de]
|
8
|
+
* Version: @{VERSION}
|
9
|
+
*/
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Plugin that renders a customisable activity indicator (spinner) using SVG or VML.
|
13
|
+
*/
|
14
|
+
(function($) {
|
15
|
+
|
16
|
+
$.fn.activity = function(opts) {
|
17
|
+
this.each(function() {
|
18
|
+
var $this = $(this);
|
19
|
+
var el = $this.data('activity');
|
20
|
+
if (el) {
|
21
|
+
clearInterval(el.data('interval'));
|
22
|
+
el.remove();
|
23
|
+
$this.removeData('activity');
|
24
|
+
}
|
25
|
+
if (opts !== false) {
|
26
|
+
opts = $.extend({color: $this.css('color')}, $.fn.activity.defaults, opts);
|
27
|
+
|
28
|
+
el = render($this, opts).css('position', 'absolute').prependTo(opts.outside ? 'body' : $this);
|
29
|
+
var h = $this.outerHeight() - el.height();
|
30
|
+
var w = $this.outerWidth() - el.width();
|
31
|
+
var margin = {
|
32
|
+
top: opts.valign == 'top' ? opts.padding : opts.valign == 'bottom' ? h - opts.padding : Math.floor(h / 2),
|
33
|
+
left: opts.align == 'left' ? opts.padding : opts.align == 'right' ? w - opts.padding : Math.floor(w / 2)
|
34
|
+
};
|
35
|
+
var offset = $this.offset();
|
36
|
+
if (opts.outside) {
|
37
|
+
el.css({top: offset.top + 'px', left: offset.left + 'px'});
|
38
|
+
}
|
39
|
+
else {
|
40
|
+
margin.top -= el.offset().top - offset.top;
|
41
|
+
margin.left -= el.offset().left - offset.left;
|
42
|
+
}
|
43
|
+
el.css({marginTop: margin.top + 'px', marginLeft: margin.left + 'px'});
|
44
|
+
animate(el, opts.segments, Math.round(10 / opts.speed) / 10);
|
45
|
+
$this.data('activity', el);
|
46
|
+
}
|
47
|
+
});
|
48
|
+
return this;
|
49
|
+
};
|
50
|
+
|
51
|
+
$.fn.activity.defaults = {
|
52
|
+
segments: 12,
|
53
|
+
space: 3,
|
54
|
+
length: 7,
|
55
|
+
width: 4,
|
56
|
+
speed: 1.2,
|
57
|
+
align: 'center',
|
58
|
+
valign: 'center',
|
59
|
+
padding: 4
|
60
|
+
};
|
61
|
+
|
62
|
+
$.fn.activity.getOpacity = function(opts, i) {
|
63
|
+
var steps = opts.steps || opts.segments-1;
|
64
|
+
var end = opts.opacity !== undefined ? opts.opacity : 1/steps;
|
65
|
+
return 1 - Math.min(i, steps) * (1 - end) / steps;
|
66
|
+
};
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Default rendering strategy. If neither SVG nor VML is available, a div with class-name 'busy'
|
70
|
+
* is inserted, that can be styled with CSS to display an animated gif as fallback.
|
71
|
+
*/
|
72
|
+
var render = function() {
|
73
|
+
return $('<div>').addClass('busy');
|
74
|
+
};
|
75
|
+
|
76
|
+
/**
|
77
|
+
* The default animation strategy does nothing as we expect an animated gif as fallback.
|
78
|
+
*/
|
79
|
+
var animate = function() {
|
80
|
+
};
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Utility function to create elements in the SVG namespace.
|
84
|
+
*/
|
85
|
+
function svg(tag, attr) {
|
86
|
+
var el = document.createElementNS("http://www.w3.org/2000/svg", tag || 'svg');
|
87
|
+
if (attr) {
|
88
|
+
$.each(attr, function(k, v) {
|
89
|
+
el.setAttributeNS(null, k, v);
|
90
|
+
});
|
91
|
+
}
|
92
|
+
return $(el);
|
93
|
+
}
|
94
|
+
|
95
|
+
if (document.createElementNS && document.createElementNS( "http://www.w3.org/2000/svg", "svg").createSVGRect) {
|
96
|
+
|
97
|
+
// =======================================================================================
|
98
|
+
// SVG Rendering
|
99
|
+
// =======================================================================================
|
100
|
+
|
101
|
+
/**
|
102
|
+
* Rendering strategy that creates a SVG tree.
|
103
|
+
*/
|
104
|
+
render = function(target, d) {
|
105
|
+
var innerRadius = d.width*2 + d.space;
|
106
|
+
var r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1);
|
107
|
+
|
108
|
+
var el = svg().width(r*2).height(r*2);
|
109
|
+
|
110
|
+
var g = svg('g', {
|
111
|
+
'stroke-width': d.width,
|
112
|
+
'stroke-linecap': 'round',
|
113
|
+
stroke: d.color
|
114
|
+
}).appendTo(svg('g', {transform: 'translate('+ r +','+ r +')'}).appendTo(el));
|
115
|
+
|
116
|
+
for (var i = 0; i < d.segments; i++) {
|
117
|
+
g.append(svg('line', {
|
118
|
+
x1: 0,
|
119
|
+
y1: innerRadius,
|
120
|
+
x2: 0,
|
121
|
+
y2: innerRadius + d.length,
|
122
|
+
transform: 'rotate(' + (360 / d.segments * i) + ', 0, 0)',
|
123
|
+
opacity: $.fn.activity.getOpacity(d, i)
|
124
|
+
}));
|
125
|
+
}
|
126
|
+
return $('<div>').append(el).width(2*r).height(2*r);
|
127
|
+
};
|
128
|
+
|
129
|
+
// Check if Webkit CSS animations are available, as they work much better on the iPad
|
130
|
+
// than setTimeout() based animations.
|
131
|
+
|
132
|
+
if (document.createElement('div').style.WebkitAnimationName !== undefined) {
|
133
|
+
|
134
|
+
var animations = {};
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Animation strategy that uses dynamically created CSS animation rules.
|
138
|
+
*/
|
139
|
+
animate = function(el, steps, duration) {
|
140
|
+
if (!animations[steps]) {
|
141
|
+
var name = 'spin' + steps;
|
142
|
+
var rule = '@-webkit-keyframes '+ name +' {';
|
143
|
+
for (var i=0; i < steps; i++) {
|
144
|
+
var p1 = Math.round(100000 / steps * i) / 1000;
|
145
|
+
var p2 = Math.round(100000 / steps * (i+1) - 1) / 1000;
|
146
|
+
var value = '% { -webkit-transform:rotate(' + Math.round(360 / steps * i) + 'deg); }\n';
|
147
|
+
rule += p1 + value + p2 + value;
|
148
|
+
}
|
149
|
+
rule += '100% { -webkit-transform:rotate(100deg); }\n}';
|
150
|
+
document.styleSheets[0].insertRule(rule);
|
151
|
+
animations[steps] = name;
|
152
|
+
}
|
153
|
+
el.css('-webkit-animation', animations[steps] + ' ' + duration +'s linear infinite');
|
154
|
+
};
|
155
|
+
}
|
156
|
+
else {
|
157
|
+
|
158
|
+
/**
|
159
|
+
* Animation strategy that transforms a SVG element using setInterval().
|
160
|
+
*/
|
161
|
+
animate = function(el, steps, duration) {
|
162
|
+
var rotation = 0;
|
163
|
+
var g = el.find('g g').get(0);
|
164
|
+
el.data('interval', setInterval(function() {
|
165
|
+
g.setAttributeNS(null, 'transform', 'rotate(' + (++rotation % steps * (360 / steps)) + ')');
|
166
|
+
}, duration * 1000 / steps));
|
167
|
+
};
|
168
|
+
}
|
169
|
+
|
170
|
+
}
|
171
|
+
else {
|
172
|
+
|
173
|
+
// =======================================================================================
|
174
|
+
// VML Rendering
|
175
|
+
// =======================================================================================
|
176
|
+
|
177
|
+
var s = $('<shape>').css('behavior', 'url(#default#VML)');
|
178
|
+
|
179
|
+
$('body').append(s);
|
180
|
+
|
181
|
+
if (s.get(0).adj) {
|
182
|
+
|
183
|
+
// VML support detected. Insert CSS rules for group, shape and stroke.
|
184
|
+
var sheet = document.createStyleSheet();
|
185
|
+
$.each(['group', 'shape', 'stroke'], function() {
|
186
|
+
sheet.addRule(this, "behavior:url(#default#VML);");
|
187
|
+
});
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Rendering strategy that creates a VML tree.
|
191
|
+
*/
|
192
|
+
render = function(target, d) {
|
193
|
+
|
194
|
+
var innerRadius = d.width*2 + d.space;
|
195
|
+
var r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1);
|
196
|
+
var s = r*2;
|
197
|
+
var o = -Math.ceil(s/2);
|
198
|
+
|
199
|
+
var el = $('<group>', {coordsize: s + ' ' + s, coordorigin: o + ' ' + o}).css({top: o, left: o, width: s, height: s});
|
200
|
+
for (var i = 0; i < d.segments; i++) {
|
201
|
+
el.append($('<shape>', {path: 'm ' + innerRadius + ',0 l ' + (innerRadius + d.length) + ',0'}).css({
|
202
|
+
width: s,
|
203
|
+
height: s,
|
204
|
+
rotation: (360 / d.segments * i) + 'deg'
|
205
|
+
}).append($('<stroke>', {color: d.color, weight: d.width + 'px', endcap: 'round', opacity: $.fn.activity.getOpacity(d, i)})));
|
206
|
+
}
|
207
|
+
return $('<group>', {coordsize: s + ' ' + s}).css({width: s, height: s, overflow: 'hidden'}).append(el);
|
208
|
+
};
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Animation strategy that modifies the VML rotation property using setInterval().
|
212
|
+
*/
|
213
|
+
animate = function(el, steps, duration) {
|
214
|
+
var rotation = 0;
|
215
|
+
var g = el.get(0);
|
216
|
+
el.data('interval', setInterval(function() {
|
217
|
+
g.style.rotation = ++rotation % steps * (360 / steps);
|
218
|
+
}, duration * 1000 / steps));
|
219
|
+
};
|
220
|
+
}
|
221
|
+
$(s).remove();
|
222
|
+
}
|
223
|
+
|
224
|
+
})(jQuery);
|
data/public/js/search.js
CHANGED
@@ -129,6 +129,23 @@ $(document).ready(function(){
|
|
129
129
|
$.onedb();
|
130
130
|
});
|
131
131
|
|
132
|
+
$('input:submit').click(function(){
|
133
|
+
var button = $(this);
|
134
|
+
|
135
|
+
//prevent submitting another query while this one is being processed
|
136
|
+
button.disable();
|
137
|
+
|
138
|
+
//fetch results now
|
139
|
+
$.post('', $('form').serialize(), function(data){
|
140
|
+
$('#result').html(data);
|
141
|
+
location.hash = '#result';
|
142
|
+
|
143
|
+
//result of previous query loaded; allow submitting a new query now
|
144
|
+
button.enable();
|
145
|
+
});
|
146
|
+
return false;
|
147
|
+
});
|
148
|
+
|
132
149
|
$(window).scroll(function() {
|
133
150
|
var areaHeight = $(this).height();
|
134
151
|
|
data/sequenceserver.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
# meta
|
3
3
|
s.name = 'sequenceserver'
|
4
|
-
s.version = '0.6.
|
4
|
+
s.version = '0.6.9'
|
5
5
|
s.authors = ['Anurag Priyam', 'Ben J Woodcroft', 'Yannick Wurm']
|
6
6
|
s.email = 'anurag08priyam@gmail.com'
|
7
7
|
s.homepage = 'http://sequenceserver.com'
|
@@ -13,6 +13,7 @@ SequenceServer lets you rapidly set up a BLAST+ server with an intuitive user in
|
|
13
13
|
DESC
|
14
14
|
|
15
15
|
# dependencies
|
16
|
+
s.add_dependency('bundler')
|
16
17
|
s.add_dependency('sinatra', '>= 1.2.0')
|
17
18
|
s.add_dependency('ptools')
|
18
19
|
|
data/views/search.erb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html lang="en">
|
3
3
|
<head>
|
4
|
-
<title>SequenceServer</title>
|
4
|
+
<title>SequenceServer: Custom BLAST Server</title>
|
5
5
|
<meta name="author" content="Anurag Priyam" />
|
6
6
|
<meta name="author" content="Ben J. Woodcroft" />
|
7
7
|
<meta name="author" content="Yannick Wurm" />
|
8
8
|
<meta name="author" content="Cedric Wurm" />
|
9
|
+
<meta name="description" content="Custom BLAST server provided by SequenceServer (http://www.sequenceserver.com)"/>
|
9
10
|
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
|
10
11
|
<script type="text/javascript" src="<%= uri('/js/jquery.js') %>"></script>
|
11
12
|
<script type="text/javascript" src="<%= uri('/js/jquery.enablePlaceholder.min.js') %>"></script>
|
@@ -213,7 +214,7 @@
|
|
213
214
|
</div>
|
214
215
|
|
215
216
|
<div id="underbar">
|
216
|
-
<p>© <a href='http://www.sequenceserver.com'>
|
217
|
+
<p>© <a href='http://www.sequenceserver.com'>SequenceServer: BLAST search made easy!</a></p>
|
217
218
|
</div>
|
218
219
|
</div> <!-- /page -->
|
219
220
|
</div> <!-- /container -->
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequenceserver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 0.6.
|
9
|
+
- 9
|
10
|
+
version: 0.6.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Anurag Priyam
|
@@ -17,12 +17,26 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-12-
|
20
|
+
date: 2011-12-16 00:00:00 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
|
-
name:
|
23
|
+
name: bundler
|
24
24
|
prerelease: false
|
25
25
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 3
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
version: "0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sinatra
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
26
40
|
none: false
|
27
41
|
requirements:
|
28
42
|
- - ">="
|
@@ -34,11 +48,11 @@ dependencies:
|
|
34
48
|
- 0
|
35
49
|
version: 1.2.0
|
36
50
|
type: :runtime
|
37
|
-
version_requirements: *
|
51
|
+
version_requirements: *id002
|
38
52
|
- !ruby/object:Gem::Dependency
|
39
53
|
name: ptools
|
40
54
|
prerelease: false
|
41
|
-
requirement: &
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
56
|
none: false
|
43
57
|
requirements:
|
44
58
|
- - ">="
|
@@ -48,7 +62,7 @@ dependencies:
|
|
48
62
|
- 0
|
49
63
|
version: "0"
|
50
64
|
type: :runtime
|
51
|
-
version_requirements: *
|
65
|
+
version_requirements: *id003
|
52
66
|
description: |
|
53
67
|
SequenceServer lets you rapidly set up a BLAST+ server with an intuitive user interface for use locally or over the web.
|
54
68
|
|
@@ -76,6 +90,7 @@ files:
|
|
76
90
|
- public/js/jquery.js
|
77
91
|
- public/js/jquery.enablePlaceholder.min.js
|
78
92
|
- public/js/search.js
|
93
|
+
- public/js/jquery.activity.js
|
79
94
|
- tests/test_sequencehelpers.rb
|
80
95
|
- tests/database/protein/Sinvicta2-2-3.prot.subset.fasta.pin
|
81
96
|
- tests/database/protein/Sinvicta2-2-3.prot.subset.fasta
|
@@ -140,3 +155,4 @@ specification_version: 3
|
|
140
155
|
summary: iPod of BLAST searching
|
141
156
|
test_files: []
|
142
157
|
|
158
|
+
has_rdoc:
|