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
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
# Define Config class.
|
4
|
+
module SequenceServer
|
5
|
+
# Capture our configuration system.
|
6
|
+
class Config
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators SequenceServer, :logger
|
10
|
+
|
11
|
+
def initialize(data = {})
|
12
|
+
@data = normalize data
|
13
|
+
@config_file = @data.delete(:config_file) || default_config_file
|
14
|
+
@config_file = File.expand_path(@config_file)
|
15
|
+
@data = parse_config_file.update @data
|
16
|
+
@data = defaults.update @data
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :data, :config_file
|
20
|
+
|
21
|
+
# Get.
|
22
|
+
def [](key)
|
23
|
+
data[key]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Set.
|
27
|
+
def []=(key, value)
|
28
|
+
data[key] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
# Exists?
|
32
|
+
def include?(key)
|
33
|
+
data.include? key
|
34
|
+
end
|
35
|
+
|
36
|
+
# Write config data to config file.
|
37
|
+
def write_config_file
|
38
|
+
return unless config_file
|
39
|
+
File.open(config_file, 'w') do |f|
|
40
|
+
f.puts(data.delete_if { |_, v| v.nil? }.to_yaml)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Symbolizes keys. Changes `database` key to `database_dir`.
|
47
|
+
def normalize(data)
|
48
|
+
return {} unless data
|
49
|
+
|
50
|
+
# Symbolize keys.
|
51
|
+
data = Hash[data.map { |k, v| [k.to_sym, v] }]
|
52
|
+
|
53
|
+
# The newer config file version replaces the older database key with
|
54
|
+
# database_dir for correctness. Let's honour the old version as well.
|
55
|
+
if data[:database]
|
56
|
+
database_dir = data.delete(:database)
|
57
|
+
data[:database_dir] ||= database_dir
|
58
|
+
end
|
59
|
+
|
60
|
+
data
|
61
|
+
end
|
62
|
+
|
63
|
+
# Parses and returns data from config_file if it exists. Returns {}
|
64
|
+
# otherwise.
|
65
|
+
def parse_config_file
|
66
|
+
unless file? config_file
|
67
|
+
logger.debug "Configuration file not found: #{config_file}"
|
68
|
+
return {}
|
69
|
+
end
|
70
|
+
|
71
|
+
logger.debug "Reading configuration file: #{config_file}."
|
72
|
+
normalize YAML.load_file(config_file)
|
73
|
+
rescue => error
|
74
|
+
raise CONFIG_FILE_ERROR.new(config_file, error)
|
75
|
+
end
|
76
|
+
|
77
|
+
def file?(file)
|
78
|
+
file && File.exist?(file) && File.file?(file)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Default configuration data.
|
82
|
+
def defaults
|
83
|
+
{
|
84
|
+
:num_threads => 1,
|
85
|
+
:port => 4567,
|
86
|
+
:host => '0.0.0.0'
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def default_config_file
|
91
|
+
'~/.sequenceserver.conf'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -4,24 +4,45 @@ require 'forwardable'
|
|
4
4
|
|
5
5
|
require 'sequenceserver/sequence'
|
6
6
|
|
7
|
+
# Define Database class.
|
7
8
|
module SequenceServer
|
8
|
-
|
9
9
|
# Captures a directory containing FASTA files and BLAST databases.
|
10
10
|
#
|
11
11
|
# Formatting a FASTA for use with BLAST+ will create 3 or 6 files,
|
12
12
|
# collectively referred to as a BLAST database.
|
13
13
|
#
|
14
|
-
# It is important that formatted BLAST database files have the same dirname
|
15
|
-
# basename as the source FASTA for SequenceServer to be able to tell
|
16
|
-
# FASTA from unformatted. And that FASTA files be formatted with
|
17
|
-
# option of `makeblastdb` for sequence retrieval to work.
|
14
|
+
# It is important that formatted BLAST database files have the same dirname
|
15
|
+
# and basename as the source FASTA for SequenceServer to be able to tell
|
16
|
+
# formatted FASTA from unformatted. And that FASTA files be formatted with
|
17
|
+
# `parse_seqids` option of `makeblastdb` for sequence retrieval to work.
|
18
18
|
#
|
19
19
|
# SequenceServer will always place BLAST database files alongside input FASTA,
|
20
20
|
# and use `parse_seqids` option of `makeblastdb` to format databases.
|
21
|
-
|
21
|
+
Database = Struct.new(:name, :title, :type, :nsequences, :ncharacters,
|
22
|
+
:updated_on) do
|
23
|
+
def initialize(*args)
|
24
|
+
args[2].downcase! # database type
|
25
|
+
args.each(&:freeze)
|
26
|
+
super
|
22
27
|
|
23
|
-
|
28
|
+
@id = Digest::MD5.hexdigest args.first
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :id
|
32
|
+
|
33
|
+
def include?(accession)
|
34
|
+
out = `blastdbcmd -entry '#{accession}' -db #{name} 2> /dev/null`
|
35
|
+
!out.empty?
|
36
|
+
end
|
24
37
|
|
38
|
+
def to_s
|
39
|
+
"#{type}: #{title} #{name}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Model Database's eigenclass as a collection of Database objects.
|
44
|
+
class Database
|
45
|
+
class << self
|
25
46
|
include Enumerable
|
26
47
|
|
27
48
|
extend Forwardable
|
@@ -68,10 +89,17 @@ module SequenceServer
|
|
68
89
|
all.first
|
69
90
|
end
|
70
91
|
|
92
|
+
# Intended to be used only for testing.
|
93
|
+
def clear
|
94
|
+
collection.clear
|
95
|
+
end
|
96
|
+
|
71
97
|
# Recurisvely scan `database_dir` for blast databases.
|
72
98
|
def scan_databases_dir
|
73
99
|
database_dir = config[:database_dir]
|
74
|
-
|
100
|
+
cmd = "blastdbcmd -recursive -list #{database_dir}" \
|
101
|
+
' -list_outfmt "%f %t %p %n %l %d" 2>&1'
|
102
|
+
list = `#{cmd}`
|
75
103
|
list.each_line do |line|
|
76
104
|
name = line.split(' ')[0]
|
77
105
|
next if multipart_database_name?(name)
|
@@ -82,13 +110,13 @@ module SequenceServer
|
|
82
110
|
# Recursively scan `database_dir` for un-formatted FASTA and format them
|
83
111
|
# for use with BLAST+.
|
84
112
|
def make_blast_databases
|
85
|
-
unformatted_fastas.
|
113
|
+
unformatted_fastas.select do |file, sequence_type|
|
86
114
|
make_blast_database(file, sequence_type)
|
87
115
|
end
|
88
116
|
end
|
89
117
|
|
90
|
-
# Returns an Array of FASTA files that may require formatting, and the
|
91
|
-
# of sequence contained in each FASTA.
|
118
|
+
# Returns an Array of FASTA files that may require formatting, and the
|
119
|
+
# type of sequence contained in each FASTA.
|
92
120
|
#
|
93
121
|
# > unformatted_fastas
|
94
122
|
# => [['/foo/bar.fasta', :nulceotide], ...]
|
@@ -96,13 +124,12 @@ module SequenceServer
|
|
96
124
|
list = []
|
97
125
|
database_dir = config[:database_dir]
|
98
126
|
Find.find database_dir do |file|
|
99
|
-
next if File.directory?
|
127
|
+
next if File.directory? file
|
100
128
|
next if Database.include? file
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
129
|
+
next unless probably_fasta? file
|
130
|
+
sequence_type = guess_sequence_type_in_fasta file
|
131
|
+
if [:protein, :nucleotide].include?(sequence_type)
|
132
|
+
list << [file, sequence_type]
|
106
133
|
end
|
107
134
|
end
|
108
135
|
list
|
@@ -110,24 +137,46 @@ module SequenceServer
|
|
110
137
|
|
111
138
|
# Create BLAST database, given FASTA file and sequence type in FASTA file.
|
112
139
|
def make_blast_database(file, type)
|
140
|
+
return unless make_blast_database? file, type
|
141
|
+
title = get_database_title(file)
|
142
|
+
_make_blast_database(file, type, title)
|
143
|
+
end
|
144
|
+
|
145
|
+
def _make_blast_database(file, type, title, quiet = false)
|
146
|
+
cmd = 'makeblastdb -parse_seqids -hash_index ' \
|
147
|
+
"-in #{file} -dbtype #{type.to_s.slice(0, 4)} -title '#{title}'"
|
148
|
+
cmd << ' &> /dev/null' if quiet
|
149
|
+
system cmd
|
150
|
+
end
|
151
|
+
|
152
|
+
# Show file path and guessed sequence type to the user and obtain a y/n
|
153
|
+
# response.
|
154
|
+
#
|
155
|
+
# Returns true if the user entered anything but 'n' or 'N'.
|
156
|
+
def make_blast_database?(file, type)
|
157
|
+
puts
|
158
|
+
puts
|
113
159
|
puts "FASTA file: #{file}"
|
114
160
|
puts "FASTA type: #{type}"
|
161
|
+
print 'Proceed? [y/n] (Default: y): '
|
115
162
|
|
116
|
-
print "Proceed? [y/n] (Default: y): "
|
117
163
|
response = STDIN.gets.to_s.strip
|
164
|
+
!response.match(/n/i)
|
165
|
+
end
|
118
166
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
167
|
+
# Generate a title for the given database and show it to the user for
|
168
|
+
# confirmation.
|
169
|
+
#
|
170
|
+
# Returns user input if any. Auto-generated title otherwise.
|
171
|
+
def get_database_title(path)
|
172
|
+
default = make_db_title(File.basename(path))
|
173
|
+
print "Enter a database title or will use '#{default}': "
|
174
|
+
from_user = STDIN.gets.to_s
|
175
|
+
from_user.strip.empty? && default || from_user
|
128
176
|
end
|
129
177
|
|
130
|
-
# Returns true if the database name appears to be a multi-part database
|
178
|
+
# Returns true if the database name appears to be a multi-part database
|
179
|
+
# name.
|
131
180
|
#
|
132
181
|
# e.g.
|
133
182
|
# /home/ben/pd.ben/sequenceserver/db/nr.00 => yes
|
@@ -166,30 +215,21 @@ module SequenceServer
|
|
166
215
|
# NOTE: 2^15 == 32786. Approximately 546 lines, assuming 60 characters on
|
167
216
|
# each line.
|
168
217
|
def guess_sequence_type_in_fasta(file)
|
169
|
-
|
170
|
-
|
171
|
-
sequence_types =
|
218
|
+
sequences = sample_sequences(file)
|
219
|
+
sequence_types = sequences.map { |seq| Sequence.guess_type(seq) }
|
220
|
+
sequence_types = sequence_types.uniq.compact
|
172
221
|
(sequence_types.length == 1) && sequence_types.first
|
173
222
|
end
|
174
|
-
end
|
175
223
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
def include?(accession)
|
187
|
-
out = `blastdbcmd -entry '#{accession}' -db #{name} 2> /dev/null`
|
188
|
-
not out.empty?
|
189
|
-
end
|
190
|
-
|
191
|
-
def to_s
|
192
|
-
"#{type}: #{title} #{name}"
|
224
|
+
# Read first 32768 characters of the file. Split on fasta def line
|
225
|
+
# pattern and return.
|
226
|
+
#
|
227
|
+
# If the given file is FASTA, returns Array of as many different
|
228
|
+
# sequences in the portion of the file read. Returns the portion
|
229
|
+
# of the file read wrapped in an Array otherwise.
|
230
|
+
def sample_sequences(file)
|
231
|
+
File.read(file, 32_768).split(/^>.+$/).delete_if(&:empty?)
|
232
|
+
end
|
193
233
|
end
|
194
234
|
end
|
195
235
|
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# This file defines all possible exceptions that can be thrown by
|
2
|
+
# SequenceServer on startup.
|
3
|
+
#
|
4
|
+
# Exceptions only ever inform another entity (downstream code or users) of an
|
5
|
+
# issue. Exceptions may or may not be recoverable.
|
6
|
+
#
|
7
|
+
# Error classes should be seen as: the error code (class name), human readable
|
8
|
+
# message (to_s method), and necessary attributes to act on the error.
|
9
|
+
#
|
10
|
+
# We define as many error classes as needed to be precise about the issue, thus
|
11
|
+
# making it easy for downstream code (bin/sequenceserver or config.ru) to act
|
12
|
+
# on them.
|
13
|
+
|
14
|
+
module SequenceServer
|
15
|
+
# Error in config file.
|
16
|
+
class CONFIG_FILE_ERROR < StandardError
|
17
|
+
def initialize(ent, err)
|
18
|
+
@ent = ent
|
19
|
+
@err = err
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :ent, :err
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
<<MSG
|
26
|
+
Error in config file: #{ent}.
|
27
|
+
#{err}
|
28
|
+
MSG
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
## ENOENT ##
|
33
|
+
|
34
|
+
# Name borrowed from standard Errno::ENOENT, this class serves as a template
|
35
|
+
# for defining errors that mean "expected to find <entity> at <path>, but
|
36
|
+
# didn't".
|
37
|
+
#
|
38
|
+
# ENOENT is raised if and only if an entity was set, either using CLI or
|
39
|
+
# config file. For instance, it's compulsory to set database_dir. But ENOENT
|
40
|
+
# is not raised if database_dir is not set. ENOENT is raised if database_dir
|
41
|
+
# was set, but does not exist.
|
42
|
+
class ENOENT < StandardError
|
43
|
+
def initialize(des, ent)
|
44
|
+
@des = des
|
45
|
+
@ent = ent
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_reader :des, :ent
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
"Could not find #{des}: #{ent}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Raised if bin dir set, but does not exist.
|
56
|
+
class BIN_DIR_NOT_FOUND < ENOENT
|
57
|
+
def initialize(ent)
|
58
|
+
super 'bin dir', ent
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Raised if database dir set, but does not exist.
|
63
|
+
class DATABASE_DIR_NOT_FOUND < ENOENT
|
64
|
+
def initialize(ent)
|
65
|
+
super 'database dir', ent
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Raised if extension file set, but does not exist.
|
70
|
+
class EXTENSION_FILE_NOT_FOUND < ENOENT
|
71
|
+
def initialize(ent)
|
72
|
+
super 'extension file', ent
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
## NUM THREADS ##
|
77
|
+
|
78
|
+
# Raised if num_threads set by the user is incorrect.
|
79
|
+
class NUM_THREADS_INCORRECT < StandardError
|
80
|
+
def to_s
|
81
|
+
'Number of threads should be a number greater than or equal to 1.'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
## BLAST NOT INSTALLED OR NOT COMPATIBLE ##
|
86
|
+
|
87
|
+
# Raised if SequenceServer could not locate NCBI BLAST+ installation on
|
88
|
+
# user's system.
|
89
|
+
class BLAST_NOT_INSTALLED < StandardError
|
90
|
+
def to_s
|
91
|
+
'Could not locate BLAST+ binaries.'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Raised if SequenceServer determined NCBI BLAST+ present on the user's
|
96
|
+
# system but not meeting SequenceServer's minimum version requirement.
|
97
|
+
class BLAST_NOT_COMPATIBLE < StandardError
|
98
|
+
def initialize(version)
|
99
|
+
@version = version
|
100
|
+
end
|
101
|
+
|
102
|
+
attr_reader :version
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
<<MSG
|
106
|
+
Your BLAST+ version #{version} is outdated.
|
107
|
+
SequenceServer needs NCBI BLAST+ version #{MINIMUM_BLAST_VERSION} or higher.
|
108
|
+
MSG
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
## BLAST+ DATABASE RELATED ##
|
113
|
+
|
114
|
+
# Raised if 'database_dir' not set.
|
115
|
+
class DATABASE_DIR_NOT_SET < StandardError
|
116
|
+
def to_s
|
117
|
+
'Database dir not set.'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Raised if not even one BLAST+ database was found in database_dir.
|
122
|
+
class NO_BLAST_DATABASE_FOUND < StandardError
|
123
|
+
def initialize(database_dir)
|
124
|
+
@database_dir = database_dir
|
125
|
+
end
|
126
|
+
|
127
|
+
attr_reader :database_dir
|
128
|
+
|
129
|
+
def to_s
|
130
|
+
"Could not find BLAST+ databases in: #{database_dir}."
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Raised if there was an error determining BLAST+ databases in database_dir.
|
135
|
+
class BLAST_DATABASE_ERROR
|
136
|
+
def initialize(cmd, out)
|
137
|
+
@cmd = cmd
|
138
|
+
@out = out
|
139
|
+
end
|
140
|
+
|
141
|
+
attr_reader :cmd, :out
|
142
|
+
|
143
|
+
def to_s
|
144
|
+
<<MSG
|
145
|
+
Error obtaining BLAST databases.
|
146
|
+
Tried: #{cmd}
|
147
|
+
Error:
|
148
|
+
#{out.strip}
|
149
|
+
|
150
|
+
Please could you report this to 'https://groups.google.com/forum/#!forum/sequenceserver'?
|
151
|
+
MSG
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|