NGLess 1.4.0 → 1.4.1
raw patch · 12 files changed
+792/−12 lines, 12 files
Files
- ChangeLog +4/−0
- Html/index.html +86/−0
- Html/ngless.css +233/−0
- Html/nglessMapStats.html +66/−0
- Html/nglessQC.html +130/−0
- Html/perBaseQualScores.css +40/−0
- NGLess.cabal +8/−1
- NGLess/Data/Fasta.hs +1/−1
- NGLess/Interpretation/Count/RefSeqInfoVector.h +71/−0
- NGLess/Interpretation/Map.hs +8/−8
- NGLess/Version.hs +2/−2
- README.md +143/−0
ChangeLog view
@@ -1,3 +1,7 @@+Version 1.4.1 2022-06-03 by luispedro+ * Fix bug with split mapping+ * Fix packaging for hackage+ Version 1.4.0 2022-05-30 by luispedro * Add --trace argument to all modes * Update --create-reference-pack mode to newer format (previous version worked, but
+ Html/index.html view
@@ -0,0 +1,86 @@+<!DOCTYPE html>+<html lang="en">+ <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.1/angular.min.js"></script>+ <script src="https://code.angularjs.org/1.3.0-beta.1/angular-sanitize.js"></script>+ <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" rel="stylesheet">+ <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css" rel="stylesheet">++ <link href="ngless.css" rel="stylesheet">+ <title>Ngless</title>++ <body>++ <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">+ <div class="navbar-collapse">+ <ul class="nav navbar-nav">+ <li class="active"><a href="#">Home</a></li>+ <li><a href="nglessQC.html">FastQ Quality Control</a></li>+ </ul>+ </div><!--/.nav-collapse -->+ </div>+ </nav>+++ <div class="bs-docs-header" id="content">+ <div class="container">+ <h1>NGLess Log</h1>+ </div>+ </div>+ <div ng-app="myApp" ng-controller="NGlessCtrl">+ <p>Result of running script file <tt>{{output.processed.name}}</tt> at <em>{{output.processed.time}}</em>.</p>+ <div class="container">+ <div class="panel-body">+ <h2>Script</h2>+ <div ng-repeat="line in output.processed.script" style="position: relative">+ <p style="white-space: pre-wrap"><span ng-if="line[0] && line[0].info_type == 'has_QCInfo'" style="position: absolute; left: -4em"><a href="nglessQC.html#{{line[0].lno}}">QC</a> </span><span ng-if="line[0] && line[0].info_type == 'has_StatsInfo'" style="position: absolute; left: -4em"><a href="nglessMapStats.html#{{line[0].lno}}">Stats</a> </span> {{line[1]}}</p>+ </div>+ </div>+ </div>+ <div class="container">++ <h3>NGLess Output</h3>+ <style>+ .output-info { color: #000000;}+ .output-debug { color: #336633;}+ .output-result { color: #663333;}+ </style>+ <p><a ng-show="!showtime" ng-click="showtime = !showtime;">Show timestamp</a><a ng-show="showtime" ng-click="showtime = !showtime;">Hide timestamp</a>.++ <p>+ <div ng-repeat="oline in output.output">+ <span class="output-{{oline.otype}}"><strong>Line {{oline.lno}}</strong><span ng-show="showtime"> [{{oline.time}}]</span>: {{oline.message}}</span><br />+ </div>+ </div>+ </div><!-- /.container -->+++ <footer id="footer">+ <div class="container">+ <p>Happily designed by <a href="https://github.com/ngless-toolkit">Luis Pedro Coelho</a> and <a href="https://github.com/montoias">Paulo Monteiro</a>.</p>+ </div>+ </footer>+ <!-- Bootstrap core JavaScript+ ================================================== -->+ <!-- Placed at the end of the document so the pages load faster -->++ <script src="https://code.jquery.com/jquery-latest.min.js" ></script>+ <script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"></script>++ <script src="output.js"></script>++ <!-- Angular Script to load different URLs -->+ <script>+var app = angular.module('myApp', ['ngSanitize']);++app.factory('NGLessOutput', function() {+ return output;+});++function NGlessCtrl($scope, $sce, NGLessOutput){+ $scope.output = output;+}++ </script>++ </body>+</html>
+ Html/ngless.css view
@@ -0,0 +1,233 @@+.textTitle {+ padding: 80px 15px;+ text-align: center;+}++.frameFastQ {+ height: 900px;+ width: 100%; + display: block;+}++.timetext {+ float:right ;+}++.titletext {+ float: left;+}++div.panel-title {+ padding-bottom: 30px;+ padding-top: 10px;+}++.panel-default>.panel-heading {+ color: #fff;+ background-color: #E8A10C;+ border-color: #ddd;+}+++/* Sidenav for Docs+-------------------------------------------------- */++.sidenav {+ width: 228px;+ margin: 30px 0 0;+ padding: 0;+ background-color: #fff;+ -webkit-border-radius: 6px;+ -moz-border-radius: 6px;+ border-radius: 6px;+ -webkit-box-shadow: 0 1px 4px rgba(0,0,0,.065);+ -moz-box-shadow: 0 1px 4px rgba(0,0,0,.065);+ box-shadow: 0 1px 4px rgba(0,0,0,.065);+}+.sidenav > li > a {+ display: block;+ width: 190px \9;+ margin: 0 0 -1px;+ padding: 8px 14px;+ border: 1px solid #e5e5e5;+}+.sidenav > li:first-child > a {+ -webkit-border-radius: 6px 6px 0 0;+ -moz-border-radius: 6px 6px 0 0;+ border-radius: 6px 6px 0 0;+}+.sidenav > li:last-child > a {+ -webkit-border-radius: 0 0 6px 6px;+ -moz-border-radius: 0 0 6px 6px;+ border-radius: 0 0 6px 6px;+}+.sidenav > .active > a {+ position: relative;+ z-index: 2;+ padding: 9px 15px;+ border: 0;+ text-shadow: 0 1px 0 rgba(0,0,0,.15);+ -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.1), inset -1px 0 0 rgba(0,0,0,.1);+ -moz-box-shadow: inset 1px 0 0 rgba(0,0,0,.1), inset -1px 0 0 rgba(0,0,0,.1);+ box-shadow: inset 1px 0 0 rgba(0,0,0,.1), inset -1px 0 0 rgba(0,0,0,.1);+}++.bs-docs-masthead, .bs-docs-header {+ position: relative;+ padding: 30px 15px;+ color: #cdbfe3;+ text-align: center;+ text-shadow: 0 1px 0 rgba(0, 0, 0, .1);+ background-color: #53B4FF;+ background-image: -webkit-linear-gradient(top, #236DFF 0, #53B4FF 100%);+ background-image: linear-gradient(to bottom, #236DFF 0, #53B4FF 100%);+ background-repeat: repeat-x;+}+++.bs-docs-header h1 {+ color: #fff+}++@media (min-width:768px){+ .bs-docs-header {+ padding-top: 10px;+ padding-bottom: 10px;+ font-size: 16px;+ text-align: left+ }++ .bs-docs-header h1 {+ font-size: 60px;+ line-height: 1+ }+}++@media (min-width:992px){.bs-docs-header h1, .bs-docs-header p {+ margin-right: 380px+ }+}+++.navbar {+ position:relative;+ min-height:40px;+ margin:0px;+ /* Add padding: 0 */+ border:0px solid transparent;+}++#nav.affix {+ position: fixed;+ top: 70px;+ width: 100%+}++.headTemplate {+ color: #53B4FF;+}+++html,body {+ height: 100%;+ /* The html and body elements cannot have any padding or margin. */+}++/* Wrapper for page content to push down footer */+#wrap {+ min-height: 100%;+ height: auto !important;+ height: 100%;+ /* Negative indent footer by it's height */+ margin: 0 auto -60px;+}++/* Set the fixed height of the footer here */+#push,+#footer {+ height: 60px;+}++#footer {+ background-color: #f5f5f5;+ padding-top: 20px;+}++++.section-body {+ position: relative;+ padding: 30px 15px;+ color: #cdbfe3;+ text-align: center;+ text-shadow: 0 1px 0 rgba(0, 0, 0, .1);+ background-color: #fff;+ background-image: -webkit-linear-gradient(top, #fff 0, #fff 100%);+ background-image: linear-gradient(to bottom, #fff 0, #fff 100%);+ background-repeat: repeat-x;+}+++.section-body h1 {+ color: #000000+}++@media (min-width:768px){+ .section-body {+ padding-top: 60px;+ padding-bottom: 60px;+ font-size: 14px;+ text-align: center+ }++ .section-body h1 {+ font-size: 20px;+ line-height: 1+ }+}+++.sec-collapse{+ text-shadow: 0 1px 0 rgba(0, 0, 0, .1);+ background-color: #5CDBE5;+ background-image: -webkit-linear-gradient(bottom, #fff 0, #5CDBE5 100%);+ background-image: linear-gradient(to top, #fff 0, #5CDBE5 100%);+ background-repeat: repeat-x;+}++@media (min-width:768px){+ .sec-collapse {+ padding-top: 20px;+ padding-bottom: 60px;+ }++ .sec-collapse h1 {+ font-size: 20px;+ line-height: 1+ }+}++#leftcolumn {+ background-color: grey;+ font-size: 12px;+ text-align: left;+ color: white;+ width: 20%; + float:left;+}++#rightCont {+ width: 70%; + float:right;+ margin-left: 10px;+ margin-right: 50px;+}++#leftitem {+ margin-left: 6px;+ color: white;+}++#headList {+ text-align: center;+}
+ Html/nglessMapStats.html view
@@ -0,0 +1,66 @@+<!DOCTYPE html>+<html lang="en">+ <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.1/angular.min.js"></script>+ <script src="https://code.angularjs.org/1.3.0-beta.1/angular-sanitize.js">/</script>+ <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.1.6/d3.min.js"></script>+ <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.14-beta/nv.d3.js"></script>++ <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" rel="stylesheet">+ <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css" rel="stylesheet">+++ <link href="ngless.css" rel="stylesheet">+ <title>Mapping Statistics</title>+ <script src="output.js"></script>++ <body>+ <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">+ <div class="navbar-collapse">+ <ul class="nav navbar-nav">+ <li><a href="index.html">Home</a></li>+ <li><a href="nglessQC.html">FastQ Quality Control</a></li>+ </ul>+ </div><!--/.nav-collapse -->+ </div>+ </nav>+ <h1>Mapping Statistics</h1>+ <div ng-app="mapStatsApp" ng-controller="mapStatsCntrl">+ <div id="table" align="center">+ <table class="table table-bordered table-hover">+ <thead>+ <tr>+ <th>Line Number</th>+ <th>Reference</th>+ <th>Input file</th>+ <th>Total reads</th>+ <th>Total aligned</th>+ <th>Total unique</th>+ </tr>+ </thead>+ <tbody>+ <tr ng-repeat="m in mapStats">+ <td>{{m.lno}}</td>+ <td>{{m.reference}}</td>+ <td>{{m.inputFile}}</td>+ <td>{{m.totalReads}}</td>+ <td>{{m.totalAligned}}</td>+ <td>{{m.totalUnique}}</td>+ </tr>+ </tbody>+ </table>+ </div>++ <script>++var app = angular.module('mapStatsApp', []);+app.factory('mapStatsApp', function() {+ return output.mapStats;+});++function mapStatsCntrl($scope){+ $scope.mapStats = output.mapStats;+}+ </script>+ </div>+ </body>+</html>
+ Html/nglessQC.html view
@@ -0,0 +1,130 @@+<!DOCTYPE html>+<html lang="en">+ <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.1/angular.min.js"></script>+ <script src="https://code.angularjs.org/1.3.0-beta.1/angular-sanitize.js"></script>+ <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.1.6/d3.min.js"></script>+ <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.14-beta/nv.d3.js"></script>++ <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" rel="stylesheet" />+ <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css" rel="stylesheet" />++ <link href="ngless.css" rel="stylesheet" />+ <link rel="stylesheet" type="text/css" href="perBaseQualScores.css" media="screen" />++ <title>FastQ Quality Statistics</title>+ <script src="output.js"></script>++ <body>+ <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">+ <div class="navbar-collapse">+ <ul class="nav navbar-nav">+ <li><a href="index.html">Home</a></li>+ <li><a href="#">FastQ Quality Control</a></li>+ </ul>+ </div><!--/.nav-collapse -->+ </div>+ </nav>+ <div ng-app="fqStatsApp">+ <div ng-controller="FQInfoCtrl">+ <div id="table" align="center">+ <table class="table table-bordered table-hover">+ <thead>+ <tr>+ <th> </th>+ <th ng-repeat="fq in fqStats">{{fq.fileName}}</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td> %GC: </td>+ <td ng-repeat="fq in fqStats">{{fq.gcContent*100. | number : 1}}%</td>+ </tr>+ <tr>+ <td> Encoding: </td>+ <td ng-repeat="fq in fqStats">{{fq.encoding}}</td>+ </tr>+ <tr>+ <td> Number of Sequences: </td>+ <td ng-repeat="fq in fqStats">{{fq.numSeqs}}</td>+ </tr>+ <tr>+ <td> Sequence length: </td>+ <td ng-repeat="fq in fqStats">{{fq.seqLength[0]}}–{{fq.seqLength[1]}}</td>+ </tr>+ <tr>+ <td>Plot below</td>+ <td ng-repeat="fq in fqStats"><button ng-click="doPlot($index);">Plot</button></td>+ </tr>+ </tbody>+ </table>+ </div>++ <div id="offsetDiv">+ <div class='with-3d-shadow with-transitions'>+ <svg id="qualityPlot"></svg>+ </div>+ </div>++ <script>+ function convertData (data) {+ var newData = [],+ shapes = ['triangle-up', 'triangle-down'],+ tag = ['mean', 'median', 'lowerQuartile', 'upperQuartile'];++ for (var i = 0; i < tag.length; i++) {+ newData.push({+ key: tag[i],+ values: []+ });++ for (var j = 0; j < data.length; j++) {+ newData[i].values.push({+ x: j,+ y: data[j][tag[i]],+ shape: shapes[i % 2]+ });+ }+ }+ return newData;+ }+ var chart = nv.models.lineChart()+ .showYAxis(true)+ .showXAxis(true)+ .useVoronoi(false)+ .color(d3.scale.category10().range())+ .transitionDuration(300)+ ;++ chart.xAxis.tickFormat(d3.format('1'));+ chart.yAxis.tickFormat(d3.format('.02f'));+ chart.tooltipContent(function(key) {+ return '<h4>' + key + '</h4>';+ });+++ nv.utils.windowResize(chart.update);++ chart.dispatch.on('stateChange', function(e) { ('New State:', JSON.stringify(e)); });++ var app = angular.module('fqStatsApp', []);+ app.factory('fqStats', function() {+ return output.fqStats;+ });++ function FQInfoCtrl($scope, fqStats){+ $scope.fqStats = fqStats;+ $scope.doPlot = function (index) {+ d3.select('#qualityPlot')+ .datum(convertData(fqStats[index].perBaseQ))+ .call(chart);+ }+ }++ </script>++ </div>+ </div>+++ </body>+</html>
+ Html/perBaseQualScores.css view
@@ -0,0 +1,40 @@++#table {+ position: relative;+ top: 30px;+}++body {+ overflow-y:scroll;+ margin: 0;+ padding: 0;+}++svg {+ overflow: hidden;+}++div {+ border: 0;+ margin: 0;+}+++#offsetDiv {+ margin-left: 100px;+ margin-top: 100px;+ margin-right: 100px;+}+++.nv-legendWrap {+ margin-bottom: 300px;+}+++#qualityPlot {+ margin: 0;+ height: 500px;+ min-width: 800px;+}+
NGLess.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: NGLess-version: 1.4.0+version: 1.4.1 synopsis: NGLess implements ngless, a DSL for processing sequencing data description: NGLess implements a domain-specific language for processing next generation data, particularly metagenomics. category: Domain Specific Language@@ -17,7 +17,14 @@ license-file: COPYING build-type: Simple extra-source-files:+ README.md ChangeLog+ Html/index.html+ Html/ngless.css+ Html/nglessMapStats.html+ Html/nglessQC.html+ Html/perBaseQualScores.css+ NGLess/Interpretation/Count/RefSeqInfoVector.h source-repository head type: git
NGLess/Data/Fasta.hs view
@@ -49,7 +49,7 @@ getdata !n header toks = C.await >>= \case Nothing -> C.yield $ FastaSeq header (B.concat $ reverse toks) Just (ByteLine next)- | B.null next -> throwDataError ("Unexpected empty string at line " ++ show (n+1) ++ " (expected header line).")+ | B.null next -> getdata (n+1) header toks | B.head next == greaterThanSign -> do C.yield $ FastaSeq header (B.concat $ reverse toks) getdata (n+1) (B.drop 1 next) []
+ NGLess/Interpretation/Count/RefSeqInfoVector.h view
@@ -0,0 +1,71 @@+#include <vector>+#include <string>+#include <cstring>+#include <algorithm>++const unsigned block_size = 8192 - 64; // 64 is for padding+struct PoolC {+ PoolC():free_(0) { }+ ~PoolC() {+ for (std::vector<void*>::iterator it = data_.begin(), past = data_.end(); it != past; ++it) {+ operator delete(*it);+ }+ }+ const char* strdup(const char* input) {+ const unsigned int len = std::strlen(input) + 1;+ if (len > block_size) {+ char* n = static_cast<char*>(operator new(len));+ std::strcpy(n, input);+ data_.push_back(n);+ free_ = 0;+ return n;+ }+ if (len > free_) {+ data_.push_back(operator new(block_size));+ free_ = block_size;+ }+ char* r = static_cast<char*>(data_.back());+ r += block_size - free_;+ std::strcpy(r, input);+ free_ -= len;+ return r;+ }+ private:++ std::vector<void*> data_;+ size_t free_;+};+++struct RefSeqInfo {+ RefSeqInfo(const char* s, double v)+ :str(s)+ ,val(v) { }+ bool operator <(const RefSeqInfo& rhs) const { return strcmp(str, rhs.str) < 0; }+ const char* str;+ double val;+};+++struct RefSeqInfoVector {+ RefSeqInfoVector() { }+ ~RefSeqInfoVector() { }+ void insert(std::string f, double v) {+ data_.push_back(RefSeqInfo(pool_.strdup(f.c_str()), v));+ }+ RefSeqInfo& at(int ix) { return data_.at(ix); }+ int find(const char* f) {+ std::vector<RefSeqInfo>::const_iterator it = std::lower_bound(data_.begin(), data_.end(), RefSeqInfo(f, 0));+ if (it == data_.end() || strcmp(it->str, f)) { return -1; }+ return it - data_.begin();+ }+ void sort() { std::sort(data_.begin(), data_.end()); }+ unsigned size() const { return data_.size(); }+ std::vector<RefSeqInfo> data_;+ PoolC pool_;+};++extern "C" {+ void rsiv_free(void* p) { delete static_cast<RefSeqInfoVector*>(p); }+}+
NGLess/Interpretation/Map.hs view
@@ -1,4 +1,4 @@-{- Copyright 2013-2019 NGLess Authors+{- Copyright 2013-2022 NGLess Authors - License: MIT -} {-# LANGUAGE FlexibleContexts #-}@@ -24,7 +24,6 @@ import qualified Data.Conduit.Algorithms.Async as CAlg import Data.Conduit ((.|)) import Data.Conduit.Algorithms.Utils (awaitJust)-import Data.Conduit.Algorithms.Async (conduitPossiblyCompressedFile) import Control.Monad.Extra (unlessM) import Data.List (sort) @@ -142,6 +141,7 @@ forM_ blocks (ensureIndexExists 0 mapper) return blocks +ensureSplitsExist :: Int -> FilePath -> NGLessIO [FilePath] ensureSplitsExist blockSize fafile = do fafile' <- getIndexOutput False fafile let ofafile = FilePath.takeDirectory fafile' </> FilePath.takeBaseName fafile <.> "splits_" ++ show blockSize ++ "m"@@ -189,12 +189,12 @@ , maxAge = 36 * 3000 , whenExistsStrategy = IfLockedRetry { nrLockRetries = 120, timeBetweenRetries = 60 } , mtimeUpdate = True- } $ C.runConduit $- conduitPossiblyCompressedFile ifile- .| faConduit- .| splitWriter+ } $+ CAlg.withPossiblyCompressedFile ifile $ \ic ->+ C.runConduit (ic .| faConduit .| splitWriter) where maxBPS = 1000 * 1000 * megaBPS+ splitWriter :: C.ConduitT FastaSeq C.Void NGLessIO [FilePath] splitWriter = splitWriter' [] (0 :: Int) splitWriter' fs n = do let f = ofileBase ++ "." ++ show n ++ ".fna"@@ -314,13 +314,13 @@ mergeSamFiles inputs = do lift $ outputListLno' TraceOutput ["Merging SAM files: ", show inputs] forM_ inputs $ \f ->- CB.sourceFile f+ CAlg.conduitPossiblyCompressedFile f .| linesC .| readSamHeaders -- This is sub-optimal as we reparse the file. -- There are also obvious opportunities to make this code take advantage of parallelism C.sequenceSources- [CB.sourceFile f+ [CAlg.conduitPossiblyCompressedFile f .| linesVC 4096 .| readSamGroupsC' 1 True .| CC.concat -- TODO: Remove this and adapt `mergeSAMGroups` to work directly on vectors
NGLess/Version.hs view
@@ -17,10 +17,10 @@ versionStr = showVersion version versionStrLong :: String-versionStrLong = "1.4.0"+versionStrLong = "1.4.1" dateStr :: String-dateStr = "May 30 2022"+dateStr = "June 3 2022" embeddedStr :: String #ifdef NO_EMBED_SAMTOOLS_BWA
+ README.md view
@@ -0,0 +1,143 @@+# NGLess: NGS Processing with Less Work++ Ngless is a domain-specific language for+NGS (next-generation sequencing data) processing.++[](https://travis-ci.com/ngless-toolkit/ngless)+[](https://raw.githubusercontent.com/hyperium/hyper/master/LICENSE)+[](https://anaconda.org/bioconda/ngless)+[](https://anaconda.org/bioconda/ngless)+[](https://doi.org/10.1186/s40168-019-0684-8)+[](https://gitter.im/ngless-toolkit)+++For questions and discussions, please use the [ngless mailing+list](https://groups.google.com/forum/#!forum/ngless).++If you are using NGLess, please cite:++> _NG-meta-profiler: fast processing of metagenomes using NGLess, a+> domain-specific language_ by Luis Pedro Coelho, Renato Alves, Paulo Monteiro,+> Jaime Huerta-Cepas, Ana Teresa Freitas, Peer Bork, Microbiome (2019)+> [https://doi.org/10.1186/s40168-019-0684-8](https://doi.org/10.1186/s40168-019-0684-8)++++## Example++ ngless "1.4"+ input = fastq(['ctrl1.fq','ctrl2.fq','stim1.fq','stim2.fq'])+ input = preprocess(input) using |read|:+ read = read[5:]+ read = substrim(read, min_quality=26)+ if len(read) < 31:+ discard++ mapped = map(input,+ reference='hg19')+ write(count(mapped, features=['gene']),+ ofile='gene_counts.csv',+ format={csv})++## Installing++See the [install documentation](https://ngless.embl.de/install.html) for more+information.++### Bioconda++The recommended way to install NGLess is through+[bioconda](https://bioconda.github.io):++ conda install -c bioconda ngless ++### Docker++Alternatively, a docker container with NGLess is available at+[docker hub](https://hub.docker.com/r/nglesstoolkit/ngless):++ docker run -v $PWD:/workdir -w /workdir -it nglesstoolkit/ngless:1.4.0 ngless --version++Adapt the mount flags (``-v``) as needed.++### Linux++You can download a [statically linked version of NGless+1.4.0](https://github.com/ngless-toolkit/ngless/releases/download/v1.4.0/NGLess-v1.4.0-Linux-static-full)++This should work across a wide range of Linux versions (please+[report](https://github.com/ngless-toolkit/ngless/issues) any issues you encounter):++ curl -L -O https://github.com/ngless-toolkit/ngless/releases/download/v1.4.0/NGLess-v1.4.0-Linux-static-full+ chmod +x NGLess-v1.4.0-Linux-static-full+ ./NGLess-v1.4.0-Linux-static-full++This downloaded file bundles bwa, samtools and megahit (also statically linked).++### From Source++Installing/compiling from source is also possible. Clone+[https://github.com/ngless-toolkit/ngless](https://github.com/ngless-toolkit/ngless)++#### Dependencies++The simplest way to get an environment with all the dependencies is to use conda:++ conda create -n ngless+ conda activate ngless+ conda config --add channels conda-forge+ conda install stack cairo bzip2 gmp zlib perl wget xz pkg-config make++You should have `gcc` installed (or another C-compiler).++The following sequence of commands should download and build the software++ git clone https://github.com/ngless-toolkit/ngless+ cd ngless+ stack setup+ make++To install, you can use the following command (replace `<PREFIX>` with+the directory where you wish to install, default is `/usr/local`):++ make make++## Running Sample Test Scripts on Local Machine++For developers who have successfully compiled and installed NGless, running the+test scripts in the `tests` folder would be the next line of action to have the+output of sample test cases.++ cd tests++Once in the `test` directory, select any of the test folders to run NGless.++For example, here we would run the `regression-fqgz` test:++ cd regression-fqgz+ ngless ungzip.ngl++After running this script open the newly generated folder `ungzip.ngl.output_ngless` and view the template in the **index.html** file.++For developers who have done this much more datasets for testing purposes can be referenced and used by reading these documentation links:+**[Human Gut Metagenomics Functional & Taxonomic Profiling](https://ngless.embl.de/tutorial-gut-metagenomics.html#)**+**[Ocean Metagenomics Functional Profiling](https://ngless.embl.de/tutorial-ocean-metagenomics.html)**+**[Ocean Metagenomics Assembly and Gene Prediction](https://ngless.embl.de/tutorial-assembly-gp.html)**+++## More information++- [Full documentation](https://ngless.embl.de/)+- [Frequently Asked Questions (FAQ)](https://ngless.embl.de/faq.html)+- [ngless mailing list](https://groups.google.com/forum/#!forum/ngless)+- [What's new log](https://ngless.embl.de/whatsnew.html)+- [NGless 1.4.0 Release Documentation](https://ngless.embl.de/whatsnew.html#version-1-4-0)++## Authors++- [Luis Pedro Coelho](https://luispedro.org) (email: [luispedro@big-data-biology.org](mailto:luispedro@big-data-biology.org)) (on twitter: [@luispedrocoelho](https://twitter.com/luispedrocoelho))+- Paulo Monteiro+- Renato Alves+- [Ana Teresa Freitas](https://web.tecnico.ulisboa.pt/ana.freitas/)+- Peer Bork+