clustal-js 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,5 @@
1
- [![Build Status](https://travis-ci.com/cmdcolin/clustal-js.svg?branch=master)](https://travis-ci.com/cmdcolin/clustal-js)
1
+ [![NPM version](https://img.shields.io/npm/v/@gmod/bam.svg?style=flat-square)](https://npmjs.org/package/@gmod/bam)
2
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/cmdcolin/clustal-js/push.yml?branch=master)](https://github.com/cmdcolin/clustal-js/actions?query=branch%3Amaster+workflow%3APush+)
2
3
 
3
4
  # clustal-js
4
5
 
package/dist/index.d.ts CHANGED
@@ -1,26 +1,27 @@
1
1
  export declare function parseClustalIter(arr: Iterator<string>): {
2
2
  consensus: string;
3
3
  alns: {
4
- id: any;
5
- seq: any;
4
+ id: string;
5
+ seq: string;
6
6
  }[];
7
7
  header: {
8
8
  info: string;
9
9
  version: string;
10
10
  };
11
11
  };
12
+ export interface Row {
13
+ id: string;
14
+ seq: string;
15
+ }
12
16
  export declare function parsePairwiseIter(arr: string): {
13
17
  consensus: string;
14
- alns: {
15
- id: any;
16
- seq: any;
17
- }[];
18
+ alns: [Row, Row];
18
19
  };
19
20
  export declare function parse(contents: string): {
20
21
  consensus: string;
21
22
  alns: {
22
- id: any;
23
- seq: any;
23
+ id: string;
24
+ seq: string;
24
25
  }[];
25
26
  header: {
26
27
  info: string;
@@ -29,8 +30,5 @@ export declare function parse(contents: string): {
29
30
  };
30
31
  export declare function parsePairwise(contents: string): {
31
32
  consensus: string;
32
- alns: {
33
- id: any;
34
- seq: any;
35
- }[];
33
+ alns: [Row, Row];
36
34
  };
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parsePairwise = exports.parse = exports.parsePairwiseIter = exports.parseClustalIter = void 0;
3
+ exports.parseClustalIter = parseClustalIter;
4
+ exports.parsePairwiseIter = parsePairwiseIter;
5
+ exports.parse = parse;
6
+ exports.parsePairwise = parsePairwise;
4
7
  const pairwise_1 = require("./pairwise");
5
8
  const util_1 = require("./util");
6
9
  function parseClustalIter(arr) {
@@ -20,7 +23,6 @@ function parseClustalIter(arr) {
20
23
  }
21
24
  return { consensus, alns, header };
22
25
  }
23
- exports.parseClustalIter = parseClustalIter;
24
26
  function parsePairwiseIter(arr) {
25
27
  const res = (0, pairwise_1.parsePairwiseBlocks)(arr.split('\n')[Symbol.iterator]());
26
28
  if (res === undefined) {
@@ -31,19 +33,22 @@ function parsePairwiseIter(arr) {
31
33
  if (consensus.length != alns[0].seq.length) {
32
34
  throw new Error(`Consensus length != sequence length. Con ${consensus.length} seq ${alns[0].seq.length}`);
33
35
  }
34
- return { consensus, alns };
36
+ if (alns.length !== 2) {
37
+ throw new Error('More than two sequences in pairwise alignment');
38
+ }
39
+ return {
40
+ consensus,
41
+ alns: alns,
42
+ };
35
43
  }
36
- exports.parsePairwiseIter = parsePairwiseIter;
37
44
  function parse(contents) {
38
45
  const iter = contents.split('\n')[Symbol.iterator]();
39
46
  return parseClustalIter(iter);
40
47
  }
41
- exports.parse = parse;
42
48
  function parsePairwise(contents) {
43
- const res = contents
49
+ return parsePairwiseIter(contents
44
50
  .split('\n')
45
51
  .filter(f => !f.startsWith('#'))
46
- .join('\n');
47
- return parsePairwiseIter(res);
52
+ .join('\n'));
48
53
  }
49
- exports.parsePairwise = parsePairwise;
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAGA,4CAqBC;AAMD,8CAoBC;AAED,sBAGC;AAED,sCAOC;AAhED,yCAAgD;AAChD,iCAAuE;AAEvE,SAAgB,gBAAgB,CAAC,GAAqB;IACpD,MAAM,IAAI,GAAG,IAAA,2BAAoB,EAAC,GAAG,CAAC,CAAA;IACtC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;IACxC,CAAC;IACD,MAAM,MAAM,GAAG,IAAA,kBAAW,EAAC,IAAI,CAAC,CAAA;IAEhC,MAAM,GAAG,GAAG,IAAA,kBAAW,EAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACzE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAA;IACzB,IAAI,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,4CAA4C,SAAS,CAAC,MAAM,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CACzF,CAAA;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACpC,CAAC;AAMD,SAAgB,iBAAiB,CAAC,GAAW;IAC3C,MAAM,GAAG,GAAG,IAAA,8BAAmB,EAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IACnE,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACzE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAA;IACzB,IAAI,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,4CAA4C,SAAS,CAAC,MAAM,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CACzF,CAAA;IACH,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IACD,OAAO;QACL,SAAS;QACT,IAAI,EAAE,IAAkB;KACzB,CAAA;AACH,CAAC;AAED,SAAgB,KAAK,CAAC,QAAgB;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAA;IACpD,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAA;AAC/B,CAAC;AAED,SAAgB,aAAa,CAAC,QAAgB;IAC5C,OAAO,iBAAiB,CACtB,QAAQ;SACL,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;SAC/B,IAAI,CAAC,IAAI,CAAC,CACd,CAAA;AACH,CAAC"}
@@ -1,11 +1,11 @@
1
1
  export declare function getSeqBounds(line: string): readonly [number, number];
2
2
  export declare function parsePairwiseBlock(arr: Iterator<string>): {
3
- ids: any[];
4
- seqs: any[];
3
+ ids: string[];
4
+ seqs: string[];
5
5
  consensus: string;
6
6
  } | undefined;
7
7
  export declare function parsePairwiseBlocks(arr: Iterator<string>): {
8
- ids: any[];
9
- seqs: any[];
8
+ ids: string[];
9
+ seqs: string[];
10
10
  consensus: string;
11
11
  } | undefined;
package/dist/pairwise.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parsePairwiseBlocks = exports.parsePairwiseBlock = exports.getSeqBounds = void 0;
3
+ exports.getSeqBounds = getSeqBounds;
4
+ exports.parsePairwiseBlock = parsePairwiseBlock;
5
+ exports.parsePairwiseBlocks = parsePairwiseBlocks;
4
6
  const util_1 = require("./util");
5
7
  function getSeqBounds(line) {
6
8
  const fields = line.split(/\s+/);
@@ -10,7 +12,6 @@ function getSeqBounds(line) {
10
12
  const e = s + fields[2].length;
11
13
  return [s, e];
12
14
  }
13
- exports.getSeqBounds = getSeqBounds;
14
15
  // Use the first block to get the sequence identifiers
15
16
  function parsePairwiseBlock(arr) {
16
17
  let line = (0, util_1.getFirstNonEmptyLine)(arr);
@@ -20,11 +21,11 @@ function parsePairwiseBlock(arr) {
20
21
  return undefined;
21
22
  }
22
23
  while (line) {
23
- if (line[0] !== ' ') {
24
- block.push(line);
24
+ if (line.startsWith(' ')) {
25
+ consensusLine = line;
25
26
  }
26
27
  else {
27
- consensusLine = line;
28
+ block.push(line);
28
29
  }
29
30
  line = arr.next().value;
30
31
  }
@@ -40,7 +41,6 @@ function parsePairwiseBlock(arr) {
40
41
  }
41
42
  return { ids, seqs, consensus };
42
43
  }
43
- exports.parsePairwiseBlock = parsePairwiseBlock;
44
44
  function parsePairwiseBlocks(arr) {
45
45
  let block;
46
46
  const res = parsePairwiseBlock(arr);
@@ -54,4 +54,4 @@ function parsePairwiseBlocks(arr) {
54
54
  }
55
55
  return res;
56
56
  }
57
- exports.parsePairwiseBlocks = parsePairwiseBlocks;
57
+ //# sourceMappingURL=pairwise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairwise.js","sourceRoot":"","sources":["../src/pairwise.ts"],"names":[],"mappings":";;AAEA,oCAOC;AAGD,gDA4BC;AAED,kDAYC;AAtDD,iCAA6C;AAE7C,SAAgB,YAAY,CAAC,IAAY;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAChC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAC3B,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IACtC,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IAC9B,OAAO,CAAC,CAAC,EAAE,CAAC,CAAU,CAAA;AACxB,CAAC;AAED,sDAAsD;AACtD,SAAgB,kBAAkB,CAAC,GAAqB;IACtD,IAAI,IAAI,GAAG,IAAA,2BAAoB,EAAC,GAAG,CAAC,CAAA;IACpC,MAAM,KAAK,GAAG,EAAE,CAAA;IAChB,IAAI,aAAa,GAAG,EAAE,CAAA;IACtB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,aAAa,GAAG,IAAI,CAAA;QACtB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClB,CAAC;QACD,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAA;IACzB,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAClC,IAAI,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAE/C,0DAA0D;IAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;IACnD,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACpC,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;AACjC,CAAC;AAED,SAAgB,mBAAmB,CAAC,GAAqB;IACvD,IAAI,KAAK,CAAA;IACT,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;IACnC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAC9B,CAAC;YACD,GAAG,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAA;QAClC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
package/dist/util.d.ts CHANGED
@@ -3,15 +3,15 @@ export declare function parseHeader(info: string): {
3
3
  info: string;
4
4
  version: string;
5
5
  };
6
- export declare function getFirstNonEmptyLine(arr: Iterator<string>): any;
6
+ export declare function getFirstNonEmptyLine(arr: Iterator<string>): string;
7
7
  export declare function getSeqBounds(line: string): readonly [number, number];
8
8
  export declare function parseBlock(arr: Iterator<string>): {
9
- ids: any[];
10
- seqs: any[];
9
+ ids: string[];
10
+ seqs: string[];
11
11
  consensus: string;
12
12
  } | undefined;
13
13
  export declare function parseBlocks(arr: Iterator<string>): {
14
- ids: any[];
15
- seqs: any[];
14
+ ids: string[];
15
+ seqs: string[];
16
16
  consensus: string;
17
17
  } | undefined;
package/dist/util.js CHANGED
@@ -1,11 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseBlocks = exports.parseBlock = exports.getSeqBounds = exports.getFirstNonEmptyLine = exports.parseHeader = exports.parseVersion = void 0;
3
+ exports.parseVersion = parseVersion;
4
+ exports.parseHeader = parseHeader;
5
+ exports.getFirstNonEmptyLine = getFirstNonEmptyLine;
6
+ exports.getSeqBounds = getSeqBounds;
7
+ exports.parseBlock = parseBlock;
8
+ exports.parseBlocks = parseBlocks;
4
9
  function parseVersion(line) {
5
- const res = line.match(/\(?(\d+(\.\d+)+)\)?/);
10
+ const res = /\(?(\d+(\.\d+)+)\)?/.exec(line);
6
11
  return res && res.length > 1 ? res[1] : '';
7
12
  }
8
- exports.parseVersion = parseVersion;
9
13
  function parseHeader(info) {
10
14
  const knownHeaders = ['CLUSTAL', 'PROBCONS', 'MUSCLE', 'MSAPROBS', 'Kalign'];
11
15
  if (!knownHeaders.some(l => info.startsWith(l))) {
@@ -14,7 +18,6 @@ function parseHeader(info) {
14
18
  const version = parseVersion(info);
15
19
  return { info, version };
16
20
  }
17
- exports.parseHeader = parseHeader;
18
21
  function getFirstNonEmptyLine(arr) {
19
22
  // There should be two blank lines after the header line
20
23
  let line = arr.next();
@@ -23,7 +26,6 @@ function getFirstNonEmptyLine(arr) {
23
26
  }
24
27
  return line.value;
25
28
  }
26
- exports.getFirstNonEmptyLine = getFirstNonEmptyLine;
27
29
  function getSeqBounds(line) {
28
30
  const fields = line.split(/\s+/);
29
31
  const temp = line.slice(fields[0].length);
@@ -31,7 +33,6 @@ function getSeqBounds(line) {
31
33
  const e = s + fields[1].length;
32
34
  return [s, e];
33
35
  }
34
- exports.getSeqBounds = getSeqBounds;
35
36
  // Use the first block to get the sequence identifiers
36
37
  function parseBlock(arr) {
37
38
  let line = getFirstNonEmptyLine(arr);
@@ -41,11 +42,11 @@ function parseBlock(arr) {
41
42
  return undefined;
42
43
  }
43
44
  while (line) {
44
- if (line[0] !== ' ') {
45
- block.push(line);
45
+ if (line[0].startsWith(' ')) {
46
+ consensusLine = line;
46
47
  }
47
48
  else {
48
- consensusLine = line;
49
+ block.push(line);
49
50
  }
50
51
  line = arr.next().value;
51
52
  }
@@ -61,7 +62,6 @@ function parseBlock(arr) {
61
62
  }
62
63
  return { ids, seqs, consensus };
63
64
  }
64
- exports.parseBlock = parseBlock;
65
65
  function parseBlocks(arr) {
66
66
  let block;
67
67
  const res = parseBlock(arr);
@@ -75,4 +75,4 @@ function parseBlocks(arr) {
75
75
  }
76
76
  return res;
77
77
  }
78
- exports.parseBlocks = parseBlocks;
78
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
package/esm/index.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ export declare function parseClustalIter(arr: Iterator<string>): {
2
+ consensus: string;
3
+ alns: {
4
+ id: string;
5
+ seq: string;
6
+ }[];
7
+ header: {
8
+ info: string;
9
+ version: string;
10
+ };
11
+ };
12
+ export interface Row {
13
+ id: string;
14
+ seq: string;
15
+ }
16
+ export declare function parsePairwiseIter(arr: string): {
17
+ consensus: string;
18
+ alns: [Row, Row];
19
+ };
20
+ export declare function parse(contents: string): {
21
+ consensus: string;
22
+ alns: {
23
+ id: string;
24
+ seq: string;
25
+ }[];
26
+ header: {
27
+ info: string;
28
+ version: string;
29
+ };
30
+ };
31
+ export declare function parsePairwise(contents: string): {
32
+ consensus: string;
33
+ alns: [Row, Row];
34
+ };
package/esm/index.js ADDED
@@ -0,0 +1,48 @@
1
+ import { parsePairwiseBlocks } from './pairwise';
2
+ import { parseBlocks, parseHeader, getFirstNonEmptyLine } from './util';
3
+ export function parseClustalIter(arr) {
4
+ const line = getFirstNonEmptyLine(arr);
5
+ if (!line) {
6
+ throw new Error('Empty file received');
7
+ }
8
+ const header = parseHeader(line);
9
+ const res = parseBlocks(arr);
10
+ if (res === undefined) {
11
+ throw new Error('No blocks parsed');
12
+ }
13
+ const alns = res.seqs.map((n, index) => ({ id: res.ids[index], seq: n }));
14
+ const { consensus } = res;
15
+ if (consensus.length != alns[0].seq.length) {
16
+ throw new Error(`Consensus length != sequence length. Con ${consensus.length} seq ${alns[0].seq.length}`);
17
+ }
18
+ return { consensus, alns, header };
19
+ }
20
+ export function parsePairwiseIter(arr) {
21
+ const res = parsePairwiseBlocks(arr.split('\n')[Symbol.iterator]());
22
+ if (res === undefined) {
23
+ throw new Error('No blocks parsed');
24
+ }
25
+ const alns = res.seqs.map((n, index) => ({ id: res.ids[index], seq: n }));
26
+ const { consensus } = res;
27
+ if (consensus.length != alns[0].seq.length) {
28
+ throw new Error(`Consensus length != sequence length. Con ${consensus.length} seq ${alns[0].seq.length}`);
29
+ }
30
+ if (alns.length !== 2) {
31
+ throw new Error('More than two sequences in pairwise alignment');
32
+ }
33
+ return {
34
+ consensus,
35
+ alns: alns,
36
+ };
37
+ }
38
+ export function parse(contents) {
39
+ const iter = contents.split('\n')[Symbol.iterator]();
40
+ return parseClustalIter(iter);
41
+ }
42
+ export function parsePairwise(contents) {
43
+ return parsePairwiseIter(contents
44
+ .split('\n')
45
+ .filter(f => !f.startsWith('#'))
46
+ .join('\n'));
47
+ }
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare function getSeqBounds(line: string): readonly [number, number];
2
+ export declare function parsePairwiseBlock(arr: Iterator<string>): {
3
+ ids: string[];
4
+ seqs: string[];
5
+ consensus: string;
6
+ } | undefined;
7
+ export declare function parsePairwiseBlocks(arr: Iterator<string>): {
8
+ ids: string[];
9
+ seqs: string[];
10
+ consensus: string;
11
+ } | undefined;
@@ -0,0 +1,52 @@
1
+ import { getFirstNonEmptyLine } from './util';
2
+ export function getSeqBounds(line) {
3
+ const fields = line.split(/\s+/);
4
+ const k1 = fields[0].length + fields[1].length;
5
+ const temp = line.slice(k1);
6
+ const s = k1 + temp.indexOf(fields[2]);
7
+ const e = s + fields[2].length;
8
+ return [s, e];
9
+ }
10
+ // Use the first block to get the sequence identifiers
11
+ export function parsePairwiseBlock(arr) {
12
+ let line = getFirstNonEmptyLine(arr);
13
+ const block = [];
14
+ let consensusLine = '';
15
+ if (!line) {
16
+ return undefined;
17
+ }
18
+ while (line) {
19
+ if (line.startsWith(' ')) {
20
+ consensusLine = line;
21
+ }
22
+ else {
23
+ block.push(line);
24
+ }
25
+ line = arr.next().value;
26
+ }
27
+ const [start, end] = getSeqBounds(block[0]);
28
+ const fields = block.map(s => s.split(/\s+/));
29
+ const ids = fields.map(s => s[0]);
30
+ const seqs = fields.map(s => s[2]);
31
+ let consensus = consensusLine.slice(start, end);
32
+ // handle if the consensus trailing whitespace got trimmed
33
+ const remainder = seqs[0].length - consensus.length;
34
+ if (remainder) {
35
+ consensus += ' '.repeat(remainder);
36
+ }
37
+ return { ids, seqs, consensus };
38
+ }
39
+ export function parsePairwiseBlocks(arr) {
40
+ let block;
41
+ const res = parsePairwiseBlock(arr);
42
+ if (res !== undefined) {
43
+ while ((block = parsePairwiseBlock(arr))) {
44
+ for (let i = 0; i < block.seqs.length; i++) {
45
+ res.seqs[i] += block.seqs[i];
46
+ }
47
+ res.consensus += block.consensus;
48
+ }
49
+ }
50
+ return res;
51
+ }
52
+ //# sourceMappingURL=pairwise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairwise.js","sourceRoot":"","sources":["../src/pairwise.ts"],"names":[],"mappings":"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"}
package/esm/util.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ export declare function parseVersion(line: string): string;
2
+ export declare function parseHeader(info: string): {
3
+ info: string;
4
+ version: string;
5
+ };
6
+ export declare function getFirstNonEmptyLine(arr: Iterator<string>): string;
7
+ export declare function getSeqBounds(line: string): readonly [number, number];
8
+ export declare function parseBlock(arr: Iterator<string>): {
9
+ ids: string[];
10
+ seqs: string[];
11
+ consensus: string;
12
+ } | undefined;
13
+ export declare function parseBlocks(arr: Iterator<string>): {
14
+ ids: string[];
15
+ seqs: string[];
16
+ consensus: string;
17
+ } | undefined;
package/esm/util.js ADDED
@@ -0,0 +1,70 @@
1
+ export function parseVersion(line) {
2
+ const res = /\(?(\d+(\.\d+)+)\)?/.exec(line);
3
+ return res && res.length > 1 ? res[1] : '';
4
+ }
5
+ export function parseHeader(info) {
6
+ const knownHeaders = ['CLUSTAL', 'PROBCONS', 'MUSCLE', 'MSAPROBS', 'Kalign'];
7
+ if (!knownHeaders.some(l => info.startsWith(l))) {
8
+ console.warn(`${info} is not a known CLUSTAL header: ${knownHeaders.join(',')}, proceeding but could indicate an issue`);
9
+ }
10
+ const version = parseVersion(info);
11
+ return { info, version };
12
+ }
13
+ export function getFirstNonEmptyLine(arr) {
14
+ // There should be two blank lines after the header line
15
+ let line = arr.next();
16
+ while (!line.done && line.value.trim() === '') {
17
+ line = arr.next();
18
+ }
19
+ return line.value;
20
+ }
21
+ export function getSeqBounds(line) {
22
+ const fields = line.split(/\s+/);
23
+ const temp = line.slice(fields[0].length);
24
+ const s = fields[0].length + temp.indexOf(fields[1]);
25
+ const e = s + fields[1].length;
26
+ return [s, e];
27
+ }
28
+ // Use the first block to get the sequence identifiers
29
+ export function parseBlock(arr) {
30
+ let line = getFirstNonEmptyLine(arr);
31
+ const block = [];
32
+ let consensusLine = '';
33
+ if (!line) {
34
+ return undefined;
35
+ }
36
+ while (line) {
37
+ if (line[0].startsWith(' ')) {
38
+ consensusLine = line;
39
+ }
40
+ else {
41
+ block.push(line);
42
+ }
43
+ line = arr.next().value;
44
+ }
45
+ const [start, end] = getSeqBounds(block[0]);
46
+ const fields = block.map(s => s.split(/\s+/));
47
+ const ids = fields.map(s => s[0]);
48
+ const seqs = block.map(s => s.slice(start, end));
49
+ let consensus = consensusLine.slice(start, end);
50
+ // handle if the consensus trailing whitespace got trimmed
51
+ const remainder = seqs[0].length - consensus.length;
52
+ if (remainder) {
53
+ consensus += ' '.repeat(remainder);
54
+ }
55
+ return { ids, seqs, consensus };
56
+ }
57
+ export function parseBlocks(arr) {
58
+ let block;
59
+ const res = parseBlock(arr);
60
+ if (res !== undefined) {
61
+ while ((block = parseBlock(arr))) {
62
+ for (let i = 0; i < block.seqs.length; i++) {
63
+ res.seqs[i] += block.seqs[i];
64
+ }
65
+ res.consensus += block.consensus;
66
+ }
67
+ }
68
+ return res;
69
+ }
70
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,31 +1,36 @@
1
1
  {
2
2
  "name": "clustal-js",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "main": "dist/index.js",
5
+ "module": "esm/index.js",
5
6
  "repository": "cmdcolin/clustal-js",
6
7
  "files": [
7
- "dist"
8
+ "dist",
9
+ "esm",
10
+ "src"
8
11
  ],
9
12
  "license": "MIT",
10
13
  "devDependencies": {
11
14
  "@types/jest": "^29.5.12",
12
- "@types/node": "^20.11.16",
13
- "@typescript-eslint/eslint-plugin": "^6.21.0",
14
- "@typescript-eslint/parser": "^6.21.0",
15
- "eslint": "^8.56.0",
16
- "eslint-config-prettier": "^9.1.0",
17
- "eslint-plugin-prettier": "^5.1.3",
18
- "eslint-plugin-unicorn": "^50.0.1",
15
+ "@types/node": "^22.0.0",
16
+ "@typescript-eslint/eslint-plugin": "^8.1.0",
17
+ "@typescript-eslint/parser": "^8.1.0",
18
+ "eslint": "^9.9.0",
19
+ "eslint-plugin-unicorn": "^55.0.0",
19
20
  "jest": "^29.7.0",
20
21
  "prettier": "^3.2.5",
21
- "ts-jest": "^29.1.2",
22
- "typescript": "^5.3.3"
22
+ "rimraf": "^6.0.1",
23
+ "ts-jest": "^29.2.4",
24
+ "typescript": "^5.3.3",
25
+ "typescript-eslint": "^8.1.0"
23
26
  },
24
27
  "scripts": {
25
- "clean": "rimraf dist",
28
+ "clean": "rimraf dist esm",
26
29
  "test": "jest",
27
- "lint": "eslint --ext .ts src test",
28
- "build": "tsc",
30
+ "lint": "eslint --report-unused-disable-directives --max-warnings 0",
31
+ "build": "npm run build:esm && npm run build:es5",
32
+ "build:esm": "tsc --target es2018 --outDir esm",
33
+ "build:es5": "tsc --target es2015 --module commonjs --outDir dist",
29
34
  "prebuild": "npm run clean",
30
35
  "preversion": "npm run lint && npm test && npm run build",
31
36
  "postversion": "git push --follow-tags"
package/src/index.ts ADDED
@@ -0,0 +1,65 @@
1
+ import { parsePairwiseBlocks } from './pairwise'
2
+ import { parseBlocks, parseHeader, getFirstNonEmptyLine } from './util'
3
+
4
+ export function parseClustalIter(arr: Iterator<string>) {
5
+ const line = getFirstNonEmptyLine(arr)
6
+ if (!line) {
7
+ throw new Error('Empty file received')
8
+ }
9
+ const header = parseHeader(line)
10
+
11
+ const res = parseBlocks(arr)
12
+ if (res === undefined) {
13
+ throw new Error('No blocks parsed')
14
+ }
15
+
16
+ const alns = res.seqs.map((n, index) => ({ id: res.ids[index], seq: n }))
17
+ const { consensus } = res
18
+ if (consensus.length != alns[0].seq.length) {
19
+ throw new Error(
20
+ `Consensus length != sequence length. Con ${consensus.length} seq ${alns[0].seq.length}`,
21
+ )
22
+ }
23
+
24
+ return { consensus, alns, header }
25
+ }
26
+
27
+ export interface Row {
28
+ id: string
29
+ seq: string
30
+ }
31
+ export function parsePairwiseIter(arr: string) {
32
+ const res = parsePairwiseBlocks(arr.split('\n')[Symbol.iterator]())
33
+ if (res === undefined) {
34
+ throw new Error('No blocks parsed')
35
+ }
36
+
37
+ const alns = res.seqs.map((n, index) => ({ id: res.ids[index], seq: n }))
38
+ const { consensus } = res
39
+ if (consensus.length != alns[0].seq.length) {
40
+ throw new Error(
41
+ `Consensus length != sequence length. Con ${consensus.length} seq ${alns[0].seq.length}`,
42
+ )
43
+ }
44
+ if (alns.length !== 2) {
45
+ throw new Error('More than two sequences in pairwise alignment')
46
+ }
47
+ return {
48
+ consensus,
49
+ alns: alns as [Row, Row],
50
+ }
51
+ }
52
+
53
+ export function parse(contents: string) {
54
+ const iter = contents.split('\n')[Symbol.iterator]()
55
+ return parseClustalIter(iter)
56
+ }
57
+
58
+ export function parsePairwise(contents: string) {
59
+ return parsePairwiseIter(
60
+ contents
61
+ .split('\n')
62
+ .filter(f => !f.startsWith('#'))
63
+ .join('\n'),
64
+ )
65
+ }
@@ -0,0 +1,55 @@
1
+ import { getFirstNonEmptyLine } from './util'
2
+
3
+ export function getSeqBounds(line: string) {
4
+ const fields = line.split(/\s+/)
5
+ const k1 = fields[0].length + fields[1].length
6
+ const temp = line.slice(k1)
7
+ const s = k1 + temp.indexOf(fields[2])
8
+ const e = s + fields[2].length
9
+ return [s, e] as const
10
+ }
11
+
12
+ // Use the first block to get the sequence identifiers
13
+ export function parsePairwiseBlock(arr: Iterator<string>) {
14
+ let line = getFirstNonEmptyLine(arr)
15
+ const block = []
16
+ let consensusLine = ''
17
+ if (!line) {
18
+ return undefined
19
+ }
20
+
21
+ while (line) {
22
+ if (line.startsWith(' ')) {
23
+ consensusLine = line
24
+ } else {
25
+ block.push(line)
26
+ }
27
+ line = arr.next().value
28
+ }
29
+ const [start, end] = getSeqBounds(block[0])
30
+ const fields = block.map(s => s.split(/\s+/))
31
+ const ids = fields.map(s => s[0])
32
+ const seqs = fields.map(s => s[2])
33
+ let consensus = consensusLine.slice(start, end)
34
+
35
+ // handle if the consensus trailing whitespace got trimmed
36
+ const remainder = seqs[0].length - consensus.length
37
+ if (remainder) {
38
+ consensus += ' '.repeat(remainder)
39
+ }
40
+ return { ids, seqs, consensus }
41
+ }
42
+
43
+ export function parsePairwiseBlocks(arr: Iterator<string>) {
44
+ let block
45
+ const res = parsePairwiseBlock(arr)
46
+ if (res !== undefined) {
47
+ while ((block = parsePairwiseBlock(arr))) {
48
+ for (let i = 0; i < block.seqs.length; i++) {
49
+ res.seqs[i] += block.seqs[i]
50
+ }
51
+ res.consensus += block.consensus
52
+ }
53
+ }
54
+ return res
55
+ }
package/src/util.ts ADDED
@@ -0,0 +1,79 @@
1
+ export function parseVersion(line: string) {
2
+ const res = /\(?(\d+(\.\d+)+)\)?/.exec(line)
3
+ return res && res.length > 1 ? res[1] : ''
4
+ }
5
+ export function parseHeader(info: string) {
6
+ const knownHeaders = ['CLUSTAL', 'PROBCONS', 'MUSCLE', 'MSAPROBS', 'Kalign']
7
+
8
+ if (!knownHeaders.some(l => info.startsWith(l))) {
9
+ console.warn(
10
+ `${info} is not a known CLUSTAL header: ${knownHeaders.join(
11
+ ',',
12
+ )}, proceeding but could indicate an issue`,
13
+ )
14
+ }
15
+ const version = parseVersion(info)
16
+ return { info, version }
17
+ }
18
+
19
+ export function getFirstNonEmptyLine(arr: Iterator<string>): string {
20
+ // There should be two blank lines after the header line
21
+ let line = arr.next()
22
+ while (!line.done && line.value.trim() === '') {
23
+ line = arr.next()
24
+ }
25
+ return line.value
26
+ }
27
+
28
+ export function getSeqBounds(line: string) {
29
+ const fields = line.split(/\s+/)
30
+ const temp = line.slice(fields[0].length)
31
+ const s = fields[0].length + temp.indexOf(fields[1])
32
+ const e = s + fields[1].length
33
+ return [s, e] as const
34
+ }
35
+
36
+ // Use the first block to get the sequence identifiers
37
+ export function parseBlock(arr: Iterator<string>) {
38
+ let line = getFirstNonEmptyLine(arr)
39
+ const block = []
40
+ let consensusLine = ''
41
+ if (!line) {
42
+ return undefined
43
+ }
44
+
45
+ while (line) {
46
+ if (line[0].startsWith(' ')) {
47
+ consensusLine = line
48
+ } else {
49
+ block.push(line)
50
+ }
51
+ line = arr.next().value
52
+ }
53
+ const [start, end] = getSeqBounds(block[0])
54
+ const fields = block.map(s => s.split(/\s+/))
55
+ const ids = fields.map(s => s[0])
56
+ const seqs = block.map(s => s.slice(start, end))
57
+ let consensus = consensusLine.slice(start, end)
58
+
59
+ // handle if the consensus trailing whitespace got trimmed
60
+ const remainder = seqs[0].length - consensus.length
61
+ if (remainder) {
62
+ consensus += ' '.repeat(remainder)
63
+ }
64
+ return { ids, seqs, consensus }
65
+ }
66
+
67
+ export function parseBlocks(arr: Iterator<string>) {
68
+ let block
69
+ const res = parseBlock(arr)
70
+ if (res !== undefined) {
71
+ while ((block = parseBlock(arr))) {
72
+ for (let i = 0; i < block.seqs.length; i++) {
73
+ res.seqs[i] += block.seqs[i]
74
+ }
75
+ res.consensus += block.consensus
76
+ }
77
+ }
78
+ return res
79
+ }