sequenceserver 1.0.0.pre.2 → 1.0.0.pre.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +18 -4
- data/bin/sequenceserver +219 -124
- data/lib/sequenceserver.rb +156 -153
- data/lib/sequenceserver/blast.rb +163 -432
- data/lib/sequenceserver/blast/exceptions.rb +27 -0
- data/lib/sequenceserver/blast/hit.rb +32 -0
- data/lib/sequenceserver/blast/hsp.rb +260 -0
- data/lib/sequenceserver/blast/query.rb +28 -0
- data/lib/sequenceserver/blast/report.rb +123 -0
- data/lib/sequenceserver/config.rb +94 -0
- data/lib/sequenceserver/database.rb +89 -49
- data/lib/sequenceserver/exceptions.rb +154 -0
- data/lib/sequenceserver/links.rb +1 -1
- data/lib/sequenceserver/logger.rb +5 -7
- data/lib/sequenceserver/sequence.rb +40 -39
- data/public/css/bootstrap.min.css +5 -7
- data/public/css/custom.css +28 -27
- data/public/dist/css/sequenceserver.min.css +1 -0
- data/public/dist/css/sequenceserver.min.css.gz +0 -0
- data/public/dist/fonts/FontAwesome.otf +0 -0
- data/public/dist/fonts/fontawesome-webfont.eot +0 -0
- data/public/dist/fonts/fontawesome-webfont.svg +565 -0
- data/public/dist/fonts/fontawesome-webfont.ttf +0 -0
- data/public/dist/fonts/fontawesome-webfont.woff +0 -0
- data/public/dist/fonts/fontawesome-webfont.woff2 +0 -0
- data/public/dist/js/sequenceserver.min.js +12 -0
- data/public/dist/js/sequenceserver.min.js.gz +0 -0
- data/public/dist/js/shims/FlashCanvas/canvas2png.js +1 -0
- data/public/dist/js/shims/FlashCanvas/flashcanvas.js +1 -0
- data/public/dist/js/shims/FlashCanvas/flashcanvas.swf +0 -0
- data/public/dist/js/shims/FlashCanvasPro/canvas2png.js +1 -0
- data/public/dist/js/shims/FlashCanvasPro/flash10canvas.swf +0 -0
- data/public/dist/js/shims/FlashCanvasPro/flash9canvas.swf +0 -0
- data/public/dist/js/shims/FlashCanvasPro/flashcanvas.js +1 -0
- data/public/dist/js/shims/canvas-blob.js +1 -0
- data/public/dist/js/shims/color-picker.js +2 -0
- data/public/dist/js/shims/combos/1.js +6 -0
- data/public/dist/js/shims/combos/10.js +2 -0
- data/public/dist/js/shims/combos/11.js +2 -0
- data/public/dist/js/shims/combos/12.js +6 -0
- data/public/dist/js/shims/combos/13.js +1 -0
- data/public/dist/js/shims/combos/14.js +1 -0
- data/public/dist/js/shims/combos/15.js +2 -0
- data/public/dist/js/shims/combos/16.js +7 -0
- data/public/dist/js/shims/combos/17.js +2 -0
- data/public/dist/js/shims/combos/18.js +3 -0
- data/public/dist/js/shims/combos/2.js +7 -0
- data/public/dist/js/shims/combos/21.js +2 -0
- data/public/dist/js/shims/combos/22.js +1 -0
- data/public/dist/js/shims/combos/23.js +6 -0
- data/public/dist/js/shims/combos/25.js +2 -0
- data/public/dist/js/shims/combos/27.js +1 -0
- data/public/dist/js/shims/combos/28.js +1 -0
- data/public/dist/js/shims/combos/29.js +1 -0
- data/public/dist/js/shims/combos/3.js +1 -0
- data/public/dist/js/shims/combos/30.js +2 -0
- data/public/dist/js/shims/combos/31.js +1 -0
- data/public/dist/js/shims/combos/33.js +1 -0
- data/public/dist/js/shims/combos/34.js +1 -0
- data/public/dist/js/shims/combos/4.js +1 -0
- data/public/dist/js/shims/combos/5.js +2 -0
- data/public/dist/js/shims/combos/6.js +2 -0
- data/public/dist/js/shims/combos/7.js +7 -0
- data/public/dist/js/shims/combos/8.js +7 -0
- data/public/dist/js/shims/combos/9.js +2 -0
- data/public/dist/js/shims/combos/97.js +1 -0
- data/public/dist/js/shims/combos/98.js +1 -0
- data/public/dist/js/shims/combos/99.js +1 -0
- data/public/dist/js/shims/details.js +1 -0
- data/public/dist/js/shims/dom-extend.js +1 -0
- data/public/dist/js/shims/es5.js +1 -0
- data/public/dist/js/shims/es6.js +1 -0
- data/public/dist/js/shims/excanvas.js +1 -0
- data/public/dist/js/shims/filereader-xhr.js +1 -0
- data/public/dist/js/shims/form-combat.js +1 -0
- data/public/dist/js/shims/form-core.js +1 -0
- data/public/dist/js/shims/form-datalist-lazy.js +1 -0
- data/public/dist/js/shims/form-datalist.js +1 -0
- data/public/dist/js/shims/form-fixrangechange.js +1 -0
- data/public/dist/js/shims/form-inputmode.js +1 -0
- data/public/dist/js/shims/form-message.js +1 -0
- data/public/dist/js/shims/form-native-extend.js +1 -0
- data/public/dist/js/shims/form-number-date-api.js +1 -0
- data/public/dist/js/shims/form-number-date-ui.js +1 -0
- data/public/dist/js/shims/form-shim-extend.js +1 -0
- data/public/dist/js/shims/form-shim-extend2.js +1 -0
- data/public/dist/js/shims/form-validation.js +1 -0
- data/public/dist/js/shims/form-validators.js +1 -0
- data/public/dist/js/shims/forms-picker.js +1 -0
- data/public/dist/js/shims/geolocation.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-ar.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-ch-CN.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-cs.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-de.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-el.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-en.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-es.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-fa.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-fr.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-he.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-hi.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-hu.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-it.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-ja.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-lt.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-nl.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-pl.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-pt-BR.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-pt-PT.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-pt.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-ru.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-sv.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-zh-CN.js +1 -0
- data/public/dist/js/shims/i18n/formcfg-zh-TW.js +1 -0
- data/public/dist/js/shims/jme/alternate-media.js +1 -0
- data/public/dist/js/shims/jme/base.js +1 -0
- data/public/dist/js/shims/jme/controls.css +1 -0
- data/public/dist/js/shims/jme/jme.eot +0 -0
- data/public/dist/js/shims/jme/jme.svg +36 -0
- data/public/dist/js/shims/jme/jme.ttf +0 -0
- data/public/dist/js/shims/jme/jme.woff +0 -0
- data/public/dist/js/shims/jme/mediacontrols-lazy.js +1 -0
- data/public/dist/js/shims/jme/mediacontrols.js +1 -0
- data/public/dist/js/shims/jme/playlist.js +1 -0
- data/public/dist/js/shims/jpicker/images/AlphaBar.png +0 -0
- data/public/dist/js/shims/jpicker/images/Bars.png +0 -0
- data/public/dist/js/shims/jpicker/images/Maps.png +0 -0
- data/public/dist/js/shims/jpicker/images/NoColor.png +0 -0
- data/public/dist/js/shims/jpicker/images/bar-opacity.png +0 -0
- data/public/dist/js/shims/jpicker/images/map-opacity.png +0 -0
- data/public/dist/js/shims/jpicker/images/mappoint.gif +0 -0
- data/public/dist/js/shims/jpicker/images/picker.gif +0 -0
- data/public/dist/js/shims/jpicker/images/preview-opacity.png +0 -0
- data/public/dist/js/shims/jpicker/images/rangearrows.gif +0 -0
- data/public/dist/js/shims/jpicker/jpicker.css +1 -0
- data/public/dist/js/shims/matchMedia.js +3 -0
- data/public/dist/js/shims/mediacapture-picker.js +1 -0
- data/public/dist/js/shims/mediacapture.js +1 -0
- data/public/dist/js/shims/mediaelement-core.js +1 -0
- data/public/dist/js/shims/mediaelement-debug.js +1 -0
- data/public/dist/js/shims/mediaelement-jaris.js +1 -0
- data/public/dist/js/shims/mediaelement-native-fix.js +1 -0
- data/public/dist/js/shims/mediaelement-yt.js +1 -0
- data/public/dist/js/shims/moxie/flash/Moxie.cdn.swf +0 -0
- data/public/dist/js/shims/moxie/flash/Moxie.min.swf +0 -0
- data/public/dist/js/shims/moxie/js/moxie-html4.js +3 -0
- data/public/dist/js/shims/moxie/js/moxie-swf.js +2 -0
- data/public/dist/js/shims/picture.js +1 -0
- data/public/dist/js/shims/plugins/jquery.ui.position.js +11 -0
- data/public/dist/js/shims/range-ui.js +1 -0
- data/public/dist/js/shims/sizzle.js +11 -0
- data/public/dist/js/shims/sticky.js +1 -0
- data/public/dist/js/shims/styles/color-picker.png +0 -0
- data/public/dist/js/shims/styles/forms-ext.css +1 -0
- data/public/dist/js/shims/styles/forms-picker.css +1 -0
- data/public/dist/js/shims/styles/progress.gif +0 -0
- data/public/dist/js/shims/styles/progress.png +0 -0
- data/public/dist/js/shims/styles/shim-ext.css +1 -0
- data/public/dist/js/shims/styles/shim.css +1 -0
- data/public/dist/js/shims/styles/transparent.png +0 -0
- data/public/dist/js/shims/styles/widget.eot +0 -0
- data/public/dist/js/shims/styles/widget.svg +12 -0
- data/public/dist/js/shims/styles/widget.ttf +0 -0
- data/public/dist/js/shims/styles/widget.woff +0 -0
- data/public/dist/js/shims/swf/JarisFLVPlayer.swf +0 -0
- data/public/dist/js/shims/swfmini-embed.js +1 -0
- data/public/dist/js/shims/swfmini.js +6 -0
- data/public/dist/js/shims/track-ui.js +1 -0
- data/public/dist/js/shims/track.js +1 -0
- data/public/dist/js/shims/url.js +1 -0
- data/public/dist/js/shims/usermedia-core.js +1 -0
- data/public/dist/js/shims/usermedia-shim.js +1 -0
- data/public/dist/js/webshims/shims/FlashCanvas/canvas2png.js +1 -0
- data/public/dist/js/webshims/shims/FlashCanvas/flashcanvas.js +1 -0
- data/public/dist/js/webshims/shims/FlashCanvas/flashcanvas.swf +0 -0
- data/public/dist/js/webshims/shims/FlashCanvasPro/canvas2png.js +1 -0
- data/public/dist/js/webshims/shims/FlashCanvasPro/flash10canvas.swf +0 -0
- data/public/dist/js/webshims/shims/FlashCanvasPro/flash9canvas.swf +0 -0
- data/public/dist/js/webshims/shims/FlashCanvasPro/flashcanvas.js +1 -0
- data/public/dist/js/webshims/shims/canvas-blob.js +1 -0
- data/public/dist/js/webshims/shims/color-picker.js +2 -0
- data/public/dist/js/webshims/shims/combos/1.js +6 -0
- data/public/dist/js/webshims/shims/combos/10.js +2 -0
- data/public/dist/js/webshims/shims/combos/11.js +2 -0
- data/public/dist/js/webshims/shims/combos/12.js +6 -0
- data/public/dist/js/webshims/shims/combos/13.js +1 -0
- data/public/dist/js/webshims/shims/combos/14.js +1 -0
- data/public/dist/js/webshims/shims/combos/15.js +2 -0
- data/public/dist/js/webshims/shims/combos/16.js +7 -0
- data/public/dist/js/webshims/shims/combos/17.js +2 -0
- data/public/dist/js/webshims/shims/combos/18.js +3 -0
- data/public/dist/js/webshims/shims/combos/2.js +7 -0
- data/public/dist/js/webshims/shims/combos/21.js +2 -0
- data/public/dist/js/webshims/shims/combos/22.js +1 -0
- data/public/dist/js/webshims/shims/combos/23.js +6 -0
- data/public/dist/js/webshims/shims/combos/25.js +2 -0
- data/public/dist/js/webshims/shims/combos/27.js +1 -0
- data/public/dist/js/webshims/shims/combos/28.js +1 -0
- data/public/dist/js/webshims/shims/combos/29.js +1 -0
- data/public/dist/js/webshims/shims/combos/3.js +1 -0
- data/public/dist/js/webshims/shims/combos/30.js +2 -0
- data/public/dist/js/webshims/shims/combos/31.js +1 -0
- data/public/dist/js/webshims/shims/combos/33.js +1 -0
- data/public/dist/js/webshims/shims/combos/34.js +1 -0
- data/public/dist/js/webshims/shims/combos/4.js +1 -0
- data/public/dist/js/webshims/shims/combos/5.js +2 -0
- data/public/dist/js/webshims/shims/combos/6.js +2 -0
- data/public/dist/js/webshims/shims/combos/7.js +7 -0
- data/public/dist/js/webshims/shims/combos/8.js +7 -0
- data/public/dist/js/webshims/shims/combos/9.js +2 -0
- data/public/dist/js/webshims/shims/combos/97.js +1 -0
- data/public/dist/js/webshims/shims/combos/98.js +1 -0
- data/public/dist/js/webshims/shims/combos/99.js +1 -0
- data/public/dist/js/webshims/shims/details.js +1 -0
- data/public/dist/js/webshims/shims/dom-extend.js +1 -0
- data/public/dist/js/webshims/shims/es5.js +1 -0
- data/public/dist/js/webshims/shims/es6.js +1 -0
- data/public/dist/js/webshims/shims/excanvas.js +1 -0
- data/public/dist/js/webshims/shims/filereader-xhr.js +1 -0
- data/public/dist/js/webshims/shims/form-combat.js +1 -0
- data/public/dist/js/webshims/shims/form-core.js +1 -0
- data/public/dist/js/webshims/shims/form-datalist-lazy.js +1 -0
- data/public/dist/js/webshims/shims/form-datalist.js +1 -0
- data/public/dist/js/webshims/shims/form-fixrangechange.js +1 -0
- data/public/dist/js/webshims/shims/form-inputmode.js +1 -0
- data/public/dist/js/webshims/shims/form-message.js +1 -0
- data/public/dist/js/webshims/shims/form-native-extend.js +1 -0
- data/public/dist/js/webshims/shims/form-number-date-api.js +1 -0
- data/public/dist/js/webshims/shims/form-number-date-ui.js +1 -0
- data/public/dist/js/webshims/shims/form-shim-extend.js +1 -0
- data/public/dist/js/webshims/shims/form-shim-extend2.js +1 -0
- data/public/dist/js/webshims/shims/form-validation.js +1 -0
- data/public/dist/js/webshims/shims/form-validators.js +1 -0
- data/public/dist/js/webshims/shims/forms-picker.js +1 -0
- data/public/dist/js/webshims/shims/geolocation.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-ar.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-ch-CN.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-cs.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-de.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-el.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-en.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-es.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-fa.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-fr.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-he.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-hi.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-hu.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-it.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-ja.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-lt.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-nl.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-pl.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-pt-BR.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-pt-PT.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-pt.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-ru.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-sv.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-zh-CN.js +1 -0
- data/public/dist/js/webshims/shims/i18n/formcfg-zh-TW.js +1 -0
- data/public/dist/js/webshims/shims/jme/alternate-media.js +1 -0
- data/public/dist/js/webshims/shims/jme/base.js +1 -0
- data/public/dist/js/webshims/shims/jme/controls.css +1 -0
- data/public/dist/js/webshims/shims/jme/jme.eot +0 -0
- data/public/dist/js/webshims/shims/jme/jme.svg +36 -0
- data/public/dist/js/webshims/shims/jme/jme.ttf +0 -0
- data/public/dist/js/webshims/shims/jme/jme.woff +0 -0
- data/public/dist/js/webshims/shims/jme/mediacontrols-lazy.js +1 -0
- data/public/dist/js/webshims/shims/jme/mediacontrols.js +1 -0
- data/public/dist/js/webshims/shims/jme/playlist.js +1 -0
- data/public/dist/js/webshims/shims/jpicker/images/AlphaBar.png +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/Bars.png +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/Maps.png +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/NoColor.png +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/bar-opacity.png +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/map-opacity.png +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/mappoint.gif +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/picker.gif +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/preview-opacity.png +0 -0
- data/public/dist/js/webshims/shims/jpicker/images/rangearrows.gif +0 -0
- data/public/dist/js/webshims/shims/jpicker/jpicker.css +1 -0
- data/public/dist/js/webshims/shims/matchMedia.js +3 -0
- data/public/dist/js/webshims/shims/mediacapture-picker.js +1 -0
- data/public/dist/js/webshims/shims/mediacapture.js +1 -0
- data/public/dist/js/webshims/shims/mediaelement-core.js +1 -0
- data/public/dist/js/webshims/shims/mediaelement-debug.js +1 -0
- data/public/dist/js/webshims/shims/mediaelement-jaris.js +1 -0
- data/public/dist/js/webshims/shims/mediaelement-native-fix.js +1 -0
- data/public/dist/js/webshims/shims/mediaelement-yt.js +1 -0
- data/public/dist/js/webshims/shims/moxie/flash/Moxie.cdn.swf +0 -0
- data/public/dist/js/webshims/shims/moxie/flash/Moxie.min.swf +0 -0
- data/public/dist/js/webshims/shims/moxie/js/moxie-html4.js +3 -0
- data/public/dist/js/webshims/shims/moxie/js/moxie-swf.js +2 -0
- data/public/dist/js/webshims/shims/picture.js +1 -0
- data/public/dist/js/webshims/shims/plugins/jquery.ui.position.js +11 -0
- data/public/dist/js/webshims/shims/range-ui.js +1 -0
- data/public/dist/js/webshims/shims/sizzle.js +11 -0
- data/public/dist/js/webshims/shims/sticky.js +1 -0
- data/public/dist/js/webshims/shims/styles/color-picker.png +0 -0
- data/public/dist/js/webshims/shims/styles/forms-ext.css +1 -0
- data/public/dist/js/webshims/shims/styles/forms-picker.css +1 -0
- data/public/dist/js/webshims/shims/styles/progress.gif +0 -0
- data/public/dist/js/webshims/shims/styles/progress.png +0 -0
- data/public/dist/js/webshims/shims/styles/shim-ext.css +1 -0
- data/public/dist/js/webshims/shims/styles/shim.css +1 -0
- data/public/dist/js/webshims/shims/styles/transparent.png +0 -0
- data/public/dist/js/webshims/shims/styles/widget.eot +0 -0
- data/public/dist/js/webshims/shims/styles/widget.svg +12 -0
- data/public/dist/js/webshims/shims/styles/widget.ttf +0 -0
- data/public/dist/js/webshims/shims/styles/widget.woff +0 -0
- data/public/dist/js/webshims/shims/swf/JarisFLVPlayer.swf +0 -0
- data/public/dist/js/webshims/shims/swfmini-embed.js +1 -0
- data/public/dist/js/webshims/shims/swfmini.js +6 -0
- data/public/dist/js/webshims/shims/track-ui.js +1 -0
- data/public/dist/js/webshims/shims/track.js +1 -0
- data/public/dist/js/webshims/shims/url.js +1 -0
- data/public/dist/js/webshims/shims/usermedia-core.js +1 -0
- data/public/dist/js/webshims/shims/usermedia-shim.js +1 -0
- data/public/js/bootstrap.min.js +3 -8
- data/public/js/jquery-ui.min.js +6 -0
- data/public/js/jquery.min.js +4 -0
- data/public/js/jquery.t.js +4 -4
- data/public/js/sequenceserver.blast.js +20 -18
- data/public/js/sequenceserver.js +116 -74
- data/sequenceserver.gemspec +20 -16
- data/views/400.erb +2 -1
- data/views/500.erb +6 -1
- data/views/result.erb +38 -18
- data/views/search.erb +49 -32
- metadata +389 -11
- data/public/img/glyphicons-halflings-white.png +0 -0
- data/public/img/glyphicons-halflings.png +0 -0
- data/public/js/jquery-ui.js +0 -14987
- data/public/js/jquery.js +0 -5
- data/public/js/jquery.scrollspy.js +0 -74
- data/public/sequence.min.js +0 -1
data/lib/sequenceserver.rb
CHANGED
@@ -1,27 +1,22 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'English'
|
2
3
|
require 'fileutils'
|
3
4
|
require 'sinatra/base'
|
4
5
|
require 'thin'
|
5
6
|
require 'json'
|
6
7
|
|
8
|
+
require 'sequenceserver/exceptions'
|
9
|
+
require 'sequenceserver/config'
|
7
10
|
require 'sequenceserver/logger'
|
8
11
|
require 'sequenceserver/sequence'
|
9
12
|
require 'sequenceserver/database'
|
10
13
|
require 'sequenceserver/blast'
|
11
14
|
|
15
|
+
# Top level module / namespace.
|
12
16
|
module SequenceServer
|
13
|
-
|
14
17
|
# Use a fixed minimum version of BLAST+
|
15
18
|
MINIMUM_BLAST_VERSION = '2.2.30+'
|
16
19
|
|
17
|
-
# Use the following exit codes, or 1.
|
18
|
-
EXIT_BLAST_NOT_INSTALLED = 2
|
19
|
-
EXIT_BLAST_NOT_COMPATIBLE = 3
|
20
|
-
EXIT_NO_BLAST_DATABASE = 4
|
21
|
-
EXIT_BLAST_INSTALLATION_FAILED = 5
|
22
|
-
EXIT_CONFIG_FILE_NOT_FOUND = 6
|
23
|
-
EXIT_NO_SEQUENCE_DIR = 7
|
24
|
-
|
25
20
|
class << self
|
26
21
|
def environment
|
27
22
|
ENV['RACK_ENV']
|
@@ -40,80 +35,53 @@ module SequenceServer
|
|
40
35
|
end
|
41
36
|
|
42
37
|
def init(config = {})
|
43
|
-
@
|
44
|
-
@config_file = File.expand_path(config_file)
|
45
|
-
assert_file_present('config file', config_file, EXIT_CONFIG_FILE_NOT_FOUND)
|
46
|
-
|
47
|
-
@config = {
|
48
|
-
:num_threads => 1,
|
49
|
-
:port => 4567,
|
50
|
-
:host => 'localhost'
|
51
|
-
}.update(parse_config_file.merge(config))
|
52
|
-
|
53
|
-
if @config[:bin]
|
54
|
-
@config[:bin] = File.expand_path @config[:bin]
|
55
|
-
assert_dir_present 'bin dir', @config[:bin]
|
56
|
-
export_bin_dir
|
57
|
-
end
|
58
|
-
|
59
|
-
assert_blast_installed_and_compatible
|
60
|
-
|
61
|
-
assert_dir_present 'database dir', @config[:database_dir], EXIT_NO_SEQUENCE_DIR
|
62
|
-
@config[:database_dir] = File.expand_path(@config[:database_dir])
|
63
|
-
assert_blast_databases_present_in_database_dir
|
38
|
+
@config = Config.new(config)
|
64
39
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
if @config[:require]
|
72
|
-
@config[:require] = File.expand_path @config[:require]
|
73
|
-
assert_file_present 'extension file', @config[:require]
|
74
|
-
require @config[:require]
|
75
|
-
end
|
40
|
+
init_binaries
|
41
|
+
init_database
|
42
|
+
load_extension
|
43
|
+
check_num_threads
|
44
|
+
self
|
76
45
|
|
77
46
|
# We don't validate port and host settings. If SequenceServer is run
|
78
47
|
# self-hosted, bind will fail on incorrect values. If SequenceServer
|
79
48
|
# is run via Apache+Passenger, we don't need to worry.
|
80
|
-
|
81
|
-
self
|
82
49
|
end
|
83
50
|
|
84
|
-
attr_reader :
|
85
|
-
|
86
|
-
def [](key)
|
87
|
-
config[key]
|
88
|
-
end
|
51
|
+
attr_reader :config
|
89
52
|
|
90
53
|
# Run SequenceServer as a self-hosted server using Thin webserver.
|
91
54
|
def run
|
55
|
+
check_host
|
92
56
|
url = "http://#{config[:host]}:#{config[:port]}"
|
93
|
-
server = Thin::Server.new(config[:host],
|
57
|
+
server = Thin::Server.new(config[:host],
|
58
|
+
config[:port],
|
59
|
+
:signals => false) do
|
94
60
|
use Rack::CommonLogger
|
95
61
|
run SequenceServer
|
96
62
|
end
|
97
63
|
server.silent = true
|
98
64
|
server.backend.start do
|
99
|
-
puts
|
65
|
+
puts '** SequenceServer is ready.'
|
100
66
|
puts " Go to #{url} in your browser and start BLASTing!"
|
101
|
-
puts
|
67
|
+
puts ' Press CTRL+C to quit.'
|
102
68
|
[:INT, :TERM].each do |sig|
|
103
69
|
trap sig do
|
104
70
|
server.stop!
|
105
71
|
puts
|
106
|
-
puts
|
107
|
-
puts
|
108
|
-
puts
|
109
|
-
puts
|
72
|
+
puts '** Thank you for using SequenceServer :).'
|
73
|
+
puts ' Please cite: '
|
74
|
+
puts ' Priyam, Woodcroft, Rai & Wurm,'
|
75
|
+
puts ' SequenceServer (in prep).'
|
110
76
|
end
|
111
77
|
end
|
112
78
|
end
|
113
79
|
rescue
|
114
|
-
puts
|
80
|
+
puts '** Oops! There was an error.'
|
115
81
|
puts " Is SequenceServer already accessible at #{url}?"
|
116
|
-
puts
|
82
|
+
puts ' Try running SequenceServer on another port, like so:'
|
83
|
+
puts
|
84
|
+
puts ' sequenceserver -p 4570.'
|
117
85
|
end
|
118
86
|
|
119
87
|
# Rack-interface.
|
@@ -137,105 +105,105 @@ module SequenceServer
|
|
137
105
|
|
138
106
|
private
|
139
107
|
|
140
|
-
def
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
puts "*** Error in config file: #{error}."
|
154
|
-
puts " YAML is white space sensitive. Is your config file properly indented?"
|
155
|
-
exit 1
|
108
|
+
def init_binaries
|
109
|
+
if config[:bin]
|
110
|
+
config[:bin] = File.expand_path config[:bin]
|
111
|
+
unless File.exist?(config[:bin]) && File.directory?(config[:bin])
|
112
|
+
fail BIN_DIR_NOT_FOUND, config[:bin]
|
113
|
+
end
|
114
|
+
logger.debug("Will use NCBI BLAST+ at: #{config[:bin]}")
|
115
|
+
export_bin_dir
|
116
|
+
else
|
117
|
+
logger.debug('Will use NCBI BLAST+ at: $PATH')
|
118
|
+
end
|
119
|
+
|
120
|
+
assert_blast_installed_and_compatible
|
156
121
|
end
|
157
122
|
|
158
|
-
def
|
159
|
-
|
160
|
-
|
123
|
+
def init_database
|
124
|
+
fail DATABASE_DIR_NOT_SET unless config[:database_dir]
|
125
|
+
|
126
|
+
config[:database_dir] = File.expand_path(config[:database_dir])
|
127
|
+
unless File.exist?(config[:database_dir]) &&
|
128
|
+
File.directory?(config[:database_dir])
|
129
|
+
fail DATABASE_DIR_NOT_FOUND, config[:database_dir]
|
130
|
+
end
|
131
|
+
|
132
|
+
assert_blast_databases_present_in_database_dir
|
133
|
+
logger.debug("Will use BLAST+ databases at: #{config[:database_dir]}")
|
134
|
+
|
135
|
+
Database.scan_databases_dir
|
136
|
+
Database.each do |database|
|
137
|
+
logger.debug("Found #{database.type} database '#{database.title}'" \
|
138
|
+
" at '#{database.name}'")
|
161
139
|
end
|
162
140
|
end
|
163
141
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
142
|
+
def check_num_threads
|
143
|
+
num_threads = Integer(config[:num_threads])
|
144
|
+
fail NUM_THREADS_INCORRECT unless num_threads > 0
|
145
|
+
|
146
|
+
logger.debug "Will use #{num_threads} threads to run BLAST."
|
147
|
+
if num_threads > 256
|
148
|
+
logger.warn "Number of threads set at #{num_threads} is unusually high."
|
171
149
|
end
|
150
|
+
rescue
|
151
|
+
raise NUM_THREADS_INCORRECT
|
172
152
|
end
|
173
153
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
154
|
+
# Check and warn user if host is 0.0.0.0 (default).
|
155
|
+
def check_host
|
156
|
+
# rubocop:disable Style/GuardClause
|
157
|
+
if config[:host] == '0.0.0.0'
|
158
|
+
logger.warn 'Will listen on all interfaces (0.0.0.0).' \
|
159
|
+
' Consider using 127.0.0.1 (--host option).'
|
178
160
|
end
|
161
|
+
# rubocop:enable Style/GuardClause
|
179
162
|
end
|
180
163
|
|
181
|
-
|
164
|
+
def load_extension
|
165
|
+
return unless config[:require]
|
182
166
|
|
183
|
-
|
184
|
-
unless
|
185
|
-
|
186
|
-
exit EXIT_BLAST_NOT_INSTALLED
|
187
|
-
end
|
188
|
-
version = %x|blastdbcmd -version|.split[1]
|
189
|
-
unless version >= MINIMUM_BLAST_VERSION
|
190
|
-
puts "*** Your BLAST+ version #{version} is outdated."
|
191
|
-
puts " SequenceServer needs NCBI BLAST+ version #{MINIMUM_BLAST_VERSION} or higher."
|
192
|
-
exit EXIT_BLAST_NOT_COMPATIBLE
|
167
|
+
config[:require] = File.expand_path config[:require]
|
168
|
+
unless File.exist?(config[:require]) && File.file?(config[:require])
|
169
|
+
fail EXTENSION_FILE_NOT_FOUND, config[:require]
|
193
170
|
end
|
171
|
+
|
172
|
+
logger.debug("Loading extension: #{config[:require]}")
|
173
|
+
require config[:require]
|
194
174
|
end
|
195
175
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
elsif out.match(/BLAST Database error/) or not $?.success?
|
203
|
-
puts "*** Error obtaining BLAST databases."
|
204
|
-
puts " Tried: #{find_dbs_command}"
|
205
|
-
puts " Error:"
|
206
|
-
out.strip.split("\n").each do |l|
|
207
|
-
puts " #{l}"
|
208
|
-
end
|
209
|
-
puts " Please could you report this to 'https://groups.google.com/forum/#!forum/sequenceserver'?"
|
210
|
-
exit EXIT_BLAST_DATABASE_ERROR
|
211
|
-
end
|
176
|
+
# Export NCBI BLAST+ bin dir to PATH environment variable.
|
177
|
+
def export_bin_dir
|
178
|
+
bin_dir = config[:bin]
|
179
|
+
return unless bin_dir
|
180
|
+
return if ENV['PATH'].split(':').include? bin_dir
|
181
|
+
ENV['PATH'] = "#{bin_dir}:#{ENV['PATH']}"
|
212
182
|
end
|
213
183
|
|
214
|
-
def
|
215
|
-
unless
|
216
|
-
|
217
|
-
|
218
|
-
exit 1
|
219
|
-
end
|
220
|
-
if num_threads > 256
|
221
|
-
logger.warn "*** Number of threads set at #{num_threads} is unusually high."
|
222
|
-
end
|
223
|
-
rescue
|
224
|
-
puts "*** Number of threads should be a number."
|
225
|
-
exit 1
|
184
|
+
def assert_blast_installed_and_compatible
|
185
|
+
fail BLAST_NOT_INSTALLED unless command? 'blastdbcmd'
|
186
|
+
version = `blastdbcmd -version`.split[1]
|
187
|
+
fail BLAST_NOT_COMPATIBLE, version unless version >= MINIMUM_BLAST_VERSION
|
226
188
|
end
|
227
189
|
|
190
|
+
def assert_blast_databases_present_in_database_dir
|
191
|
+
cmd = "blastdbcmd -recursive -list #{config[:database_dir]}"
|
192
|
+
out = `#{cmd}`
|
193
|
+
errpat = /BLAST Database error/
|
194
|
+
fail NO_BLAST_DATABASE_FOUND, config[:database_dir] if out.empty?
|
195
|
+
fail BLAST_DATABASE_ERROR, cmd, out if out.match(errpat) ||
|
196
|
+
!$CHILD_STATUS.success?
|
197
|
+
end
|
228
198
|
|
229
199
|
# Return `true` if the given command exists and is executable.
|
230
200
|
def command?(command)
|
231
201
|
system("which #{command} > /dev/null 2>&1")
|
232
202
|
end
|
233
|
-
|
234
203
|
end
|
235
204
|
|
236
205
|
# Controller.
|
237
206
|
class App < Sinatra::Base
|
238
|
-
|
239
207
|
# See
|
240
208
|
# http://www.sinatrarb.com/configuration.html
|
241
209
|
configure do
|
@@ -254,7 +222,7 @@ module SequenceServer
|
|
254
222
|
# or http_status` methods. Error blocks errors must explicitly set http
|
255
223
|
# status, if needed, by calling `status` method.
|
256
224
|
# method.
|
257
|
-
enable
|
225
|
+
enable :dump_errors
|
258
226
|
|
259
227
|
# We don't want Sinatra do setup any loggers for us. We will use our own.
|
260
228
|
set :logging, nil
|
@@ -267,6 +235,13 @@ module SequenceServer
|
|
267
235
|
# http://www.sinatrarb.com/intro.html#Mime%20Types
|
268
236
|
configure do
|
269
237
|
mime_type :fasta, 'text/fasta'
|
238
|
+
mime_type :xml, 'text/xml'
|
239
|
+
mime_type :tsv, 'text/tsv'
|
240
|
+
end
|
241
|
+
|
242
|
+
configure :production do
|
243
|
+
set :public_folder,
|
244
|
+
lambda { File.join SequenceServer.root, 'public', 'dist' }
|
270
245
|
end
|
271
246
|
|
272
247
|
helpers do
|
@@ -274,16 +249,16 @@ module SequenceServer
|
|
274
249
|
#
|
275
250
|
# See links.rb for example of a Hash object that will be rendered.
|
276
251
|
def a(link)
|
277
|
-
return unless link[:title]
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
252
|
+
return unless link[:title] && link[:url]
|
253
|
+
a = ['<a']
|
254
|
+
a << "href=#{link[:url]}"
|
255
|
+
a << "class=\"#{link[:class]}\"" if link[:class]
|
256
|
+
a << "target=\"_blank\"" if absolute? link[:url]
|
257
|
+
a << '>'
|
258
|
+
a << "<i class=\"fa #{link[:icon]}\"></i>" if link[:icon]
|
259
|
+
a << link[:title]
|
260
|
+
a << '</a>'
|
261
|
+
a.join("\n")
|
287
262
|
end
|
288
263
|
|
289
264
|
# Is the given URI absolute? (or relative?)
|
@@ -291,19 +266,34 @@ module SequenceServer
|
|
291
266
|
URI.parse(uri).absolute?
|
292
267
|
end
|
293
268
|
|
294
|
-
#
|
295
|
-
def
|
296
|
-
|
269
|
+
# Prettify given data.
|
270
|
+
def prettify(data)
|
271
|
+
return prettify_tuple(data) if tuple? data
|
272
|
+
return prettify_float(data) if data.is_a? Float
|
273
|
+
data
|
297
274
|
end
|
298
275
|
|
299
|
-
# Formats
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
276
|
+
# Formats float as "a.bcd" or "a x b^c". The latter if float is
|
277
|
+
# scientific notation. Former otherwise.
|
278
|
+
def prettify_float(float)
|
279
|
+
float.to_s.sub(/(\d*\.\d*)e?([+-]\d*)?/) do
|
280
|
+
base = Regexp.last_match[1]
|
281
|
+
power = Regexp.last_match[2]
|
282
|
+
s = format '%.2f', base
|
283
|
+
s << " × 10<sup>#{power}</sup>" if power
|
304
284
|
s
|
305
285
|
end
|
306
286
|
end
|
287
|
+
|
288
|
+
# Formats an array of two elements as "first (last)".
|
289
|
+
def prettify_tuple(tuple)
|
290
|
+
"#{tuple.first} (#{tuple.last})"
|
291
|
+
end
|
292
|
+
|
293
|
+
# Is the given value a tuple? (array of length two).
|
294
|
+
def tuple?(data)
|
295
|
+
return true if data.is_a?(Array) && data.length == 2
|
296
|
+
end
|
307
297
|
end
|
308
298
|
|
309
299
|
# For any request that hits the app in development mode, log incoming
|
@@ -314,15 +304,20 @@ module SequenceServer
|
|
314
304
|
|
315
305
|
# Render the search form.
|
316
306
|
get '/' do
|
317
|
-
erb :search, :locals => {:databases => Database.group_by(&:type)}
|
307
|
+
erb :search, :locals => { :databases => Database.group_by(&:type) }
|
318
308
|
end
|
319
309
|
|
320
310
|
# BLAST search!
|
321
311
|
post '/' do
|
322
|
-
erb :result, :locals => {:report => BLAST.run(params)}
|
312
|
+
erb :result, :locals => { :report => BLAST.run(params) }
|
323
313
|
end
|
324
314
|
|
325
|
-
#
|
315
|
+
# @params sequence_ids: whitespace separated list of sequence ids to
|
316
|
+
# retrieve
|
317
|
+
# @params database_ids: whitespace separated list of database ids to
|
318
|
+
# retrieve the sequence from.
|
319
|
+
# @params download: whether to return raw response or initiate file
|
320
|
+
# download
|
326
321
|
#
|
327
322
|
# Use whitespace to separate entries in sequence_ids (all other chars exist
|
328
323
|
# in identifiers) and retreival_databases (we don't allow whitespace in a
|
@@ -345,18 +340,26 @@ module SequenceServer
|
|
345
340
|
{
|
346
341
|
:sequence_ids => sequence_ids,
|
347
342
|
:databases => Database[database_ids].map(&:title),
|
348
|
-
:sequences => sequences.map
|
343
|
+
:sequences => sequences.map(&:info)
|
349
344
|
}.to_json
|
350
345
|
end
|
351
346
|
end
|
352
347
|
|
348
|
+
get '/get_report/' do
|
349
|
+
ofile = BLAST.format(params)
|
350
|
+
|
351
|
+
send_file ofile[:filepath],
|
352
|
+
:filename => ofile[:filename],
|
353
|
+
:type => ofile[:type].to_sym
|
354
|
+
end
|
355
|
+
|
353
356
|
# This error block will only ever be hit if the user gives us a funny
|
354
357
|
# sequence or incorrect advanced parameter. Well, we could hit this block
|
355
358
|
# if someone is playing around with our HTTP API too.
|
356
359
|
error BLAST::ArgumentError do
|
357
360
|
status 400
|
358
361
|
error = env['sinatra.error']
|
359
|
-
erb :'400', :locals => {:error => error}
|
362
|
+
erb :'400', :locals => { :error => error }
|
360
363
|
end
|
361
364
|
|
362
365
|
# This will catch any unhandled error and some very special errors. Ideally
|
@@ -367,7 +370,7 @@ module SequenceServer
|
|
367
370
|
error Exception, BLAST::RuntimeError do
|
368
371
|
status 500
|
369
372
|
error = env['sinatra.error']
|
370
|
-
erb :'500', :locals => {:error => error}
|
373
|
+
erb :'500', :locals => { :error => error }
|
371
374
|
end
|
372
375
|
end
|
373
376
|
end
|