peptide-score 2.3.14
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/LICENSE +22 -0
- package/README.md +149 -0
- package/lib/src/allowNeutralLoss.d.ts +7 -0
- package/lib/src/allowNeutralLoss.d.ts.map +1 -0
- package/lib/src/allowNeutralLoss.js +25 -0
- package/lib/src/allowNeutralLoss.js.map +1 -0
- package/lib/src/aminoAcids.d.ts +29 -0
- package/lib/src/aminoAcids.d.ts.map +1 -0
- package/lib/src/aminoAcids.js +247 -0
- package/lib/src/aminoAcids.js.map +1 -0
- package/lib/src/chargePeptide.d.ts +2 -0
- package/lib/src/chargePeptide.d.ts.map +1 -0
- package/lib/src/chargePeptide.js +50 -0
- package/lib/src/chargePeptide.js.map +1 -0
- package/lib/src/digestPeptide.d.ts +2 -0
- package/lib/src/digestPeptide.d.ts.map +1 -0
- package/lib/src/digestPeptide.js +83 -0
- package/lib/src/digestPeptide.js.map +1 -0
- package/lib/src/generatePeptideFragments.d.ts +2 -0
- package/lib/src/generatePeptideFragments.d.ts.map +1 -0
- package/lib/src/generatePeptideFragments.js +89 -0
- package/lib/src/generatePeptideFragments.js.map +1 -0
- package/lib/src/getAA.d.ts +29 -0
- package/lib/src/getAA.d.ts.map +1 -0
- package/lib/src/getAA.js +21 -0
- package/lib/src/getAA.js.map +1 -0
- package/lib/src/index.d.ts +44 -0
- package/lib/src/index.d.ts.map +1 -0
- package/lib/src/index.js +74 -0
- package/lib/src/index.js.map +1 -0
- package/lib/src/isoElectricPoint.d.ts +10 -0
- package/lib/src/isoElectricPoint.d.ts.map +1 -0
- package/lib/src/isoElectricPoint.js +134 -0
- package/lib/src/isoElectricPoint.js.map +1 -0
- package/lib/src/sequenceToMF.d.ts +2 -0
- package/lib/src/sequenceToMF.d.ts.map +1 -0
- package/lib/src/sequenceToMF.js +99 -0
- package/lib/src/sequenceToMF.js.map +1 -0
- package/lib/src/splitPeptide.d.ts +2 -0
- package/lib/src/splitPeptide.d.ts.map +1 -0
- package/lib/src/splitPeptide.js +17 -0
- package/lib/src/splitPeptide.js.map +1 -0
- package/lib/tsconfig.build.tsbuildinfo +1 -0
- package/lib/tsconfig.test.tsbuildinfo +1 -0
- package/package.json +29 -0
- package/src/allowNeutralLoss.js +22 -0
- package/src/aminoAcids.js +244 -0
- package/src/chargePeptide.js +48 -0
- package/src/digestPeptide.js +87 -0
- package/src/generatePeptideFragments.js +89 -0
- package/src/getAA.js +18 -0
- package/src/index.js +37 -0
- package/src/isoElectricPoint.js +124 -0
- package/src/sequenceToMF.js +96 -0
- package/src/splitPeptide.js +13 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getAA } from './getAA';
|
|
2
|
+
|
|
3
|
+
// SOURCE: https://en.wikipedia.org/wiki/Amino_acid
|
|
4
|
+
|
|
5
|
+
export function chargePeptide(mf, options = {}) {
|
|
6
|
+
if (Array.isArray(mf)) {
|
|
7
|
+
for (let i = 0; i < mf.length; i++) {
|
|
8
|
+
mf[i] = chargeOnePeptide(mf[i], options);
|
|
9
|
+
}
|
|
10
|
+
return mf;
|
|
11
|
+
} else {
|
|
12
|
+
return chargeOnePeptide(mf, options);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function chargeOnePeptide(mf, options) {
|
|
17
|
+
const { pH = 0 } = options;
|
|
18
|
+
// we will allow to charge the peptide at a specific pH
|
|
19
|
+
|
|
20
|
+
// first amino acids (N-terminal)
|
|
21
|
+
if (mf.match(/^H[A-Z][a-z]{2}/)) {
|
|
22
|
+
let firstAA = mf.replace(/^H([A-Z][a-z]{2}).*/, '$1');
|
|
23
|
+
if (getAA(firstAA) && pH < getAA(firstAA).pKaN) {
|
|
24
|
+
mf = mf.replace(/^H([^+])/, 'H+H$1');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// last amino acids (C-terminal)
|
|
29
|
+
if (mf.match(/[A-Z][a-z]{2}OH$/)) {
|
|
30
|
+
let lastAA = mf.replace(/.*([A-Z][a-z]{2})OH$/, '$1');
|
|
31
|
+
if (getAA(lastAA) && pH > getAA(lastAA).pKaC) {
|
|
32
|
+
mf = mf.replace(/OH$/, 'O-');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// basic AA
|
|
37
|
+
if (pH < getAA('Arg').sc.pKa) mf = mf.replaceAll(/(Arg)(?!\()/g, '$1(H+)');
|
|
38
|
+
if (pH < getAA('His').sc.pKa) mf = mf.replaceAll(/(His)(?!\()/g, '$1(H+)');
|
|
39
|
+
if (pH < getAA('Lys').sc.pKa) mf = mf.replaceAll(/(Lys)(?!\()/g, '$1(H+)');
|
|
40
|
+
|
|
41
|
+
// acid AA
|
|
42
|
+
if (pH > getAA('Asp').sc.pKa) mf = mf.replaceAll(/(Asp)(?!\()/g, '$1(H-1-)');
|
|
43
|
+
if (pH > getAA('Glu').sc.pKa) mf = mf.replaceAll(/(Glu)(?!\()/g, '$1(H-1-)');
|
|
44
|
+
|
|
45
|
+
if (pH > getAA('Cys').sc.pKa) mf = mf.replaceAll(/(Cys)(?!\()/g, '$1(H-1-)');
|
|
46
|
+
|
|
47
|
+
return mf;
|
|
48
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Iotuibs:
|
|
3
|
+
* minMissed (default: 0)
|
|
4
|
+
* maxMissed (default: 0)
|
|
5
|
+
* minResidue: 0;
|
|
6
|
+
* maxResidue: infinity
|
|
7
|
+
* enzyme: chymotrypsin, trypsin, glucph4, glucph8, thermolysin, cyanogenbromide : Mandatory, no default value !
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export function digestPeptide(sequence, options = {}) {
|
|
11
|
+
sequence = sequence.replace(/^H([^a-z])/, '$1').replace(/OH$/, '');
|
|
12
|
+
options.enzyme = options.enzyme || 'trypsin';
|
|
13
|
+
if (options.minMissed === undefined) options.minMissed = 0;
|
|
14
|
+
if (options.maxMissed === undefined) options.maxMissed = 0;
|
|
15
|
+
if (options.minResidue === undefined) options.minResidue = 0;
|
|
16
|
+
if (options.maxResidue === undefined) options.maxResidue = Number.MAX_VALUE;
|
|
17
|
+
let regexp = getRegexp(options.enzyme);
|
|
18
|
+
let fragments = sequence.replace(regexp, '$1 ').split(/ /).filter(Boolean);
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
let from = 0;
|
|
22
|
+
for (let i = 0; i < fragments.length; i++) {
|
|
23
|
+
let nbResidue = fragments[i]
|
|
24
|
+
.replaceAll(/([A-Z][a-z]{2})/g, ' $1')
|
|
25
|
+
.split(/ /)
|
|
26
|
+
.filter(Boolean).length;
|
|
27
|
+
fragments[i] = {
|
|
28
|
+
sequence: fragments[i],
|
|
29
|
+
nbResidue,
|
|
30
|
+
from,
|
|
31
|
+
to: from + nbResidue - 1,
|
|
32
|
+
};
|
|
33
|
+
from += nbResidue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let results = [];
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < fragments.length - options.minMissed; i++) {
|
|
40
|
+
for (
|
|
41
|
+
let j = options.minMissed;
|
|
42
|
+
j <= Math.min(options.maxMissed, fragments.length - i - 1);
|
|
43
|
+
j++
|
|
44
|
+
) {
|
|
45
|
+
let fragment = '';
|
|
46
|
+
let nbResidue = 0;
|
|
47
|
+
for (let k = i; k <= i + j; k++) {
|
|
48
|
+
fragment += fragments[k].sequence;
|
|
49
|
+
nbResidue += fragments[k].nbResidue;
|
|
50
|
+
}
|
|
51
|
+
let from = fragments[i].from + 1;
|
|
52
|
+
let to = fragments[i + j].to + 1;
|
|
53
|
+
if (
|
|
54
|
+
fragment &&
|
|
55
|
+
nbResidue >= options.minResidue &&
|
|
56
|
+
nbResidue <= options.maxResidue
|
|
57
|
+
) {
|
|
58
|
+
results.push(`H${fragment}OH$D${from}>${to}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getRegexp(enzyme) {
|
|
67
|
+
switch (enzyme.toLowerCase().replaceAll(/[^\da-z]/g, '')) {
|
|
68
|
+
case 'chymotrypsin':
|
|
69
|
+
return /(Phe|Tyr|Trp)(?!Pro)/g;
|
|
70
|
+
case 'trypsin':
|
|
71
|
+
return /(Lys|Arg)(?!Pro)/g;
|
|
72
|
+
case 'lysc':
|
|
73
|
+
return /(Lys)(?!Pro)/g;
|
|
74
|
+
case 'glucph4':
|
|
75
|
+
return /(Glu)(?!Pro|Glu)/g;
|
|
76
|
+
case 'glucph8':
|
|
77
|
+
return /(Asp|Glu)(?!Pro|Glu)/g;
|
|
78
|
+
case 'thermolysin': // N-term of Leu, Phe, Val, Ile, Ala, Met
|
|
79
|
+
return /()(?=Ile|Leu|Val|Ala|Met|Phe)/g;
|
|
80
|
+
case 'cyanogenbromide':
|
|
81
|
+
return /(Met)/g;
|
|
82
|
+
case 'any':
|
|
83
|
+
return /()(?=[A-Z][a-z]{2})/g;
|
|
84
|
+
default:
|
|
85
|
+
throw new Error(`Digestion enzyme: ${enzyme} is unknown`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export function generatePeptideFragments(mf, options) {
|
|
2
|
+
if (options === undefined) {
|
|
3
|
+
options = {
|
|
4
|
+
a: false,
|
|
5
|
+
b: true,
|
|
6
|
+
c: false,
|
|
7
|
+
x: false,
|
|
8
|
+
y: true,
|
|
9
|
+
z: false,
|
|
10
|
+
i: false,
|
|
11
|
+
ya: false,
|
|
12
|
+
yb: false,
|
|
13
|
+
yc: false,
|
|
14
|
+
zc: false,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
options.maxInternal = options.maxInternal || Number.MAX_VALUE;
|
|
18
|
+
options.minInternal = options.minInternal || 0;
|
|
19
|
+
|
|
20
|
+
let mfs = [];
|
|
21
|
+
// need to allow 0-9 to deal with neutral loss
|
|
22
|
+
let mfparts = mf
|
|
23
|
+
.replaceAll(/([\d)a-z])([A-Z][a-z](?=[a-z]))/g, '$1 $2')
|
|
24
|
+
.split(/ /);
|
|
25
|
+
|
|
26
|
+
let nTerm = '';
|
|
27
|
+
let cTerm = '';
|
|
28
|
+
|
|
29
|
+
if (mfparts[0].startsWith('(')) {
|
|
30
|
+
nTerm += mfparts[0];
|
|
31
|
+
mfparts = mfparts.splice(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (mfparts.at(-1).includes('(')) {
|
|
35
|
+
cTerm += mfparts.at(-1).replace(/^[^()]*/, '');
|
|
36
|
+
mfparts[mfparts.length - 1] = mfparts.at(-1).replace(/\(.*/, '');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (let i = 1; i < mfparts.length; i++) {
|
|
40
|
+
nTerm += mfparts[i - 1];
|
|
41
|
+
cTerm = mfparts[mfparts.length - i] + cTerm;
|
|
42
|
+
addNTerm(mfs, nTerm, i, options);
|
|
43
|
+
addCTerm(mfs, cTerm, i, options);
|
|
44
|
+
if (options.i) mfs.push(`${mfparts[i]}HC-1O-1(+1)$i:${mfparts[i]}`);
|
|
45
|
+
|
|
46
|
+
if (options.ya || options.yb || options.yc || options.zc) {
|
|
47
|
+
// we have double fragmentations
|
|
48
|
+
for (
|
|
49
|
+
let j = i + 1;
|
|
50
|
+
j < Math.min(mfparts.length, options.maxInternal + i + 1);
|
|
51
|
+
j++
|
|
52
|
+
) {
|
|
53
|
+
let iTerm = '';
|
|
54
|
+
if (j - i >= options.minInternal) {
|
|
55
|
+
for (let k = i; k < j; k++) {
|
|
56
|
+
iTerm += mfparts[k];
|
|
57
|
+
}
|
|
58
|
+
addITerm(mfs, iTerm, mfparts.length - i, j, options);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// todo does this make sense ??? I think we should remote those 3 lines
|
|
65
|
+
if (mfs.length === 0) {
|
|
66
|
+
mfs = mfs.concat([mf]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return mfs;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function addNTerm(mfs, nTerm, i, options) {
|
|
73
|
+
if (options.a) mfs.push(`${nTerm}C-1O-1(+1)$a${i}`);
|
|
74
|
+
if (options.b) mfs.push(`${nTerm}(+1)$b${i}`);
|
|
75
|
+
if (options.c) mfs.push(`${nTerm}NH3(+1)$c${i}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function addITerm(mfs, iTerm, i, j, options) {
|
|
79
|
+
if (options.ya) mfs.push(`H${iTerm}C-1O-1(+1)$a${j}y${i}`);
|
|
80
|
+
if (options.yb) mfs.push(`H${iTerm}(+1)$b${j}y${i}`);
|
|
81
|
+
if (options.yc) mfs.push(`H${iTerm}NH3(+1)$c${j}y${i}`);
|
|
82
|
+
if (options.zc) mfs.push(`N-1${iTerm}NH3(+1)$c${j}z${i}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function addCTerm(mfs, cTerm, i, options) {
|
|
86
|
+
if (options.x) mfs.push(`CO(+1)${cTerm}$x${i}`);
|
|
87
|
+
if (options.y) mfs.push(`H2(+1)${cTerm}$y${i}`);
|
|
88
|
+
if (options.z) mfs.push(`N-1H-1(+1)${cTerm}$z${i}`);
|
|
89
|
+
}
|
package/src/getAA.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { aminoAcids } from './aminoAcids';
|
|
2
|
+
|
|
3
|
+
export function getAA(code) {
|
|
4
|
+
if (code.length === 1) {
|
|
5
|
+
for (let i = 0; i < aminoAcids.length; i++) {
|
|
6
|
+
if (aminoAcids[i].aa1 === code) {
|
|
7
|
+
return aminoAcids[i];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
if (code.length === 3) {
|
|
12
|
+
for (let i = 0; i < aminoAcids.length; i++) {
|
|
13
|
+
if (aminoAcids[i].aa3 === code) {
|
|
14
|
+
return aminoAcids[i];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { aminoAcids } from './aminoAcids';
|
|
2
|
+
import * as IEP from './isoElectricPoint';
|
|
3
|
+
import { splitPeptide } from './splitPeptide.js';
|
|
4
|
+
|
|
5
|
+
export * from './allowNeutralLoss.js';
|
|
6
|
+
export * from './chargePeptide.js';
|
|
7
|
+
export * from './sequenceToMF.js';
|
|
8
|
+
export * from './generatePeptideFragments.js';
|
|
9
|
+
export * from './digestPeptide.js';
|
|
10
|
+
export * from './splitPeptide.js';
|
|
11
|
+
|
|
12
|
+
export function getInfo() {
|
|
13
|
+
return aminoAcids;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// sequence should be in the "right" format like HAlaGlyProOH
|
|
17
|
+
|
|
18
|
+
export function calculateIEP(sequence) {
|
|
19
|
+
let aas = splitPeptide(sequence);
|
|
20
|
+
let result = IEP.calculateIEP(aas);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function calculateIEPChart(sequence) {
|
|
25
|
+
let aas = splitPeptide(sequence);
|
|
26
|
+
let result = IEP.calculateChart(aas);
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getColorForIEP(iep) {
|
|
31
|
+
return IEP.getColor(iep);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function calculateCharge(sequence, ph) {
|
|
35
|
+
let aas = splitPeptide(sequence);
|
|
36
|
+
return IEP.calculateCharge(aas, ph);
|
|
37
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { aminoAcids } from './aminoAcids';
|
|
2
|
+
|
|
3
|
+
// we will convert the data to an object to be much faster
|
|
4
|
+
let aaObject = {};
|
|
5
|
+
for (let i = 0; i < aminoAcids.length; i++) {
|
|
6
|
+
aaObject[aminoAcids[i].aa3] = aminoAcids[i];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function calculateCharge(aas, pH = 7) {
|
|
10
|
+
let combined = combine(aas);
|
|
11
|
+
if (!combined) return;
|
|
12
|
+
let charge = calculateForPh(combined, pH);
|
|
13
|
+
return Math.round(charge * 1000) / 1000;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// this methods required an array of aas
|
|
17
|
+
|
|
18
|
+
export function calculateIEP(aas) {
|
|
19
|
+
let combined = combine(aas);
|
|
20
|
+
if (!combined) return;
|
|
21
|
+
let first = 0;
|
|
22
|
+
let last = 14;
|
|
23
|
+
let current = 14;
|
|
24
|
+
let previous = 0;
|
|
25
|
+
let currentCharge;
|
|
26
|
+
while (Math.abs(current - previous) > 0.0001) {
|
|
27
|
+
previous = current;
|
|
28
|
+
current = (last + first) / 2;
|
|
29
|
+
currentCharge = calculateForPh(combined, current);
|
|
30
|
+
if (currentCharge > 0) {
|
|
31
|
+
first = current;
|
|
32
|
+
} else if (currentCharge < 0) {
|
|
33
|
+
last = current;
|
|
34
|
+
} else {
|
|
35
|
+
previous = current;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return Math.round(current * 1000) / 1000;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function calculateChart(aas) {
|
|
42
|
+
let combined = combine(aas);
|
|
43
|
+
if (!combined) return;
|
|
44
|
+
let y = [];
|
|
45
|
+
let x = [];
|
|
46
|
+
let yAbs = [];
|
|
47
|
+
for (let i = 0; i <= 14; i = i + 0.01) {
|
|
48
|
+
let charge = calculateForPh(combined, i);
|
|
49
|
+
x.push(i);
|
|
50
|
+
y.push(charge);
|
|
51
|
+
yAbs.push(Math.abs(charge));
|
|
52
|
+
}
|
|
53
|
+
combined.x = x;
|
|
54
|
+
combined.y = y;
|
|
55
|
+
combined.yAbs = yAbs;
|
|
56
|
+
|
|
57
|
+
return combined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function calculateForPh(combined, pH) {
|
|
61
|
+
let total = 0;
|
|
62
|
+
total += 1 / (1 + 10 ** (pH - combined.first));
|
|
63
|
+
total += -1 / (1 + 10 ** (combined.last - pH));
|
|
64
|
+
for (let key in combined.acid) {
|
|
65
|
+
total += -combined.acid[key] / (1 + 10 ** (aaObject[key].sc.pKa - pH));
|
|
66
|
+
}
|
|
67
|
+
for (let key in combined.basic) {
|
|
68
|
+
total += combined.basic[key] / (1 + 10 ** (pH - aaObject[key].sc.pKa));
|
|
69
|
+
}
|
|
70
|
+
return total;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// we will combine the amino acids
|
|
74
|
+
function combine(aas) {
|
|
75
|
+
let combined = {};
|
|
76
|
+
if (aaObject[aas[0]]) {
|
|
77
|
+
combined.first = aaObject[aas[0]].pKaN;
|
|
78
|
+
} else {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (aaObject[aas.at(-1)]) {
|
|
82
|
+
combined.last = aaObject[aas.at(-1)].pKaC;
|
|
83
|
+
} else {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
combined.basic = {};
|
|
87
|
+
combined.acid = {};
|
|
88
|
+
for (let i = 0; i < aas.length; i++) {
|
|
89
|
+
let currentAA = aas[i];
|
|
90
|
+
if (!aaObject[currentAA]) return;
|
|
91
|
+
if (aaObject[currentAA].sc && aaObject[currentAA].sc.type) {
|
|
92
|
+
if (aaObject[currentAA].sc.type === 'positive') {
|
|
93
|
+
if (!combined.basic[currentAA]) {
|
|
94
|
+
combined.basic[currentAA] = 0;
|
|
95
|
+
}
|
|
96
|
+
combined.basic[currentAA]++;
|
|
97
|
+
} else if (aaObject[currentAA].sc.type === 'negative') {
|
|
98
|
+
if (!combined.acid[currentAA]) {
|
|
99
|
+
combined.acid[currentAA] = 0;
|
|
100
|
+
}
|
|
101
|
+
combined.acid[currentAA]++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return combined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/*
|
|
109
|
+
We can generate a color based on iep
|
|
110
|
+
0 -> 7 means that at pH 7 it is charged negatively (blue)
|
|
111
|
+
7 -> 14 means that at pH7 it is charged positively (red)
|
|
112
|
+
*/
|
|
113
|
+
export function getColor(iep) {
|
|
114
|
+
if (iep < 7) {
|
|
115
|
+
if (iep < 3) iep = 3;
|
|
116
|
+
let white = Math.round(255 - (7 - iep) * (200 / 4));
|
|
117
|
+
return `rgb(${white},${white},255)`;
|
|
118
|
+
} else if (iep > 7) {
|
|
119
|
+
if (iep > 11) iep = 11;
|
|
120
|
+
let white = Math.round(255 - (iep - 7) * (200 / 4));
|
|
121
|
+
return `rgb(255,${white},${white})`;
|
|
122
|
+
}
|
|
123
|
+
return 'rgb(255,255,255)';
|
|
124
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { ensureUppercaseSequence } from 'mf-utilities';
|
|
2
|
+
|
|
3
|
+
import { aminoAcids } from './aminoAcids';
|
|
4
|
+
|
|
5
|
+
export function sequenceToMF(mf) {
|
|
6
|
+
if (mf === '') return '';
|
|
7
|
+
mf = ensureUppercaseSequence(mf);
|
|
8
|
+
// this function will check if it is a sequence of aa in 1 letter or 3 letters and convert them if it is the case
|
|
9
|
+
// it could be a multiline mf !
|
|
10
|
+
// if it is a multiline we could make some "tricks" ...
|
|
11
|
+
|
|
12
|
+
let newMF = mf;
|
|
13
|
+
// SEQRES 1 B 256 MET PRO VAL GLU ILE THR VAL LYS GLU LEU LEU GLU ALA
|
|
14
|
+
// SEQRES 2 B 256 GLY VAL HIS PHE GLY HIS GLU ARG LYS ARG TRP ASN PRO
|
|
15
|
+
// or
|
|
16
|
+
// MET PRO VAL GLU ILE THR VAL LYS GLU LEU LEU GLU ALA
|
|
17
|
+
// GLY VAL HIS PHE GLY HIS GLU ARG LYS ARG TRP ASN PRO
|
|
18
|
+
if (mf.search(/(?:[A-Z]{3} ){2}[A-Z]{3}/) > -1) {
|
|
19
|
+
// this is a PDB !
|
|
20
|
+
let tmpmf = mf.replaceAll(/[\n\r]+/g, ' ');
|
|
21
|
+
tmpmf = tmpmf.replaceAll(/(SEQRES|\d+| [A-Z] | [\dA-Z]{4-50})/g, '');
|
|
22
|
+
// we need to correct the uppercase / lowercase
|
|
23
|
+
let parts = tmpmf.split(' ');
|
|
24
|
+
newMF = 'H';
|
|
25
|
+
for (let i = 0; i < parts.length; i++) {
|
|
26
|
+
newMF += parts[i].slice(0, 1) + parts[i].slice(1).toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
newMF += 'OH';
|
|
29
|
+
} else if (mf.includes('(') && isOneLetterCode(mf)) {
|
|
30
|
+
// we expect one-letter code with modification
|
|
31
|
+
newMF = '';
|
|
32
|
+
let nTerminal = 'H';
|
|
33
|
+
let cTerminal = 'OH';
|
|
34
|
+
let parenthesisCounter = 0;
|
|
35
|
+
for (let i = 0; i < mf.length; i++) {
|
|
36
|
+
let currentSymbol = mf[i];
|
|
37
|
+
if (
|
|
38
|
+
currentSymbol === '(' ||
|
|
39
|
+
currentSymbol === ')' ||
|
|
40
|
+
parenthesisCounter > 0
|
|
41
|
+
) {
|
|
42
|
+
if (currentSymbol === '(') {
|
|
43
|
+
parenthesisCounter++;
|
|
44
|
+
if (i === 0) nTerminal = '';
|
|
45
|
+
}
|
|
46
|
+
if (currentSymbol === ')') {
|
|
47
|
+
parenthesisCounter--;
|
|
48
|
+
if (i === mf.length - 1) cTerminal = '';
|
|
49
|
+
}
|
|
50
|
+
newMF += currentSymbol;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
newMF += convertAA1To3(currentSymbol);
|
|
54
|
+
}
|
|
55
|
+
newMF = nTerminal + newMF + cTerminal;
|
|
56
|
+
} else if (mf.search(/[A-Za-z][\da-z]/) === -1) {
|
|
57
|
+
// UNIPROT
|
|
58
|
+
// 370 380 390 400 410 420
|
|
59
|
+
//GFKPNLRKTF VSGLFRESCG AHFYRGVDVK PFYIKKPVDN LFALMLILNR LRGWGVVGGM
|
|
60
|
+
//
|
|
61
|
+
// 430 440 450 460 470 480
|
|
62
|
+
//SDPRLYKVWV RLSSQVPSMF FGGTDLAADY YVVSPPTAVS VYTKTPYGRL LADTRTSGFR
|
|
63
|
+
// We remove all the number, all the spaces, etc
|
|
64
|
+
newMF = `H${convertAA1To3(newMF.replaceAll(/[^A-Z]/g, ''))}OH`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return newMF;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function convertAA1To3(mf) {
|
|
71
|
+
let newmf = '';
|
|
72
|
+
for (let i = 0; i < mf.length; i++) {
|
|
73
|
+
newmf += aa1To3(mf.charAt(i));
|
|
74
|
+
}
|
|
75
|
+
return newmf;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function aa1To3(code) {
|
|
79
|
+
for (let i = 0; i < aminoAcids.length; i++) {
|
|
80
|
+
if (aminoAcids[i].aa1 === code) {
|
|
81
|
+
return aminoAcids[i].aa3;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`Invalid 1 letter code: ${code}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// mf can contain as well parenthesis. We need to check if it is not yet a correct molecular formula
|
|
88
|
+
function isOneLetterCode(mf) {
|
|
89
|
+
let parenthesisLevel = 0;
|
|
90
|
+
for (let char of mf) {
|
|
91
|
+
if (parenthesisLevel === 0 && char.match(/[a-z]/)) return false;
|
|
92
|
+
if (char === '(') parenthesisLevel++;
|
|
93
|
+
if (char === ')') parenthesisLevel--;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function splitPeptide(sequence) {
|
|
2
|
+
let aas = sequence.replaceAll(/([A-Z])/g, ' $1').split(/ /);
|
|
3
|
+
let begin = 0;
|
|
4
|
+
while (aas[begin] === '' || aas[begin] === 'H') {
|
|
5
|
+
begin++;
|
|
6
|
+
}
|
|
7
|
+
let end = aas.length - 1;
|
|
8
|
+
while (aas[end] === 'O' || aas[end] === 'H') {
|
|
9
|
+
end--;
|
|
10
|
+
}
|
|
11
|
+
aas = aas.slice(begin, end + 1);
|
|
12
|
+
return aas;
|
|
13
|
+
}
|