@datagrok-libraries/utils 0.0.5 → 0.0.6
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/package.json +4 -3
- package/src/bit-array.ts +29 -18
- package/src/reduce-dimensionality.ts +40 -34
- package/src/sequence-encoder.ts +8 -7
- package/src/string-measure.ts +5 -5
- package/src/bit-array.js +0 -656
- package/src/operations.js +0 -144
- package/src/reduce-dimensionality.js +0 -233
- package/src/sequence-encoder.js +0 -116
- package/src/spe.js +0 -151
- package/src/string-measure.js +0 -46
- package/src/string-utils.js +0 -9
- package/src/table-validation.js +0 -47
- package/src/test-utils.js +0 -80
- package/src/type_declarations.js +0 -37
package/src/operations.js
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { Vector } from './type_declarations';
|
|
2
|
-
/**
|
|
3
|
-
* Asserts a condition by throwing an Error.
|
|
4
|
-
*
|
|
5
|
-
* @export
|
|
6
|
-
* @param {boolean} [condition=false] Condition to assert.
|
|
7
|
-
* @param {string} [message='Assertion error.'] Message to output.
|
|
8
|
-
* @throws {Error}
|
|
9
|
-
*/
|
|
10
|
-
export function assert(condition = false, message = 'Assertion error.') {
|
|
11
|
-
if (!condition) {
|
|
12
|
-
throw new Error(message);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Generates single random integer from 0 to range.
|
|
17
|
-
*
|
|
18
|
-
* @export
|
|
19
|
-
* @param {number} range Max generating value.
|
|
20
|
-
* @return {number} A random integer generated.
|
|
21
|
-
*/
|
|
22
|
-
export function randomInt(range) {
|
|
23
|
-
return Math.floor(Math.random() * range);
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Creates new two-dimensional array and fills it with the value given.
|
|
27
|
-
*
|
|
28
|
-
* @param {number} dimension1 The first dimension of the coordinates (number of rows).
|
|
29
|
-
* @param {number} dimension2 The second dimension of the coordinates (number of columns).
|
|
30
|
-
* @param {number} [fill=0] A value to fill the coordinates with.
|
|
31
|
-
* @return {Coordinates} A two-dimensional filled with the value given.
|
|
32
|
-
* @todo Might be slow since used Array.map. Probably needs performance revision.
|
|
33
|
-
*/
|
|
34
|
-
function initCoordinates(dimension1, dimension2, fill = 0) {
|
|
35
|
-
return new Array(dimension1).fill(fill).map(() => (new Vector(dimension2).fill(fill)));
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Transpose matrix.
|
|
39
|
-
*
|
|
40
|
-
* @export
|
|
41
|
-
* @param {Matrix} matrix The matrix to be transposed.
|
|
42
|
-
* @return {Matrix} Transposed matrix.
|
|
43
|
-
* @todo Might be slow since used Array.map. Probably needs performance revision.
|
|
44
|
-
*/
|
|
45
|
-
export function transposeMatrix(matrix) {
|
|
46
|
-
return new Array(matrix[0].length).fill(0).map((_, i) => (new Vector(matrix.length).fill(0).map((_, j) => (matrix[j][i]))));
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Adds two vectors with the second one to be multiplied by the given ratio.
|
|
50
|
-
*
|
|
51
|
-
* @export
|
|
52
|
-
* @param {Vector} p The first vector to add.
|
|
53
|
-
* @param {Vector} q The second vector to add.
|
|
54
|
-
* @param {number} [multiplier=1] A multiplier to be used before the second vector is added.
|
|
55
|
-
* @return {Vector} New vector contained the result of operation p+multiplier*q.
|
|
56
|
-
*/
|
|
57
|
-
export function vectorAdd(p, q, multiplier = 1) {
|
|
58
|
-
const nItems = p.length;
|
|
59
|
-
assert(nItems == q.length, 'Vector lengths do not match.');
|
|
60
|
-
let total = new Vector(nItems);
|
|
61
|
-
for (let i = 0; i < p.length; ++i) {
|
|
62
|
-
total[i] = p[i] + multiplier * q[i];
|
|
63
|
-
}
|
|
64
|
-
return total;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Sums the vector's items.
|
|
68
|
-
*
|
|
69
|
-
* @param {Vector} v The vector to be summed.
|
|
70
|
-
* @return {number} The vector's items sum.
|
|
71
|
-
*/
|
|
72
|
-
function itemsSum(v) {
|
|
73
|
-
let total = 0;
|
|
74
|
-
for (let i = 0; i < v.length; ++i) {
|
|
75
|
-
total += v[i];
|
|
76
|
-
}
|
|
77
|
-
return total;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Suqares the vector's items.
|
|
81
|
-
*
|
|
82
|
-
* @param {Vector} v The vector to square.
|
|
83
|
-
* @return {Vector} A new vector containing the original's items squared.
|
|
84
|
-
*/
|
|
85
|
-
function vectorSquare(v) {
|
|
86
|
-
const nItems = v.length;
|
|
87
|
-
let total = new Vector(nItems);
|
|
88
|
-
for (let i = 0; i < v.length; ++i) {
|
|
89
|
-
total[i] = v[i] * v[i];
|
|
90
|
-
}
|
|
91
|
-
return total;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Creates a matrix filled with random floating point values.
|
|
95
|
-
*
|
|
96
|
-
* @export
|
|
97
|
-
* @param {number} dimension1 The first dimension of the matrix.
|
|
98
|
-
* @param {number} dimension2 The second dimension of the matrix.
|
|
99
|
-
* @param {number} [scale=1.] Max value given by random generator.
|
|
100
|
-
* @return {Matrix} A new matrix filled with random floating point values.
|
|
101
|
-
*/
|
|
102
|
-
export function fillRandomMatrix(dimension1, dimension2, scale = 1.) {
|
|
103
|
-
let matrix = initCoordinates(dimension1, dimension2);
|
|
104
|
-
for (let i = 0; i < dimension1; ++i) {
|
|
105
|
-
for (let j = 0; j < dimension2; ++j) {
|
|
106
|
-
matrix[i][j] = Math.random() * scale;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return matrix;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Calculates Euclidean distance between two vectors.
|
|
113
|
-
*
|
|
114
|
-
* @export
|
|
115
|
-
* @param {Vector} p The first vector.
|
|
116
|
-
* @param {Vector} q The second vector.
|
|
117
|
-
* @return {number} Euclidean distance between the given vectors.
|
|
118
|
-
*/
|
|
119
|
-
export function calculateEuclideanDistance(p, q) {
|
|
120
|
-
const diff = vectorAdd(p, q, -1);
|
|
121
|
-
const sqdiff = vectorSquare(diff);
|
|
122
|
-
const sqdiffSumm = itemsSum(sqdiff);
|
|
123
|
-
return Math.sqrt(sqdiffSumm);
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Creates a distance matrix using a custom distance function.
|
|
127
|
-
*
|
|
128
|
-
* @export
|
|
129
|
-
* @param {Vectors} data Input vectors to calculate distances.
|
|
130
|
-
* @param {DistanceMetric} distance Custom distance function.
|
|
131
|
-
* @return {Matrix} Calculated custom distance matrix.
|
|
132
|
-
*/
|
|
133
|
-
export function calcDistanceMatrix(data, distance) {
|
|
134
|
-
const nItems = data.length;
|
|
135
|
-
let matrix = initCoordinates(nItems, nItems, 0);
|
|
136
|
-
for (let i = 0; i < nItems; ++i) {
|
|
137
|
-
for (let j = i + 1; j < nItems; ++j) {
|
|
138
|
-
const d = (data[i] == null) || (data[j] == null) ? 0 : distance(data[i], data[j]);
|
|
139
|
-
matrix[i][j] = matrix[j][i] = d;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return matrix;
|
|
143
|
-
}
|
|
144
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmF0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wZXJhdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFTLE1BQU0sRUFBdUMsTUFBTSxxQkFBcUIsQ0FBQztBQUV6Rjs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxZQUFxQixLQUFLLEVBQUUsVUFBa0Isa0JBQWtCO0lBQ3JGLElBQUksQ0FBQyxTQUFTLEVBQUU7UUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0tBQzFCO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsS0FBYTtJQUNyQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQVMsZUFBZSxDQUFDLFVBQWtCLEVBQUUsVUFBa0IsRUFBRSxPQUFlLENBQUM7SUFDL0UsT0FBTyxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN6RixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsTUFBYztJQUM1QyxPQUFPLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxD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QixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxJQUFhLEVBQUUsUUFBd0I7SUFDeEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUMzQixJQUFJLE1BQU0sR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUVoRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFO1FBQy9CLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFO1lBQ2pDLE1BQU0sQ0FBQyxHQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUYsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDakM7S0FDRjtJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge01hdHJpeCwgVmVjdG9yLCBDb29yZGluYXRlcywgVmVjdG9ycywgRGlzdGFuY2VNZXRyaWN9IGZyb20gJy4vdHlwZV9kZWNsYXJhdGlvbnMnO1xyXG5cclxuLyoqXHJcbiAqIEFzc2VydHMgYSBjb25kaXRpb24gYnkgdGhyb3dpbmcgYW4gRXJyb3IuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtib29sZWFufSBbY29uZGl0aW9uPWZhbHNlXSBDb25kaXRpb24gdG8gYXNzZXJ0LlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2U9J0Fzc2VydGlvbiBlcnJvci4nXSBNZXNzYWdlIHRvIG91dHB1dC5cclxuICogQHRocm93cyB7RXJyb3J9XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0KGNvbmRpdGlvbjogYm9vbGVhbiA9IGZhbHNlLCBtZXNzYWdlOiBzdHJpbmcgPSAnQXNzZXJ0aW9uIGVycm9yLicpIHtcclxuICBpZiAoIWNvbmRpdGlvbikge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEdlbmVyYXRlcyBzaW5nbGUgcmFuZG9tIGludGVnZXIgZnJvbSAwIHRvIHJhbmdlLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSByYW5nZSBNYXggZ2VuZXJhdGluZyB2YWx1ZS5cclxuICogQHJldHVybiB7bnVtYmVyfSBBIHJhbmRvbSBpbnRlZ2VyIGdlbmVyYXRlZC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiByYW5kb21JbnQocmFuZ2U6IG51bWJlcik6IG51bWJlciB7XHJcbiAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHJhbmdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgbmV3IHR3by1kaW1lbnNpb25hbCBhcnJheSBhbmQgZmlsbHMgaXQgd2l0aCB0aGUgdmFsdWUgZ2l2ZW4uXHJcbiAqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBkaW1lbnNpb24xIFRoZSBmaXJzdCBkaW1lbnNpb24gb2YgdGhlIGNvb3JkaW5hdGVzIChudW1iZXIgb2Ygcm93cykuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBkaW1lbnNpb24yIFRoZSBzZWNvbmQgZGltZW5zaW9uIG9mIHRoZSBjb29yZGluYXRlcyAobnVtYmVyIG9mIGNvbHVtbnMpLlxyXG4gKiBAcGFyYW0ge251bWJlcn0gW2ZpbGw9MF0gQSB2YWx1ZSB0byBmaWxsIHRoZSBjb29yZGluYXRlcyB3aXRoLlxyXG4gKiBAcmV0dXJuIHtDb29yZGluYXRlc30gQSB0d28tZGltZW5zaW9uYWwgZmlsbGVkIHdpdGggdGhlIHZhbHVlIGdpdmVuLlxyXG4gKiBAdG9kbyBNaWdodCBiZSBzbG93IHNpbmNlIHVzZWQgQXJyYXkubWFwLiBQcm9iYWJseSBuZWVkcyBwZXJmb3JtYW5jZSByZXZpc2lvbi5cclxuICovXHJcbmZ1bmN0aW9uIGluaXRDb29yZGluYXRlcyhkaW1lbnNpb24xOiBudW1iZXIsIGRpbWVuc2lvbjI6IG51bWJlciwgZmlsbDogbnVtYmVyID0gMCk6IENvb3JkaW5hdGVzIHtcclxuICByZXR1cm4gbmV3IEFycmF5KGRpbWVuc2lvbjEpLmZpbGwoZmlsbCkubWFwKCgpID0+IChuZXcgVmVjdG9yKGRpbWVuc2lvbjIpLmZpbGwoZmlsbCkpKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFRyYW5zcG9zZSBtYXRyaXguXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtNYXRyaXh9IG1hdHJpeCBUaGUgbWF0cml4IHRvIGJlIHRyYW5zcG9zZWQuXHJcbiAqIEByZXR1cm4ge01hdHJpeH0gVHJhbnNwb3NlZCBtYXRyaXguXHJcbiAqIEB0b2RvIE1pZ2h0IGJlIHNsb3cgc2luY2UgdXNlZCBBcnJheS5tYXAuIFByb2JhYmx5IG5lZWRzIHBlcmZvcm1hbmNlIHJldmlzaW9uLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zcG9zZU1hdHJpeChtYXRyaXg6IE1hdHJpeCk6IE1hdHJpeCB7XHJcbiAgcmV0dXJuIG5ldyBBcnJheShtYXRyaXhbMF0ubGVuZ3RoKS5maWxsKDApLm1hcCgoXywgaSkgPT4gKG5ldyBWZWN0b3IobWF0cml4Lmxlbmd0aCkuZmlsbCgwKS5tYXAoKF8sIGopID0+IChtYXRyaXhbal1baV0pKSkpO1xyXG59XHJcblxyXG4vKipcclxuICogQWRkcyB0d28gdmVjdG9ycyB3aXRoIHRoZSBzZWNvbmQgb25lIHRvIGJlIG11bHRpcGxpZWQgYnkgdGhlIGdpdmVuIHJhdGlvLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7VmVjdG9yfSBwIFRoZSBmaXJzdCB2ZWN0b3IgdG8gYWRkLlxyXG4gKiBAcGFyYW0ge1ZlY3Rvcn0gcSBUaGUgc2Vjb25kIHZlY3RvciB0byBhZGQuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBbbXVsdGlwbGllcj0xXSBBIG11bHRpcGxpZXIgdG8gYmUgdXNlZCBiZWZvcmUgdGhlIHNlY29uZCB2ZWN0b3IgaXMgYWRkZWQuXHJcbiAqIEByZXR1cm4ge1ZlY3Rvcn0gTmV3IHZlY3RvciBjb250YWluZWQgdGhlIHJlc3VsdCBvZiBvcGVyYXRpb24gcCttdWx0aXBsaWVyKnEuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdmVjdG9yQWRkKHA6IFZlY3RvciwgcTogVmVjdG9yLCBtdWx0aXBsaWVyOiBudW1iZXIgPSAxKTogVmVjdG9yIHtcclxuICBjb25zdCBuSXRlbXMgPSBwLmxlbmd0aDtcclxuXHJcbiAgYXNzZXJ0KG5JdGVtcyA9PSBxLmxlbmd0aCwgJ1ZlY3RvciBsZW5ndGhzIGRvIG5vdCBtYXRjaC4nKVxyXG5cclxuICBsZXQgdG90YWwgPSBuZXcgVmVjdG9yKG5JdGVtcyk7XHJcblxyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcC5sZW5ndGg7ICsraSkge1xyXG4gICAgdG90YWxbaV0gPSBwW2ldK211bHRpcGxpZXIqcVtpXTtcclxuICB9XHJcbiAgcmV0dXJuIHRvdGFsO1xyXG59XHJcblxyXG4vKipcclxuICogU3VtcyB0aGUgdmVjdG9yJ3MgaXRlbXMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7VmVjdG9yfSB2IFRoZSB2ZWN0b3IgdG8gYmUgc3VtbWVkLlxyXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSB2ZWN0b3IncyBpdGVtcyBzdW0uXHJcbiAqL1xyXG5mdW5jdGlvbiBpdGVtc1N1bSh2OiBWZWN0b3IpOiBudW1iZXIge1xyXG4gIGxldCB0b3RhbCA9IDA7XHJcblxyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdi5sZW5ndGg7ICsraSkge1xyXG4gICAgdG90YWwgKz0gdltpXTtcclxuICB9XHJcbiAgcmV0dXJuIHRvdGFsO1xyXG59XHJcblxyXG4vKipcclxuICogU3VxYXJlcyB0aGUgdmVjdG9yJ3MgaXRlbXMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7VmVjdG9yfSB2IFRoZSB2ZWN0b3IgdG8gc3F1YXJlLlxyXG4gKiBAcmV0dXJuIHtWZWN0b3J9IEEgbmV3IHZlY3RvciBjb250YWluaW5nIHRoZSBvcmlnaW5hbCdzIGl0ZW1zIHNxdWFyZWQuXHJcbiAqL1xyXG5mdW5jdGlvbiB2ZWN0b3JTcXVhcmUodjogVmVjdG9yKTogVmVjdG9yIHtcclxuICBjb25zdCBuSXRlbXMgPSB2Lmxlbmd0aDtcclxuICBsZXQgdG90YWwgPSBuZXcgVmVjdG9yKG5JdGVtcyk7XHJcblxyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdi5sZW5ndGg7ICsraSkge1xyXG4gICAgdG90YWxbaV0gPSB2W2ldKnZbaV07XHJcbiAgfVxyXG4gIHJldHVybiB0b3RhbDtcclxufVxyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBtYXRyaXggZmlsbGVkIHdpdGggcmFuZG9tIGZsb2F0aW5nIHBvaW50IHZhbHVlcy5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gZGltZW5zaW9uMSBUaGUgZmlyc3QgZGltZW5zaW9uIG9mIHRoZSBtYXRyaXguXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBkaW1lbnNpb24yIFRoZSBzZWNvbmQgZGltZW5zaW9uIG9mIHRoZSBtYXRyaXguXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBbc2NhbGU9MS5dIE1heCB2YWx1ZSBnaXZlbiBieSByYW5kb20gZ2VuZXJhdG9yLlxyXG4gKiBAcmV0dXJuIHtNYXRyaXh9IEEgbmV3IG1hdHJpeCBmaWxsZWQgd2l0aCByYW5kb20gZmxvYXRpbmcgcG9pbnQgIHZhbHVlcy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmaWxsUmFuZG9tTWF0cml4KGRpbWVuc2lvbjE6IG51bWJlciwgZGltZW5zaW9uMjogbnVtYmVyLCBzY2FsZTogbnVtYmVyID0gMS4pOiBNYXRyaXgge1xyXG4gIGxldCBtYXRyaXggPSBpbml0Q29vcmRpbmF0ZXMoZGltZW5zaW9uMSwgZGltZW5zaW9uMik7XHJcblxyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGltZW5zaW9uMTsgKytpKSB7XHJcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGRpbWVuc2lvbjI7ICsraikge1xyXG4gICAgICBtYXRyaXhbaV1bal0gPSBNYXRoLnJhbmRvbSgpICogc2NhbGU7XHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiBtYXRyaXg7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxjdWxhdGVzIEV1Y2xpZGVhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWN0b3JzLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7VmVjdG9yfSBwIFRoZSBmaXJzdCB2ZWN0b3IuXHJcbiAqIEBwYXJhbSB7VmVjdG9yfSBxIFRoZSBzZWNvbmQgdmVjdG9yLlxyXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEV1Y2xpZGVhbiBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBnaXZlbiB2ZWN0b3JzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUV1Y2xpZGVhbkRpc3RhbmNlKHA6IFZlY3RvciwgcTogVmVjdG9yKTogbnVtYmVyIHtcclxuICBjb25zdCBkaWZmID0gdmVjdG9yQWRkKHAsIHEsIC0xKTtcclxuICBjb25zdCBzcWRpZmYgPSB2ZWN0b3JTcXVhcmUoZGlmZik7XHJcbiAgY29uc3Qgc3FkaWZmU3VtbSA9IGl0ZW1zU3VtKHNxZGlmZik7XHJcbiAgcmV0dXJuIE1hdGguc3FydChzcWRpZmZTdW1tKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBkaXN0YW5jZSBtYXRyaXggdXNpbmcgYSBjdXN0b20gZGlzdGFuY2UgZnVuY3Rpb24uXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtWZWN0b3JzfSBkYXRhIElucHV0IHZlY3RvcnMgdG8gY2FsY3VsYXRlIGRpc3RhbmNlcy5cclxuICogQHBhcmFtIHtEaXN0YW5jZU1ldHJpY30gZGlzdGFuY2UgQ3VzdG9tIGRpc3RhbmNlIGZ1bmN0aW9uLlxyXG4gKiBAcmV0dXJuIHtNYXRyaXh9IENhbGN1bGF0ZWQgY3VzdG9tIGRpc3RhbmNlIG1hdHJpeC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBjYWxjRGlzdGFuY2VNYXRyaXgoZGF0YTogVmVjdG9ycywgZGlzdGFuY2U6IERpc3RhbmNlTWV0cmljKTogTWF0cml4IHtcclxuICBjb25zdCBuSXRlbXMgPSBkYXRhLmxlbmd0aDtcclxuICBsZXQgbWF0cml4ID0gaW5pdENvb3JkaW5hdGVzKG5JdGVtcywgbkl0ZW1zLCAwKTtcclxuXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuSXRlbXM7ICsraSkge1xyXG4gICAgZm9yIChsZXQgaiA9IGkrMTsgaiA8IG5JdGVtczsgKytqKSB7XHJcbiAgICAgIGNvbnN0IGQ6IG51bWJlciA9IChkYXRhW2ldID09IG51bGwpIHx8IChkYXRhW2pdID09IG51bGwpID8gMCA6IGRpc3RhbmNlKGRhdGFbaV0sIGRhdGFbal0pO1xyXG4gICAgICBtYXRyaXhbaV1bal0gPSBtYXRyaXhbal1baV0gPSBkO1xyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gbWF0cml4O1xyXG59XHJcbiJdfQ==
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import * as umj from 'umap-js';
|
|
2
|
-
import { TSNE } from '@keckelt/tsne';
|
|
3
|
-
import { Vector } from './type_declarations';
|
|
4
|
-
import { calcDistanceMatrix, transposeMatrix } from './operations';
|
|
5
|
-
import { SPEBase, PSPEBase } from './spe';
|
|
6
|
-
import { Measurer } from './string-measure';
|
|
7
|
-
//import {AlignedSequenceEncoder} from './sequence-encoder';
|
|
8
|
-
/**
|
|
9
|
-
* Abstract dimensionality reducer.
|
|
10
|
-
*
|
|
11
|
-
* @abstract
|
|
12
|
-
* @class Reducer
|
|
13
|
-
*/
|
|
14
|
-
class Reducer {
|
|
15
|
-
/**
|
|
16
|
-
* Creates an instance of Reducer.
|
|
17
|
-
* @param {Options} options Options to pass to the constructor.
|
|
18
|
-
* @memberof Reducer
|
|
19
|
-
*/
|
|
20
|
-
constructor(options) {
|
|
21
|
-
this.data = options.data;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Implements t-SNE dimensionality reduction.
|
|
26
|
-
*
|
|
27
|
-
* @class TSNEReducer
|
|
28
|
-
* @extends {Reducer}
|
|
29
|
-
*/
|
|
30
|
-
class TSNEReducer extends Reducer {
|
|
31
|
-
/**
|
|
32
|
-
* Creates an instance of TSNEReducer.
|
|
33
|
-
* @param {Options} options Options to pass to the constructor.
|
|
34
|
-
* @memberof TSNEReducer
|
|
35
|
-
*/
|
|
36
|
-
constructor(options) {
|
|
37
|
-
var _a;
|
|
38
|
-
super(options);
|
|
39
|
-
this.reducer = new TSNE(options);
|
|
40
|
-
this.iterations = (_a = options === null || options === void 0 ? void 0 : options.iterations) !== null && _a !== void 0 ? _a : 100;
|
|
41
|
-
this.distance = options.distance;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Embeds the data given into the two-dimensional space using t-SNE method.
|
|
45
|
-
* @return {Coordinates} Cartesian coordinate of this embedding.
|
|
46
|
-
*/
|
|
47
|
-
transform() {
|
|
48
|
-
this.reducer.initDataDist(calcDistanceMatrix(this.data, this.distance));
|
|
49
|
-
for (let i = 0; i < this.iterations; ++i) {
|
|
50
|
-
this.reducer.step(); // every time you call this, solution gets better
|
|
51
|
-
}
|
|
52
|
-
return this.reducer.getSolution();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Implements UMAP dimensionality reduction.
|
|
57
|
-
*
|
|
58
|
-
* @class UMAPReducer
|
|
59
|
-
* @extends {Reducer}
|
|
60
|
-
*/
|
|
61
|
-
class UMAPReducer extends Reducer {
|
|
62
|
-
/* protected encoder: AlignedSequenceEncoder;
|
|
63
|
-
protected distanceMatrix: Matrix;*/
|
|
64
|
-
/**
|
|
65
|
-
* Creates an instance of UMAPReducer.
|
|
66
|
-
* @param {Options} options Options to pass to the constructor.
|
|
67
|
-
* @memberof UMAPReducer
|
|
68
|
-
*/
|
|
69
|
-
constructor(options) {
|
|
70
|
-
super(options);
|
|
71
|
-
this.reducer = new umj.UMAP(options);
|
|
72
|
-
/* this.encoder = new AlignedSequenceEncoder();
|
|
73
|
-
this.distanceMatrix = calcDistanceMatrix(this.data, options.distanceFn);
|
|
74
|
-
this.distanceFn = options.distanceFn;*/
|
|
75
|
-
}
|
|
76
|
-
/* protected _encodedDistance(a: number[], b: number[]): number {
|
|
77
|
-
return this.distanceMatrix[a[a.length-1]][b[b.length-1]];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
protected _decodedDistance(a: number[], b: number[]): number {
|
|
81
|
-
return this.encoder.decode(a);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
protected encode(): number[][] {
|
|
85
|
-
let vectors: number[][] = [];
|
|
86
|
-
|
|
87
|
-
for (let i = 0; i < this.data.length; ++i) {
|
|
88
|
-
let encoded = this.encoder.encode(this.data[i]);
|
|
89
|
-
vectors.push(encoded);
|
|
90
|
-
}
|
|
91
|
-
return vectors;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
protected _calcDistance() {
|
|
95
|
-
const nItems = this.data.length;
|
|
96
|
-
const vectors = this.encode();
|
|
97
|
-
|
|
98
|
-
}*/
|
|
99
|
-
/**
|
|
100
|
-
* Embeds the data given into the two-dimensional space using UMAP method.
|
|
101
|
-
* @return {Coordinates} Cartesian coordinate of this embedding.
|
|
102
|
-
*/
|
|
103
|
-
transform() {
|
|
104
|
-
const embedding = this.reducer.fit(this.data);
|
|
105
|
-
function arrayCast2Coordinates(data) {
|
|
106
|
-
return new Array(data.length).fill(0).map((_, i) => (Vector.from(data[i])));
|
|
107
|
-
}
|
|
108
|
-
return arrayCast2Coordinates(embedding);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Implements original SPE dimensionality reduction.
|
|
113
|
-
*
|
|
114
|
-
* @class SPEReducer
|
|
115
|
-
* @extends {Reducer}
|
|
116
|
-
*/
|
|
117
|
-
class SPEReducer extends Reducer {
|
|
118
|
-
/**
|
|
119
|
-
* Creates an instance of SPEReducer.
|
|
120
|
-
* @param {Options} options Options to pass to the constructor.
|
|
121
|
-
* @memberof SPEReducer
|
|
122
|
-
*/
|
|
123
|
-
constructor(options) {
|
|
124
|
-
super(options);
|
|
125
|
-
this.reducer = new SPEBase(options);
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Embeds the data given into the two-dimensional space using the original SPE method.
|
|
129
|
-
* @return {Coordinates} Cartesian coordinate of this embedding.
|
|
130
|
-
*/
|
|
131
|
-
transform() {
|
|
132
|
-
return this.reducer.embed(this.data);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Implements modified SPE dimensionality reduction.
|
|
137
|
-
*
|
|
138
|
-
* @class PSPEReducer
|
|
139
|
-
* @extends {Reducer}
|
|
140
|
-
*/
|
|
141
|
-
class PSPEReducer extends Reducer {
|
|
142
|
-
/**
|
|
143
|
-
* Creates an instance of PSPEReducer.
|
|
144
|
-
* @param {Options} options Options to pass to the constructor.
|
|
145
|
-
* @memberof PSPEReducer
|
|
146
|
-
*/
|
|
147
|
-
constructor(options) {
|
|
148
|
-
super(options);
|
|
149
|
-
this.reducer = new PSPEBase(options);
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Embeds the data given into the two-dimensional space using the modified SPE method.
|
|
153
|
-
* @return {Coordinates} Cartesian coordinate of this embedding.
|
|
154
|
-
*/
|
|
155
|
-
transform() {
|
|
156
|
-
return this.reducer.embed(this.data);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Unified class implementing different dimensionality reduction methods.
|
|
161
|
-
*
|
|
162
|
-
* @export
|
|
163
|
-
* @class DimensionalityReducer
|
|
164
|
-
*/
|
|
165
|
-
export class DimensionalityReducer {
|
|
166
|
-
/**
|
|
167
|
-
* Creates an instance of DimensionalityReducer.
|
|
168
|
-
* @param {any[]} data Vectors to embed.
|
|
169
|
-
* @param {string} method Embedding method to be applied
|
|
170
|
-
* @param {string} metric Distance metric to be computed between each of the vectors.
|
|
171
|
-
* @param {Options} [options] Options to pass to the implementing embedders.
|
|
172
|
-
* @memberof DimensionalityReducer
|
|
173
|
-
*/
|
|
174
|
-
constructor(data, method, metric, options) {
|
|
175
|
-
var _a;
|
|
176
|
-
this.methods = ['UMAP', 'TSNE', 'SPE', 'PSPE'];
|
|
177
|
-
if (!this.availableMethods.includes(method)) {
|
|
178
|
-
throw new Error('The method "' + method + '" is not supported');
|
|
179
|
-
}
|
|
180
|
-
this.measurer = new Measurer(metric);
|
|
181
|
-
const measure = this.measurer.getMeasure();
|
|
182
|
-
if (method == 'UMAP') {
|
|
183
|
-
this.reducer = new UMAPReducer({
|
|
184
|
-
...{ data: data },
|
|
185
|
-
...{ distanceFn: measure },
|
|
186
|
-
...{ nEpochs: options === null || options === void 0 ? void 0 : options.cycles },
|
|
187
|
-
...options
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
else if (method == 'TSNE') {
|
|
191
|
-
this.reducer = new TSNEReducer({
|
|
192
|
-
...{ data: data },
|
|
193
|
-
...{ distance: measure },
|
|
194
|
-
...{ iterations: (_a = options === null || options === void 0 ? void 0 : options.cycles) !== null && _a !== void 0 ? _a : undefined },
|
|
195
|
-
...options,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
else if (method == 'SPE') {
|
|
199
|
-
this.reducer = new SPEReducer({ ...{ data: data }, ...{ distance: measure }, ...options });
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
this.reducer = new PSPEReducer({ ...{ data: data }, ...{ distance: measure }, ...options });
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Embeds the data given into the two-dimensional space using the chosen method.
|
|
207
|
-
*
|
|
208
|
-
* @param {boolean} transpose Whether to transform coordinates to have columns-first orientation.
|
|
209
|
-
* @throws {Error} If the embedding method was not found.
|
|
210
|
-
* @return {Coordinates} Cartesian coordinate of this embedding.
|
|
211
|
-
* @memberof DimensionalityReducer
|
|
212
|
-
*/
|
|
213
|
-
transform(transpose = false) {
|
|
214
|
-
if (this.reducer == undefined) {
|
|
215
|
-
throw new Error('Reducer was not defined.');
|
|
216
|
-
}
|
|
217
|
-
let embedding = this.reducer.transform();
|
|
218
|
-
if (transpose) {
|
|
219
|
-
embedding = transposeMatrix(embedding);
|
|
220
|
-
}
|
|
221
|
-
return embedding;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Returns dimensionality reduction methods available.
|
|
225
|
-
*
|
|
226
|
-
* @readonly
|
|
227
|
-
* @memberof DimensionalityReducer
|
|
228
|
-
*/
|
|
229
|
-
get availableMethods() {
|
|
230
|
-
return this.methods;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdWNlLWRpbWVuc2lvbmFsaXR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVkdWNlLWRpbWVuc2lvbmFsaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxHQUFHLE1BQU0sU0FBUyxDQUFDO0FBQy9CLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFbkMsT0FBTyxFQUF1QyxNQUFNLEVBQWtCLE1BQU0scUJBQXFCLENBQUM7QUFDbEcsT0FBTyxFQUFDLGtCQUFrQixFQUFFLGVBQWUsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUNqRSxPQUFPLEVBQUMsT0FBTyxFQUFFLFFBQVEsRUFBQyxNQUFNLE9BQU8sQ0FBQztBQUN4QyxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDMUMsNERBQTREO0FBRTVEOzs7OztHQUtHO0FBQ0gsTUFBZSxPQUFPO0lBR3BCOzs7O09BSUc7SUFDSCxZQUFZLE9BQWdCO1FBQzFCLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztJQUMzQixDQUFDO0NBVUY7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sV0FBWSxTQUFRLE9BQU87SUFLL0I7Ozs7T0FJRztJQUNILFlBQVksT0FBZ0I7O1FBQzFCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakMsSUFBSSxDQUFDLFVBQVUsU0FBRyxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsVUFBVSxtQ0FBSSxHQUFHLENBQUM7UUFDN0MsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDO0lBQ25DLENBQUM7SUFFRDs7O09BR0c7SUFDSSxTQUFTO1FBQ2QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElB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ekMsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLFNBQVMsRUFBRTtZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7U0FDN0M7UUFDRCxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBRXpDLElBQUksU0FBUyxFQUFFO1lBQ2IsU0FBUyxHQUFHLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUN4QztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILElBQUksZ0JBQWdCO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB1bWogZnJvbSAndW1hcC1qcyc7XHJcbmltcG9ydCB7VFNORX0gZnJvbSAnQGtlY2tlbHQvdHNuZSc7XHJcblxyXG5pbXBvcnQge09wdGlvbnMsIERpc3RhbmNlTWV0cmljLCBDb29yZGluYXRlcywgVmVjdG9yLCBWZWN0b3JzLCBNYXRyaXh9IGZyb20gJy4vdHlwZV9kZWNsYXJhdGlvbnMnO1xyXG5pbXBvcnQge2NhbGNEaXN0YW5jZU1hdHJpeCwgdHJhbnNwb3NlTWF0cml4fSBmcm9tICcuL29wZXJhdGlvbnMnO1xyXG5pbXBvcnQge1NQRUJhc2UsIFBTUEVCYXNlfSBmcm9tICcuL3NwZSc7XHJcbmltcG9ydCB7TWVhc3VyZXJ9IGZyb20gJy4vc3RyaW5nLW1lYXN1cmUnO1xyXG4vL2ltcG9ydCB7QWxpZ25lZFNlcXVlbmNlRW5jb2Rlcn0gZnJvbSAnLi9zZXF1ZW5jZS1lbmNvZGVyJztcclxuXHJcbi8qKlxyXG4gKiBBYnN0cmFjdCBkaW1lbnNpb25hbGl0eSByZWR1Y2VyLlxyXG4gKlxyXG4gKiBAYWJzdHJhY3RcclxuICogQGNsYXNzIFJlZHVjZXJcclxuICovXHJcbmFic3RyYWN0IGNsYXNzIFJlZHVjZXIge1xyXG4gIHByb3RlY3RlZCBkYXRhOiBWZWN0b3JzO1xyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFJlZHVjZXIuXHJcbiAgICogQHBhcmFtIHtPcHRpb25zfSBvcHRpb25zIE9wdGlvbnMgdG8gcGFzcyB0byB0aGUgY29uc3RydWN0b3IuXHJcbiAgICogQG1lbWJlcm9mIFJlZHVjZXJcclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBPcHRpb25zKSB7XHJcbiAgICB0aGlzLmRhdGEgPSBvcHRpb25zLmRhdGE7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJcyB0byBlbWJlZCB0aGUgZGF0YSBnaXZlbiBpbnRvIHRoZSB0d28tZGltZW5zaW9uYWwgc3BhY2UuXHJcbiAgICpcclxuICAgKiBAYWJzdHJhY3RcclxuICAgKiBAcmV0dXJuIHtDb29yZGluYXRlc30gQ2FydGVzaWFuIGNvb3JkaW5hdGUgb2YgdGhpcyBlbWJlZGRpbmcuXHJcbiAgICogQG1lbWJlcm9mIFJlZHVjZXJcclxuICAgKi9cclxuICBhYnN0cmFjdCB0cmFuc2Zvcm0oKTogQ29vcmRpbmF0ZXM7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBJbXBsZW1lbnRzIHQtU05FIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbi5cclxuICpcclxuICogQGNsYXNzIFRTTkVSZWR1Y2VyXHJcbiAqIEBleHRlbmRzIHtSZWR1Y2VyfVxyXG4gKi9cclxuY2xhc3MgVFNORVJlZHVjZXIgZXh0ZW5kcyBSZWR1Y2VyIHtcclxuICBwcm90ZWN0ZWQgcmVkdWNlcjogVFNORTtcclxuICBwcm90ZWN0ZWQgaXRlcmF0aW9uczogbnVtYmVyO1xyXG4gIHByb3RlY3RlZCBkaXN0YW5jZTogRGlzdGFuY2VNZXRyaWM7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgVFNORVJlZHVjZXIuXHJcbiAgICogQHBhcmFtIHtPcHRpb25zfSBvcHRpb25zIE9wdGlvbnMgdG8gcGFzcyB0byB0aGUgY29uc3RydWN0b3IuXHJcbiAgICogQG1lbWJlcm9mIFRTTkVSZWR1Y2VyXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3Iob3B0aW9uczogT3B0aW9ucykge1xyXG4gICAgc3VwZXIob3B0aW9ucyk7XHJcbiAgICB0aGlzLnJlZHVjZXIgPSBuZXcgVFNORShvcHRpb25zKTtcclxuICAgIHRoaXMuaXRlcmF0aW9ucyA9IG9wdGlvbnM/Lml0ZXJhdGlvbnMgPz8gMTAwO1xyXG4gICAgdGhpcy5kaXN0YW5jZSA9IG9wdGlvbnMuZGlzdGFuY2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbWJlZHMgdGhlIGRhdGEgZ2l2ZW4gaW50byB0aGUgdHdvLWRpbWVuc2lvbmFsIHNwYWNlIHVzaW5nIHQtU05FIG1ldGhvZC5cclxuICAgKiBAcmV0dXJuIHtDb29yZGluYXRlc30gQ2FydGVzaWFuIGNvb3JkaW5hdGUgb2YgdGhpcyBlbWJlZGRpbmcuXHJcbiAgICovXHJcbiAgcHVibGljIHRyYW5zZm9ybSgpOiBDb29yZGluYXRlcyB7XHJcbiAgICB0aGlzLnJlZHVjZXIuaW5pdERhdGFEaXN0KGNhbGNEaXN0YW5jZU1hdHJpeCh0aGlzLmRhdGEsIHRoaXMuZGlzdGFuY2UpKTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaXRlcmF0aW9uczsgKytpKSB7XHJcbiAgICAgIHRoaXMucmVkdWNlci5zdGVwKCk7IC8vIGV2ZXJ5IHRpbWUgeW91IGNhbGwgdGhpcywgc29sdXRpb24gZ2V0cyBiZXR0ZXJcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLnJlZHVjZXIuZ2V0U29sdXRpb24oKTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBJbXBsZW1lbnRzIFVNQVAgZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uLlxyXG4gKlxyXG4gKiBAY2xhc3MgVU1BUFJlZHVjZXJcclxuICogQGV4dGVuZHMge1JlZHVjZXJ9XHJcbiAqL1xyXG5jbGFzcyBVTUFQUmVkdWNlciBleHRlbmRzIFJlZHVjZXIge1xyXG4gIHByb3RlY3RlZCByZWR1Y2VyOiB1bWouVU1BUDtcclxuLyogIHByb3RlY3RlZCBlbmNvZGVyOiBBbGlnbmVkU2VxdWVuY2VFbmNvZGVyO1xyXG4gIHByb3RlY3RlZCBkaXN0YW5jZU1hdHJpeDogTWF0cml4OyovXHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgVU1BUFJlZHVjZXIuXHJcbiAgICogQHBhcmFtIHtPcHRpb25zfSBvcHRpb25zIE9wdGlvbnMgdG8gcGFzcyB0byB0aGUgY29uc3RydWN0b3IuXHJcbiAgICogQG1lbWJlcm9mIFVNQVBSZWR1Y2VyXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3Iob3B0aW9uczogT3B0aW9ucykge1xyXG4gICAgc3VwZXIob3B0aW9ucyk7XHJcbiAgICB0aGlzLnJlZHVjZXIgPSBuZXcgdW1qLlVNQVAob3B0aW9ucyk7XHJcbi8qICAgIHRoaXMuZW5jb2RlciA9IG5ldyBBbGlnbmVkU2VxdWVuY2VFbmNvZGVyKCk7XHJcbiAgICB0aGlzLmRpc3RhbmNlTWF0cml4ID0gY2FsY0Rpc3RhbmNlTWF0cml4KHRoaXMuZGF0YSwgb3B0aW9ucy5kaXN0YW5jZUZuKTtcclxuICAgIHRoaXMuZGlzdGFuY2VGbiA9IG9wdGlvbnMuZGlzdGFuY2VGbjsqL1xyXG4gIH1cclxuXHJcbi8qICBwcm90ZWN0ZWQgX2VuY29kZWREaXN0YW5jZShhOiBudW1iZXJbXSwgYjogbnVtYmVyW10pOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuZGlzdGFuY2VNYXRyaXhbYVthLmxlbmd0aC0xXV1bYltiLmxlbmd0aC0xXV07XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgX2RlY29kZWREaXN0YW5jZShhOiBudW1iZXJbXSwgYjogbnVtYmVyW10pOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5kZWNvZGUoYSk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgZW5jb2RlKCk6IG51bWJlcltdW10ge1xyXG4gICAgbGV0IHZlY3RvcnM6IG51bWJlcltdW10gPSBbXTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZGF0YS5sZW5ndGg7ICsraSkge1xyXG4gICAgICBsZXQgZW5jb2RlZCA9IHRoaXMuZW5jb2Rlci5lbmNvZGUodGhpcy5kYXRhW2ldKTtcclxuICAgICAgdmVjdG9ycy5wdXNoKGVuY29kZWQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHZlY3RvcnM7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgX2NhbGNEaXN0YW5jZSgpIHtcclxuICAgIGNvbnN0IG5JdGVtcyA9IHRoaXMuZGF0YS5sZW5ndGg7XHJcbiAgICBjb25zdCB2ZWN0b3JzID0gdGhpcy5lbmNvZGUoKTtcclxuICAgIFxyXG4gIH0qL1xyXG5cclxuICAvKipcclxuICAgKiBFbWJlZHMgdGhlIGRhdGEgZ2l2ZW4gaW50byB0aGUgdHdvLWRpbWVuc2lvbmFsIHNwYWNlIHVzaW5nIFVNQVAgbWV0aG9kLlxyXG4gICAqIEByZXR1cm4ge0Nvb3JkaW5hdGVzfSBDYXJ0ZXNpYW4gY29vcmRpbmF0ZSBvZiB0aGlzIGVtYmVkZGluZy5cclxuICAgKi9cclxuICBwdWJsaWMgdHJhbnNmb3JtKCk6IENvb3JkaW5hdGVzIHtcclxuICAgIGNvbnN0IGVtYmVkZGluZyA9IHRoaXMucmVkdWNlci5maXQodGhpcy5kYXRhKTtcclxuXHJcbiAgICBmdW5jdGlvbiBhcnJheUNhc3QyQ29vcmRpbmF0ZXMoZGF0YTogbnVtYmVyW11bXSk6IENvb3JkaW5hdGVzIHtcclxuICAgICAgcmV0dXJuIG5ldyBBcnJheShkYXRhLmxlbmd0aCkuZmlsbCgwKS5tYXAoKF8sIGkpID0+IChWZWN0b3IuZnJvbShkYXRhW2ldKSkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFycmF5Q2FzdDJDb29yZGluYXRlcyhlbWJlZGRpbmcpO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEltcGxlbWVudHMgb3JpZ2luYWwgU1BFIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbi5cclxuICpcclxuICogQGNsYXNzIFNQRVJlZHVjZXJcclxuICogQGV4dGVuZHMge1JlZHVjZXJ9XHJcbiAqL1xyXG5jbGFzcyBTUEVSZWR1Y2VyIGV4dGVuZHMgUmVkdWNlciB7XHJcbiAgcHJvdGVjdGVkIHJlZHVjZXI6IFNQRUJhc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgU1BFUmVkdWNlci5cclxuICAgKiBAcGFyYW0ge09wdGlvbnN9IG9wdGlvbnMgT3B0aW9ucyB0byBwYXNzIHRvIHRoZSBjb25zdHJ1Y3Rvci5cclxuICAgKiBAbWVtYmVyb2YgU1BFUmVkdWNlclxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IE9wdGlvbnMpIHtcclxuICAgIHN1cGVyKG9wdGlvbnMpO1xyXG4gICAgdGhpcy5yZWR1Y2VyID0gbmV3IFNQRUJhc2Uob3B0aW9ucyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbWJlZHMgdGhlIGRhdGEgZ2l2ZW4gaW50byB0aGUgdHdvLWRpbWVuc2lvbmFsIHNwYWNlIHVzaW5nIHRoZSBvcmlnaW5hbCBTUEUgbWV0aG9kLlxyXG4gICAqIEByZXR1cm4ge0Nvb3JkaW5hdGVzfSBDYXJ0ZXNpYW4gY29vcmRpbmF0ZSBvZiB0aGlzIGVtYmVkZGluZy5cclxuICAgKi9cclxuICBwdWJsaWMgdHJhbnNmb3JtKCk6IENvb3JkaW5hdGVzIHtcclxuICAgIHJldHVybiB0aGlzLnJlZHVjZXIuZW1iZWQodGhpcy5kYXRhKTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBJbXBsZW1lbnRzIG1vZGlmaWVkIFNQRSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24uXHJcbiAqXHJcbiAqIEBjbGFzcyBQU1BFUmVkdWNlclxyXG4gKiBAZXh0ZW5kcyB7UmVkdWNlcn1cclxuICovXHJcbmNsYXNzIFBTUEVSZWR1Y2VyIGV4dGVuZHMgUmVkdWNlciB7XHJcbiAgcHJvdGVjdGVkIHJlZHVjZXI6IFBTUEVCYXNlO1xyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFBTUEVSZWR1Y2VyLlxyXG4gICAqIEBwYXJhbSB7T3B0aW9uc30gb3B0aW9ucyBPcHRpb25zIHRvIHBhc3MgdG8gdGhlIGNvbnN0cnVjdG9yLlxyXG4gICAqIEBtZW1iZXJvZiBQU1BFUmVkdWNlclxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IE9wdGlvbnMpIHtcclxuICAgIHN1cGVyKG9wdGlvbnMpO1xyXG4gICAgdGhpcy5yZWR1Y2VyID0gbmV3IFBTUEVCYXNlKG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRW1iZWRzIHRoZSBkYXRhIGdpdmVuIGludG8gdGhlIHR3by1kaW1lbnNpb25hbCBzcGFjZSB1c2luZyB0aGUgbW9kaWZpZWQgU1BFIG1ldGhvZC5cclxuICAgKiBAcmV0dXJuIHtDb29yZGluYXRlc30gQ2FydGVzaWFuIGNvb3JkaW5hdGUgb2YgdGhpcyBlbWJlZGRpbmcuXHJcbiAgICovXHJcbiAgcHVibGljIHRyYW5zZm9ybSgpOiBDb29yZGluYXRlcyB7XHJcbiAgICByZXR1cm4gdGhpcy5yZWR1Y2VyLmVtYmVkKHRoaXMuZGF0YSk7XHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogVW5pZmllZCBjbGFzcyBpbXBsZW1lbnRpbmcgZGlmZmVyZW50IGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiBtZXRob2RzLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBjbGFzcyBEaW1lbnNpb25hbGl0eVJlZHVjZXJcclxuICovXHJcbmV4cG9ydCBjbGFzcyBEaW1lbnNpb25hbGl0eVJlZHVjZXIge1xyXG4gIHByaXZhdGUgcmVkdWNlcjogUmVkdWNlciB8IHVuZGVmaW5lZDtcclxuICBwcml2YXRlIG1ldGhvZHM6IHN0cmluZ1tdO1xyXG4gIHByaXZhdGUgbWVhc3VyZXI6IE1lYXN1cmVyO1xyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIERpbWVuc2lvbmFsaXR5UmVkdWNlci5cclxuICAgKiBAcGFyYW0ge2FueVtdfSBkYXRhIFZlY3RvcnMgdG8gZW1iZWQuXHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCBFbWJlZGRpbmcgbWV0aG9kIHRvIGJlIGFwcGxpZWRcclxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0cmljIERpc3RhbmNlIG1ldHJpYyB0byBiZSBjb21wdXRlZCBiZXR3ZWVuIGVhY2ggb2YgdGhlIHZlY3RvcnMuXHJcbiAgICogQHBhcmFtIHtPcHRpb25zfSBbb3B0aW9uc10gT3B0aW9ucyB0byBwYXNzIHRvIHRoZSBpbXBsZW1lbnRpbmcgZW1iZWRkZXJzLlxyXG4gICAqIEBtZW1iZXJvZiBEaW1lbnNpb25hbGl0eVJlZHVjZXJcclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihkYXRhOiBhbnlbXSwgbWV0aG9kOiBzdHJpbmcsIG1ldHJpYzogc3RyaW5nLCBvcHRpb25zPzogT3B0aW9ucykge1xyXG4gICAgdGhpcy5tZXRob2RzID0gWydVTUFQJywgJ1RTTkUnLCAnU1BFJywgJ1BTUEUnXTtcclxuXHJcbiAgICBpZiAoIXRoaXMuYXZhaWxhYmxlTWV0aG9kcy5pbmNsdWRlcyhtZXRob2QpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIG1ldGhvZCBcIicrbWV0aG9kKydcIiBpcyBub3Qgc3VwcG9ydGVkJyk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5tZWFzdXJlciA9IG5ldyBNZWFzdXJlcihtZXRyaWMpO1xyXG4gICAgY29uc3QgbWVhc3VyZSA9IHRoaXMubWVhc3VyZXIuZ2V0TWVhc3VyZSgpXHJcblxyXG4gICAgaWYgKG1ldGhvZCA9PSAnVU1BUCcpIHtcclxuICAgICAgdGhpcy5yZWR1Y2VyID0gbmV3IFVNQVBSZWR1Y2VyKHtcclxuICAgICAgICAuLi57ZGF0YTogZGF0YX0sIFxyXG4gICAgICAgIC4uLntkaXN0YW5jZUZuOiBtZWFzdXJlfSwgXHJcbiAgICAgICAgLi4ue25FcG9jaHM6IG9wdGlvbnM/LmN5Y2xlc30sXHJcbiAgICAgICAgLi4ub3B0aW9uc1xyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSBpZiAobWV0aG9kID09ICdUU05FJykge1xyXG4gICAgICB0aGlzLnJlZHVjZXIgPSBuZXcgVFNORVJlZHVjZXIoe1xyXG4gICAgICAgIC4uLntkYXRhOiBkYXRhfSxcclxuICAgICAgICAuLi57ZGlzdGFuY2U6IG1lYXN1cmV9LFxyXG4gICAgICAgIC4uLntpdGVyYXRpb25zOiBvcHRpb25zPy5jeWNsZXMgPz8gdW5kZWZpbmVkfSxcclxuICAgICAgICAuLi5vcHRpb25zLFxyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSBpZiAobWV0aG9kID09ICdTUEUnKSB7XHJcbiAgICAgIHRoaXMucmVkdWNlciA9IG5ldyBTUEVSZWR1Y2VyKHsuLi57ZGF0YTogZGF0YX0sIC4uLntkaXN0YW5jZTogbWVhc3VyZX0sIC4uLm9wdGlvbnN9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMucmVkdWNlciA9IG5ldyBQU1BFUmVkdWNlcih7Li4ue2RhdGE6IGRhdGF9LCAuLi57ZGlzdGFuY2U6IG1lYXN1cmV9LCAuLi5vcHRpb25zfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbWJlZHMgdGhlIGRhdGEgZ2l2ZW4gaW50byB0aGUgdHdvLWRpbWVuc2lvbmFsIHNwYWNlIHVzaW5nIHRoZSBjaG9zZW4gbWV0aG9kLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtib29sZWFufSB0cmFuc3Bvc2UgV2hldGhlciB0byB0cmFuc2Zvcm0gY29vcmRpbmF0ZXMgdG8gaGF2ZSBjb2x1bW5zLWZpcnN0IG9yaWVudGF0aW9uLlxyXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZW1iZWRkaW5nIG1ldGhvZCB3YXMgbm90IGZvdW5kLlxyXG4gICAqIEByZXR1cm4ge0Nvb3JkaW5hdGVzfSBDYXJ0ZXNpYW4gY29vcmRpbmF0ZSBvZiB0aGlzIGVtYmVkZGluZy5cclxuICAgKiBAbWVtYmVyb2YgRGltZW5zaW9uYWxpdHlSZWR1Y2VyXHJcbiAgICovXHJcbiAgcHVibGljIHRyYW5zZm9ybSh0cmFuc3Bvc2U6IGJvb2xlYW4gPSBmYWxzZSk6IENvb3JkaW5hdGVzIHtcclxuICAgIGlmICh0aGlzLnJlZHVjZXIgPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVkdWNlciB3YXMgbm90IGRlZmluZWQuJyk7XHJcbiAgICB9XHJcbiAgICBsZXQgZW1iZWRkaW5nID0gdGhpcy5yZWR1Y2VyLnRyYW5zZm9ybSgpO1xyXG5cclxuICAgIGlmICh0cmFuc3Bvc2UpIHtcclxuICAgICAgZW1iZWRkaW5nID0gdHJhbnNwb3NlTWF0cml4KGVtYmVkZGluZyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZW1iZWRkaW5nO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gbWV0aG9kcyBhdmFpbGFibGUuXHJcbiAgICpcclxuICAgKiBAcmVhZG9ubHlcclxuICAgKiBAbWVtYmVyb2YgRGltZW5zaW9uYWxpdHlSZWR1Y2VyXHJcbiAgICovXHJcbiAgZ2V0IGF2YWlsYWJsZU1ldGhvZHMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzO1xyXG4gIH1cclxufVxyXG4iXX0=
|
package/src/sequence-encoder.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { assert } from './operations';
|
|
2
|
-
/**
|
|
3
|
-
* Class to categorial encode/decode aligned amino acid residues sequence.
|
|
4
|
-
*
|
|
5
|
-
* @export
|
|
6
|
-
* @class AlignedSequenceEncoder
|
|
7
|
-
*/
|
|
8
|
-
export class AlignedSequenceEncoder {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.aa2num = {
|
|
11
|
-
'-': 0,
|
|
12
|
-
'A': 1,
|
|
13
|
-
'C': 2,
|
|
14
|
-
'D': 3,
|
|
15
|
-
'E': 4,
|
|
16
|
-
'F': 5,
|
|
17
|
-
'G': 6,
|
|
18
|
-
'H': 7,
|
|
19
|
-
'I': 8,
|
|
20
|
-
'K': 9,
|
|
21
|
-
'L': 10,
|
|
22
|
-
'M': 11,
|
|
23
|
-
'N': 12,
|
|
24
|
-
'P': 13,
|
|
25
|
-
'Q': 14,
|
|
26
|
-
'R': 15,
|
|
27
|
-
'S': 16,
|
|
28
|
-
'T': 17,
|
|
29
|
-
'V': 18,
|
|
30
|
-
'W': 19,
|
|
31
|
-
'Y': 20,
|
|
32
|
-
};
|
|
33
|
-
this.num2aa = {};
|
|
34
|
-
Object.entries(this.aa2num).forEach(([k, v]) => (this.num2aa[v] = k));
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Truncate NH2 and -COOH terminals of the given sequence.
|
|
38
|
-
*
|
|
39
|
-
* @protected
|
|
40
|
-
* @param {string} seq The sequence provided.
|
|
41
|
-
* @return {string} Truncated sequence.
|
|
42
|
-
* @memberof AlignedSequenceEncoder
|
|
43
|
-
*/
|
|
44
|
-
_truncateSequence(seq) {
|
|
45
|
-
let start = 0;
|
|
46
|
-
let end = seq.length;
|
|
47
|
-
const termina = ['NH2', 'COOH'];
|
|
48
|
-
if (seq.startsWith(termina[0])) {
|
|
49
|
-
const l = termina[0].length; // Cut only 'NH2' without following '-'.
|
|
50
|
-
assert(seq[l] == '-', `Wrong sequence format: ${termina[0]} without following '-' in '${seq}'.`);
|
|
51
|
-
start = l;
|
|
52
|
-
}
|
|
53
|
-
if (seq.endsWith(termina[1])) {
|
|
54
|
-
const l = termina[1].length + 1; // Cut both 'COOH' and precending '-'.
|
|
55
|
-
assert(seq[end - l] == '-', `Wrong sequence format: ${termina[1]} without '-' precending in '${seq}'.`);
|
|
56
|
-
end -= l;
|
|
57
|
-
}
|
|
58
|
-
return seq.substring(start, end);
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Cuts auxiliary defises before a residue.
|
|
62
|
-
*
|
|
63
|
-
* @protected
|
|
64
|
-
* @param {string} seq The sequence to process.
|
|
65
|
-
* @return {string} Processed sequence.
|
|
66
|
-
* @memberof AlignedSequenceEncoder
|
|
67
|
-
*/
|
|
68
|
-
_dropDefises(seq) {
|
|
69
|
-
return seq.replace(/(-)([^-]+)/g, '$2');
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Performs truncation and cutting auxiliary defises.
|
|
73
|
-
*
|
|
74
|
-
* @param {string} sequence The sequence work under process.
|
|
75
|
-
* @return {string} Result of cleaning.
|
|
76
|
-
* @memberof AlignedSequenceEncoder
|
|
77
|
-
*/
|
|
78
|
-
clean(sequence) {
|
|
79
|
-
return this._dropDefises(this._truncateSequence(sequence));
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Categorial encode of the sequence provided.
|
|
83
|
-
*
|
|
84
|
-
* @param {string} sequence The sequence.
|
|
85
|
-
* @return {number[]} Encoded vector.
|
|
86
|
-
* @memberof AlignedSequenceEncoder
|
|
87
|
-
*/
|
|
88
|
-
encode(sequence) {
|
|
89
|
-
const seq = this.clean(sequence);
|
|
90
|
-
const nItems = seq.length;
|
|
91
|
-
let values = new Array(nItems).fill(0);
|
|
92
|
-
for (let i = 0; i < nItems; ++i) {
|
|
93
|
-
let char = seq[i];
|
|
94
|
-
assert(char in this.aa2num, `Unknown char '${char}' found in sequence '${seq}'`);
|
|
95
|
-
values[i] = this.aa2num[char];
|
|
96
|
-
}
|
|
97
|
-
return values;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Decode the encoded vector into the sequence back.
|
|
101
|
-
*
|
|
102
|
-
* @param {number[]} value The vector encoded.
|
|
103
|
-
* @return {string} Decoded sequence.
|
|
104
|
-
* @memberof AlignedSequenceEncoder
|
|
105
|
-
*/
|
|
106
|
-
decode(value) {
|
|
107
|
-
let s = '';
|
|
108
|
-
for (let i = 0; i < value.length; ++i) {
|
|
109
|
-
let code = value[i];
|
|
110
|
-
assert(code in this.num2aa, `Unknown code '${code}' found in vector '${value}'`);
|
|
111
|
-
s += this.num2aa[code];
|
|
112
|
-
}
|
|
113
|
-
return s;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVuY2UtZW5jb2Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNlcXVlbmNlLWVuY29kZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUVwQzs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxzQkFBc0I7SUFJL0I7UUFDSSxJQUFJLENBQUMsTUFBTSxHQUFHO1lBQ1YsR0FBRyxFQUFFLENBQUM7WUFDTixHQUFHLEVBQUUsQ0FBQztZQUNOLEdBQUcsRUFBRSxDQUFDO1lBQ04sR0FBRyxFQUFFLENBQUM7WUFDTixHQUFHLEVBQUUsQ0FBQztZQUNOLEdBQUcsRUFBRSxDQUFDO1lBQ04sR0FBRyxFQUFFLENBQUM7WUFDTixHQUFHLEVBQUUsQ0FBQztZQUNOLEdBQUcsRUFBRSxDQUFDO1lBQ04sR0FBRyxFQUFFLENBQUM7WUFDTixHQUFHLEVBQUUsRUFBRTtZQUNQLEdBQUcsRUFBRSxFQUFFO1lBQ1AsR0FBRyxFQUFFLEVBQUU7WUFDUCxHQUFHLEVBQUUsRUFBRTtZQUNQLEdBQUcsRUFBRSxFQUFFO1lBQ1AsR0FBRyxFQUFFLEVBQUU7WUFDUCxHQUFHLEVBQUUsRUFBRTtZQUNQLEdBQUcsRUFBRSxFQUFFO1lBQ1AsR0FBRyxFQUFFLEVBQUU7WUFDUCxHQUFHLEVBQUUsRUFBRTtZQUNQLEdBQUcsRUFBRSxFQUFFO1NBQ1YsQ0FBQztRQUNGLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNPLGlCQUFpQixDQUFDLEdB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LENBQUM7U0FDMUI7UUFDRCxPQUFPLENBQUMsQ0FBQztJQUNiLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7YXNzZXJ0fSBmcm9tICcuL29wZXJhdGlvbnMnO1xyXG5cclxuLyoqXHJcbiAqIENsYXNzIHRvIGNhdGVnb3JpYWwgZW5jb2RlL2RlY29kZSBhbGlnbmVkIGFtaW5vIGFjaWQgcmVzaWR1ZXMgc2VxdWVuY2UuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQGNsYXNzIEFsaWduZWRTZXF1ZW5jZUVuY29kZXJcclxuICovXHJcbmV4cG9ydCBjbGFzcyBBbGlnbmVkU2VxdWVuY2VFbmNvZGVyIHtcclxuICAgIHByb3RlY3RlZCBhYTJudW06IHtbbmFtZTogc3RyaW5nXTogbnVtYmVyfTtcclxuICAgIHByb3RlY3RlZCBudW0yYWE6IHtbY29kZTogbnVtYmVyXTogc3RyaW5nfTtcclxuXHJcbiAgICBjb25zdHJ1Y3RvciAoKSB7XHJcbiAgICAgICAgdGhpcy5hYTJudW0gPSB7XHJcbiAgICAgICAgICAgICctJzogMCxcclxuICAgICAgICAgICAgJ0EnOiAxLFxyXG4gICAgICAgICAgICAnQyc6IDIsXHJcbiAgICAgICAgICAgICdEJzogMyxcclxuICAgICAgICAgICAgJ0UnOiA0LFxyXG4gICAgICAgICAgICAnRic6IDUsXHJcbiAgICAgICAgICAgICdHJzogNixcclxuICAgICAgICAgICAgJ0gnOiA3LFxyXG4gICAgICAgICAgICAnSSc6IDgsXHJcbiAgICAgICAgICAgICdLJzogOSxcclxuICAgICAgICAgICAgJ0wnOiAxMCxcclxuICAgICAgICAgICAgJ00nOiAxMSxcclxuICAgICAgICAgICAgJ04nOiAxMixcclxuICAgICAgICAgICAgJ1AnOiAxMyxcclxuICAgICAgICAgICAgJ1EnOiAxNCxcclxuICAgICAgICAgICAgJ1InOiAxNSxcclxuICAgICAgICAgICAgJ1MnOiAxNixcclxuICAgICAgICAgICAgJ1QnOiAxNyxcclxuICAgICAgICAgICAgJ1YnOiAxOCxcclxuICAgICAgICAgICAgJ1cnOiAxOSxcclxuICAgICAgICAgICAgJ1knOiAyMCxcclxuICAgICAgICB9O1xyXG4gICAgICAgIHRoaXMubnVtMmFhID0ge307XHJcbiAgICAgICAgT2JqZWN0LmVudHJpZXModGhpcy5hYTJudW0pLmZvckVhY2goKFtrLCB2XSkgPT4gKHRoaXMubnVtMmFhW3ZdID0gaykpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHJ1bmNhdGUgTkgyIGFuZCAtQ09PSCB0ZXJtaW5hbHMgb2YgdGhlIGdpdmVuIHNlcXVlbmNlLlxyXG4gICAgICpcclxuICAgICAqIEBwcm90ZWN0ZWRcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzZXEgVGhlIHNlcXVlbmNlIHByb3ZpZGVkLlxyXG4gICAgICogQHJldHVybiB7c3RyaW5nfSBUcnVuY2F0ZWQgc2VxdWVuY2UuXHJcbiAgICAgKiBAbWVtYmVyb2YgQWxpZ25lZFNlcXVlbmNlRW5jb2RlclxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgX3RydW5jYXRlU2VxdWVuY2Uoc2VxOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGxldCBzdGFydCA9IDA7XHJcbiAgICAgICAgbGV0IGVuZCA9IHNlcS5sZW5ndGg7XHJcbiAgICAgICAgY29uc3QgdGVybWluYSA9IFsnTkgyJywgJ0NPT0gnXTtcclxuICAgIFxyXG4gICAgICAgIGlmIChzZXEuc3RhcnRzV2l0aCh0ZXJtaW5hWzBdKSkge1xyXG4gICAgICAgICAgICBjb25zdCBsID0gdGVybWluYVswXS5sZW5ndGg7IC8vIEN1dCBvbmx5ICdOSDInIHdpdGhvdXQgZm9sbG93aW5nICctJy5cclxuICAgICAgICAgICAgYXNzZXJ0KHNlcVtsXSA9PSAnLScsIGBXcm9uZyBzZXF1ZW5jZSBmb3JtYXQ6ICR7dGVybWluYVswXX0gd2l0aG91dCBmb2xsb3dpbmcgJy0nIGluICcke3NlcX0nLmApXHJcbiAgICAgICAgICAgIHN0YXJ0ID0gbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHNlcS5lbmRzV2l0aCh0ZXJtaW5hWzFdKSkge1xyXG4gICAgICAgICAgICBjb25zdCBsID0gdGVybWluYVsxXS5sZW5ndGgrMTsgLy8gQ3V0IGJvdGggJ0NPT0gnIGFuZCBwcmVjZW5kaW5nICctJy5cclxuICAgICAgICAgICAgYXNzZXJ0KHNlcVtlbmQtbF0gPT0gJy0nLCBgV3Jvbmcgc2VxdWVuY2UgZm9ybWF0OiAke3Rlcm1pbmFbMV19IHdpdGhvdXQgJy0nIHByZWNlbmRpbmcgaW4gJyR7c2VxfScuYClcclxuICAgICAgICAgICAgZW5kIC09IGw7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBzZXEuc3Vic3RyaW5nKHN0YXJ0LCBlbmQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3V0cyBhdXhpbGlhcnkgZGVmaXNlcyBiZWZvcmUgYSByZXNpZHVlLlxyXG4gICAgICpcclxuICAgICAqIEBwcm90ZWN0ZWRcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzZXEgVGhlIHNlcXVlbmNlIHRvIHByb2Nlc3MuXHJcbiAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IFByb2Nlc3NlZCBzZXF1ZW5jZS5cclxuICAgICAqIEBtZW1iZXJvZiBBbGlnbmVkU2VxdWVuY2VFbmNvZGVyXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBfZHJvcERlZmlzZXMoc2VxOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBzZXEucmVwbGFjZSgvKC0pKFteLV0rKS9nLCAnJDInKVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGVyZm9ybXMgdHJ1bmNhdGlvbiBhbmQgY3V0dGluZyBhdXhpbGlhcnkgZGVmaXNlcy5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VxdWVuY2UgVGhlIHNlcXVlbmNlIHdvcmsgdW5kZXIgcHJvY2Vzcy5cclxuICAgICAqIEByZXR1cm4ge3N0cmluZ30gUmVzdWx0IG9mIGNsZWFuaW5nLlxyXG4gICAgICogQG1lbWJlcm9mIEFsaWduZWRTZXF1ZW5jZUVuY29kZXJcclxuICAgICAqL1xyXG4gICAgcHVibGljIGNsZWFuKHNlcXVlbmNlOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9kcm9wRGVmaXNlcyh0aGlzLl90cnVuY2F0ZVNlcXVlbmNlKHNlcXVlbmNlKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDYXRlZ29yaWFsIGVuY29kZSBvZiB0aGUgc2VxdWVuY2UgcHJvdmlkZWQuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcXVlbmNlIFRoZSBzZXF1ZW5jZS5cclxuICAgICAqIEByZXR1cm4ge251bWJlcltdfSBFbmNvZGVkIHZlY3Rvci5cclxuICAgICAqIEBtZW1iZXJvZiBBbGlnbmVkU2VxdWVuY2VFbmNvZGVyXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBlbmNvZGUoc2VxdWVuY2U6IHN0cmluZyk6IG51bWJlcltdIHtcclxuICAgICAgICBjb25zdCBzZXEgPSB0aGlzLmNsZWFuKHNlcXVlbmNlKTtcclxuICAgICAgICBjb25zdCBuSXRlbXMgPSBzZXEubGVuZ3RoO1xyXG4gICAgICAgIGxldCB2YWx1ZXMgPSBuZXcgQXJyYXkobkl0ZW1zKS5maWxsKDApO1xyXG4gICAgXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuSXRlbXM7ICsraSkge1xyXG4gICAgICAgICAgICBsZXQgY2hhciA9IHNlcVtpXTtcclxuICAgIFxyXG4gICAgICAgICAgICBhc3NlcnQoY2hhciBpbiB0aGlzLmFhMm51bSwgYFVua25vd24gY2hhciAnJHtjaGFyfScgZm91bmQgaW4gc2VxdWVuY2UgJyR7c2VxfSdgKTtcclxuICAgIFxyXG4gICAgICAgICAgICB2YWx1ZXNbaV0gPSB0aGlzLmFhMm51bVtjaGFyXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHZhbHVlcztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERlY29kZSB0aGUgZW5jb2RlZCB2ZWN0b3IgaW50byB0aGUgc2VxdWVuY2UgYmFjay5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcltdfSB2YWx1ZSBUaGUgdmVjdG9yIGVuY29kZWQuXHJcbiAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IERlY29kZWQgc2VxdWVuY2UuXHJcbiAgICAgKiBAbWVtYmVyb2YgQWxpZ25lZFNlcXVlbmNlRW5jb2RlclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZGVjb2RlKHZhbHVlOiBudW1iZXJbXSk6IHN0cmluZyB7XHJcbiAgICAgICAgbGV0IHM6IHN0cmluZyA9ICcnO1xyXG4gICAgXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgICAgICBsZXQgY29kZSA9IHZhbHVlW2ldO1xyXG5cclxuICAgICAgICAgICAgYXNzZXJ0KGNvZGUgaW4gdGhpcy5udW0yYWEsIGBVbmtub3duIGNvZGUgJyR7Y29kZX0nIGZvdW5kIGluIHZlY3RvciAnJHt2YWx1ZX0nYCk7XHJcblxyXG4gICAgICAgICAgICBzICs9IHRoaXMubnVtMmFhW2NvZGVdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcztcclxuICAgIH1cclxufVxyXG4iXX0=
|