Thomas 3 năm trước cách đây
mục cha
commit
eda7cfcb0a
9 tập tin đã thay đổi với 299 bổ sung23 xóa
  1. 1 0
      .gitignore
  2. 2 0
      dist/index.d.ts
  3. 119 0
      dist/index.js
  4. 0 20
      index.js
  5. 94 0
      index.ts
  6. 51 0
      package-lock.json
  7. 8 3
      package.json
  8. 11 0
      tsconfig.json
  9. 13 0
      yarn.lock

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+node_modules

+ 2 - 0
dist/index.d.ts

@@ -0,0 +1,2 @@
+declare const asyncBwaMem: (refPath: string, R1: string | Array<string>, R2: string | Array<string>, runName: string, libName: string, output_dir: string, onData: Function, options?: any) => Promise<string[]>;
+export default asyncBwaMem;

+ 119 - 0
dist/index.js

@@ -0,0 +1,119 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
+    });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+    function verb(n) { return function (v) { return step([n, v]); }; }
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (_) try {
+            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+            if (y = 0, t) op = [op[0] & 2, t.value];
+            switch (op[0]) {
+                case 0: case 1: t = op; break;
+                case 4: _.label++; return { value: op[1], done: false };
+                case 5: _.label++; y = op[1]; op = [0]; continue;
+                case 7: op = _.ops.pop(); _.trys.pop(); continue;
+                default:
+                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+                    if (t[2]) _.ops.pop();
+                    _.trys.pop(); continue;
+            }
+            op = body.call(thisArg, _);
+        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+    }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+    return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var child_process_1 = require("child_process");
+var fs_1 = __importDefault(require("fs"));
+var path_1 = __importDefault(require("path"));
+var async_exec = function (prog, args, onData) {
+    return new Promise(function (resolve, reject) {
+        var child = (0, child_process_1.spawn)(prog, args, { shell: true });
+        child.stdout.on('data', function (data) { return onData(data.toString().trim()); });
+        child.stderr.on('data', function (data) { return onData(data.toString().trim()); });
+        child.on('error', function (err) { return reject(err); });
+        child.on('exit', function (code) { return resolve(code); });
+    });
+};
+var asyncBwaMem = function (refPath, R1, R2, runName, libName, output_dir, onData, options) {
+    if (typeof options === 'undefined')
+        options = {};
+    var refName = path_1.default.parse(refPath).name;
+    var bwa = 'bwa';
+    var samblaster = 'samblaster';
+    var samtools = 'samtools';
+    var sambamba = 'sambamba';
+    var R1_arr = Array.isArray(R1) ? R1.join(' ') : R1;
+    var R2_arr = Array.isArray(R2) ? R2.join(' ') : R2;
+    var R1_kitty = R1_arr.slice(-2) === 'gz' ? 'zcat' : 'cat';
+    var R2_kitty = R2_arr.slice(-2) === 'gz' ? 'zcat' : 'cat';
+    var R1_in = "'< ".concat(R1_kitty, " ").concat(R1_arr, "'");
+    var R2_in = "'< ".concat(R2_kitty, " ").concat(R2_arr, "'");
+    var discordantFile = path_1.default.join(output_dir, "bwa_mem_discordants_on_".concat(refName, ".sam"));
+    var splitterFile = path_1.default.join(output_dir, "bwa_mem_splitters_on_".concat(refName, ".sam"));
+    var unmappedFile = path_1.default.join(output_dir, "bwa_mem_unmapped_on_".concat(refName, ".fq"));
+    var bam = path_1.default.join(output_dir, "bwa_mem_properly_on_".concat(refName, ".bam"));
+    var bamSorted = path_1.default.join(output_dir, "bwa_mem_properly_on_".concat(refName, ".sorted.bam"));
+    return new Promise(function (resolve, reject) { return __awaiter(void 0, void 0, void 0, function () {
+        var code, code_sort, err_1;
+        return __generator(this, function (_a) {
+            switch (_a.label) {
+                case 0:
+                    _a.trys.push([0, 3, , 4]);
+                    return [4 /*yield*/, async_exec(bwa, ['mem',
+                            '-t', String(require('os').cpus().length),
+                            '-R', "\"@RG\\tPL:Illumina\\tID:".concat(+(new Date), "\\tSM:").concat(runName, "\\tLB:").concat(libName, "\""), refPath, R1_in, R2_in,
+                            '|',
+                            samblaster,
+                            '--addMateTags',
+                            '-a',
+                            '-e',
+                            '-d', discordantFile,
+                            '-s', splitterFile,
+                            '-u', unmappedFile,
+                            '|',
+                            samtools,
+                            'view',
+                            '-b',
+                            '-',
+                            '>',
+                            bam], function (message) { return onData('[BWA-MEM] ' + message); })];
+                case 1:
+                    code = _a.sent();
+                    onData('[BWA-MEM][EXIT CODE] ' + code);
+                    return [4 /*yield*/, async_exec(sambamba, ['sort',
+                            '-t', String(require('os').cpus().length),
+                            bam
+                        ], function (message) { return onData('[SAMBAMBA-SORT] ' + message); })];
+                case 2:
+                    code_sort = _a.sent();
+                    onData('[SAMBAMBA-SORT][EXIT CODE] ' + code_sort);
+                    fs_1.default.unlinkSync(bam);
+                    resolve([bamSorted, discordantFile, splitterFile, unmappedFile]);
+                    return [3 /*break*/, 4];
+                case 3:
+                    err_1 = _a.sent();
+                    reject(err_1);
+                    return [3 /*break*/, 4];
+                case 4: return [2 /*return*/];
+            }
+        });
+    }); });
+};
+exports.default = asyncBwaMem;

+ 0 - 20
index.js

@@ -1,20 +0,0 @@
-import { spawn } from 'child_process';
-import { cpus } from 'os';
-
-const async_exec = (prog, args, onData) => {
-    return new Promise((resolve, reject) => {
-        const child = spawn(prog, args, {shell: true})
-  
-        child.stdout.on('data', data => onData(data.toString().trim()))
-        child.stderr.on('data', data => onData(data.toString().trim()))
-  
-        child.on('error', err => reject(err))
-        child.on('exit', code => resolve(code))
-    })
-}
-
-const aligner = (R1, R2, ref, bamOut, opt) => {
-    return R1
-}
-
-export default aligner

+ 94 - 0
index.ts

@@ -0,0 +1,94 @@
+import { spawn } from 'child_process';
+import { cpus } from 'os';
+import fs from 'fs'
+import path from 'path';
+
+const async_exec = (prog: string, args: string[], onData: Function) => {
+    return new Promise((resolve, reject) => {
+        const child = spawn(prog, args, {shell: true})
+
+        child.stdout.on('data', data => onData(data.toString().trim()))
+        child.stderr.on('data', data => onData(data.toString().trim()))
+
+        child.on('error', err => reject(err))
+        child.on('exit', code => resolve(code))
+    })
+}
+
+const asyncBwaMem = (
+    refPath   : string,
+    R1        : string | Array<string>,
+    R2        : string | Array<string>,
+    runName   : string,
+    libName   : string,
+    output_dir: string,
+    onData    : Function,
+    options?   : any,
+    ) => {
+
+    if (typeof options === 'undefined') options = {}
+
+    const refName = path.parse(refPath).name
+  
+    const bwa        = 'bwa'
+    const samblaster = 'samblaster'
+    const samtools   = 'samtools'
+    const sambamba   = 'sambamba'
+  
+    const R1_arr = Array.isArray(R1) ? R1.join(' ') : R1
+    const R2_arr = Array.isArray(R2) ? R2.join(' ') : R2
+  
+    const R1_kitty = R1_arr.slice(-2) === 'gz' ? 'zcat' : 'cat'
+    const R2_kitty = R2_arr.slice(-2) === 'gz' ? 'zcat' : 'cat'
+  
+    const R1_in = `'< ${R1_kitty} ${R1_arr}'`
+    const R2_in = `'< ${R2_kitty} ${R2_arr}'`
+  
+    const discordantFile = path.join(output_dir, `bwa_mem_discordants_on_${refName}.sam`)
+    const splitterFile   = path.join(output_dir, `bwa_mem_splitters_on_${refName}.sam`)
+    const unmappedFile   = path.join(output_dir, `bwa_mem_unmapped_on_${refName}.fq`)
+    const bam            = path.join(output_dir, `bwa_mem_properly_on_${refName}.bam`)
+    const bamSorted      = path.join(output_dir, `bwa_mem_properly_on_${refName}.sorted.bam`)
+  
+    return new Promise<string[]>(async (resolve, reject) => {
+      try {
+        const code = await async_exec(
+        bwa, ['mem',
+          '-t', String(require('os').cpus().length),
+          '-R', `"@RG\\tPL:Illumina\\tID:${+(new Date)}\\tSM:${runName}\\tLB:${libName}"`,
+          refPath, R1_in, R2_in,
+        '|',
+        samblaster,
+          '--addMateTags', // https://github.com/GregoryFaust/samblaster
+          '-a', // Accept duplicate marks already in input file
+          '-e', // Exclude reads marked as duplicates from discordant, splitter, and/or unmapped
+          '-d', discordantFile,
+          '-s', splitterFile,
+          '-u', unmappedFile,
+        '|',
+        samtools,
+          'view',
+          '-b',
+          '-',
+        '>',
+        bam
+        ], (message: string) => onData('[BWA-MEM] ' + message))
+        onData('[BWA-MEM][EXIT CODE] ' + code)
+        
+        const code_sort = await async_exec(
+          sambamba, ['sort',
+            '-t', String(require('os').cpus().length),
+            bam
+        ], (message: string) => onData('[SAMBAMBA-SORT] ' + message))
+        onData('[SAMBAMBA-SORT][EXIT CODE] ' + code_sort)
+  
+        fs.unlinkSync(bam)
+  
+        resolve([bamSorted, discordantFile, splitterFile, unmappedFile])
+      } catch (err) {
+        reject(err)
+      }
+    })
+}
+
+export default asyncBwaMem

+ 51 - 0
package-lock.json

@@ -0,0 +1,51 @@
+{
+  "name": "aligner",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "aligner",
+      "version": "1.0.0",
+      "license": "ISC",
+      "devDependencies": {
+        "@types/node": "^17.0.17",
+        "typescript": "^4.5.5"
+      }
+    },
+    "node_modules/@types/node": {
+      "version": "17.0.17",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz",
+      "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==",
+      "dev": true
+    },
+    "node_modules/typescript": {
+      "version": "4.5.5",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
+      "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    }
+  },
+  "dependencies": {
+    "@types/node": {
+      "version": "17.0.17",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz",
+      "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==",
+      "dev": true
+    },
+    "typescript": {
+      "version": "4.5.5",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
+      "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+      "dev": true
+    }
+  }
+}

+ 8 - 3
package.json

@@ -2,11 +2,16 @@
   "name": "aligner",
   "version": "1.0.0",
   "description": "aligning ",
-  "main": "index.js",
-  "type": "module",
+  "main": "dist/index.js",
   "scripts": {
+    "prepublish": "npm run build",
+    "build": "tsc",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "author": "",
-  "license": "ISC"
+  "license": "ISC",
+  "devDependencies": {
+    "@types/node": "^17.0.17",
+    "typescript": "^4.5.5"
+  }
 }

+ 11 - 0
tsconfig.json

@@ -0,0 +1,11 @@
+{
+    "compilerOptions": {
+      "target": "es5",
+      "module": "commonjs",
+      "declaration": true,
+      "outDir": "./dist",
+      "strict": true,
+      "esModuleInterop": true,
+    },
+  }
+  

+ 13 - 0
yarn.lock

@@ -0,0 +1,13 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@types/node@^17.0.17":
+  "integrity" "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw=="
+  "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz"
+  "version" "17.0.17"
+
+"typescript@^4.5.5":
+  "integrity" "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA=="
+  "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz"
+  "version" "4.5.5"