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.

@@ -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 File.join(root, 'lib', 'sequenceserver')
4
+ require 'bundler/setup'
5
+ require 'sequenceserver'
8
6
 
9
7
  # display name for tools like `ps`
10
8
  $PROGRAM_NAME = 'sequenceserver'
@@ -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
- return (sequence && type_of_sequences(sequence)).to_s
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
 
@@ -66,6 +66,7 @@ body {
66
66
  border-radius: 6px;
67
67
  -moz-border-radius: 6px;
68
68
  padding: 3%;
69
+ border: 1px solid transparent;
69
70
  }
70
71
 
71
72
  .focussed {
@@ -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
 
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  # meta
3
3
  s.name = 'sequenceserver'
4
- s.version = '0.6.8'
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>&copy; <a href='http://www.sequenceserver.com'>sequenceserver.com</a></p>
217
+ <p>&copy; <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: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 8
10
- version: 0.6.8
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-15 00:00:00 Z
20
+ date: 2011-12-16 00:00:00 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
- name: sinatra
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: *id001
51
+ version_requirements: *id002
38
52
  - !ruby/object:Gem::Dependency
39
53
  name: ptools
40
54
  prerelease: false
41
- requirement: &id002 !ruby/object:Gem::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: *id002
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: