@datagrok/sequence-translator 1.0.12 → 1.0.13
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/dist/package-test.js +254 -94
- package/dist/package.js +582 -348
- package/package.json +2 -2
- package/src/__jest__/remote.test.ts +11 -3
- package/src/{ICDs.ts → autostart/ICDs.ts} +0 -0
- package/src/{IDPs.ts → autostart/IDPs.ts} +0 -0
- package/src/autostart/calculations.ts +37 -0
- package/src/autostart/constants.ts +37 -0
- package/src/autostart/registration.ts +94 -129
- package/src/{salts.ts → autostart/salts.ts} +0 -0
- package/src/{sources.ts → autostart/sources.ts} +0 -0
- package/src/{users.ts → autostart/users.ts} +0 -0
- package/src/helpers.ts +28 -0
- package/src/main/main-view.ts +48 -70
- package/src/package.ts +6 -7
- package/src/structures-works/from-monomers.ts +1 -4
- package/src/structures-works/map.ts +14 -28
- package/src/structures-works/mol-transformations.ts +177 -16
- package/src/structures-works/save-sense-antisense.ts +32 -11
- package/src/structures-works/sequence-codes-tools.ts +1 -3
- package/{test-SequenceTranslator-49ff04f38f57-128d0678.html → test-SequenceTranslator-62cc009524f3-4a9916b0.html} +10 -7
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.13",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Vadym Kovadlo",
|
|
7
7
|
"email": "vkovadlo@datagrok.ai"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"directory": "packages/SequenceTranslator"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@datagrok-libraries/utils": "^1.
|
|
16
|
+
"@datagrok-libraries/utils": "^1.15.5",
|
|
17
17
|
"@types/react": "^18.0.15",
|
|
18
18
|
"datagrok-api": "^1.7.2",
|
|
19
19
|
"datagrok-tools": "^4.1.2",
|
|
@@ -43,27 +43,35 @@ it('TEST', async () => {
|
|
|
43
43
|
return new Promise<object>((resolve, reject) => {
|
|
44
44
|
(<any>window).grok.functions.eval(targetPackage + ':test()').then((df: any) => {
|
|
45
45
|
const cStatus = df.columns.byName('success');
|
|
46
|
+
const cSkipped = df.columns.byName('skipped');
|
|
46
47
|
const cMessage = df.columns.byName('result');
|
|
47
48
|
const cCat = df.columns.byName('category');
|
|
48
49
|
const cName = df.columns.byName('name');
|
|
49
50
|
const cTime = df.columns.byName('ms');
|
|
50
51
|
let failed = false;
|
|
52
|
+
let skipReport = '';
|
|
51
53
|
let passReport = '';
|
|
52
54
|
let failReport = '';
|
|
53
55
|
for (let i = 0; i < df.rowCount; i++) {
|
|
54
56
|
if (cStatus.get(i)) {
|
|
55
|
-
|
|
57
|
+
if (cSkipped.get(i)) {
|
|
58
|
+
skipReport += `Test result : Skipped : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
59
|
+
} else {
|
|
60
|
+
passReport += `Test result : Success : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
61
|
+
}
|
|
56
62
|
} else {
|
|
57
63
|
failed = true;
|
|
58
64
|
failReport += `Test result : Failed : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
59
65
|
}
|
|
60
66
|
}
|
|
61
|
-
resolve({failReport, passReport, failed});
|
|
67
|
+
resolve({failReport, skipReport, passReport, failed});
|
|
62
68
|
}).catch((e: any) => reject(e));
|
|
63
69
|
});
|
|
64
70
|
}, targetPackage);
|
|
65
71
|
// @ts-ignore
|
|
66
72
|
console.log(r.passReport);
|
|
67
73
|
// @ts-ignore
|
|
74
|
+
console.log(r.skipReport);
|
|
75
|
+
// @ts-ignore
|
|
68
76
|
expect(r.failed).checkOutput(false, r.failReport);
|
|
69
|
-
},
|
|
77
|
+
}, 7200000);
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as DG from 'datagrok-api/dg';
|
|
2
|
+
import {sortByStringLengthInDescendingOrder} from '../helpers';
|
|
3
|
+
import {MODIFICATIONS} from '../structures-works/map';
|
|
4
|
+
|
|
5
|
+
export function saltMass(
|
|
6
|
+
saltNames: string[], molWeightCol: DG.Column, equivalentsCol: DG.Column, i: number, saltCol: DG.Column,
|
|
7
|
+
): number {
|
|
8
|
+
const saltRowIndex = saltNames.indexOf(saltCol.get(i));
|
|
9
|
+
return (
|
|
10
|
+
saltRowIndex == -1 || molWeightCol.get(saltRowIndex) == DG.FLOAT_NULL || equivalentsCol.get(i) == DG.INT_NULL
|
|
11
|
+
) ?
|
|
12
|
+
DG.FLOAT_NULL :
|
|
13
|
+
molWeightCol.get(saltRowIndex) * equivalentsCol.get(i);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function saltMolWeigth(saltNamesList: string[], saltCol: DG.Column, molWeightCol: DG.Column, i: number): number {
|
|
17
|
+
const saltRowIndex = saltNamesList.indexOf(saltCol.get(i));
|
|
18
|
+
return (saltRowIndex == -1) ? DG.FLOAT_NULL : molWeightCol.get(saltRowIndex);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function batchMolWeight(compoundMolWeightCol: DG.Column, saltMassCol: DG.Column, i: number): number {
|
|
22
|
+
return (compoundMolWeightCol.getString(i) == '' || saltMassCol.getString(i) == '') ?
|
|
23
|
+
DG.FLOAT_NULL :
|
|
24
|
+
compoundMolWeightCol.get(i) + saltMassCol.get(i);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function molecularWeight(sequence: string, weightsObj: {[index: string]: number}): number {
|
|
28
|
+
const codes = sortByStringLengthInDescendingOrder(Object.keys(weightsObj)).concat(Object.keys(MODIFICATIONS));
|
|
29
|
+
let weight = 0;
|
|
30
|
+
let i = 0;
|
|
31
|
+
while (i < sequence.length) {
|
|
32
|
+
const matchedCode = codes.find((s) => s == sequence.slice(i, i + s.length))!;
|
|
33
|
+
weight += weightsObj[sequence.slice(i, i + matchedCode.length)];
|
|
34
|
+
i += matchedCode.length;
|
|
35
|
+
}
|
|
36
|
+
return weight - 61.97;
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const SEQUENCE_TYPES = {
|
|
2
|
+
SENSE_STRAND: 'SS',
|
|
3
|
+
ANTISENSE_STRAND: 'AS',
|
|
4
|
+
DUPLEX: 'Duplex',
|
|
5
|
+
TRIPLEX: 'Triplex',
|
|
6
|
+
DIMER: 'Dimer',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const COL_NAMES = {
|
|
10
|
+
CHEMISTRY: 'Chemistry',
|
|
11
|
+
NUMBER: 'Number',
|
|
12
|
+
TYPE: 'Type',
|
|
13
|
+
CHEMISTRY_NAME: 'Chemistry Name',
|
|
14
|
+
INTERNAL_COMPOUND_ID: 'Internal compound ID',
|
|
15
|
+
IDP: 'IDP',
|
|
16
|
+
SEQUENCE: 'Sequence',
|
|
17
|
+
COMPOUND_NAME: 'Compound Name',
|
|
18
|
+
COMPOUND_COMMENTS: 'Compound Comments',
|
|
19
|
+
SALT: 'Salt',
|
|
20
|
+
EQUIVALENTS: 'Equivalents',
|
|
21
|
+
PURITY: 'Purity',
|
|
22
|
+
COMPOUND_MOL_WEIGHT: 'Cpd MW',
|
|
23
|
+
SALT_MOL_WEIGHT: 'Salt MW',
|
|
24
|
+
SALT_MASS: 'Salt mass',
|
|
25
|
+
BATCH_MOL_WEIGHT: 'Batch MW',
|
|
26
|
+
SOURCE: 'Source',
|
|
27
|
+
ICD: 'ICD',
|
|
28
|
+
OWNER: 'Owner',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const GENERATED_COL_NAMES = [
|
|
32
|
+
COL_NAMES.COMPOUND_NAME,
|
|
33
|
+
COL_NAMES.COMPOUND_COMMENTS,
|
|
34
|
+
COL_NAMES.COMPOUND_MOL_WEIGHT,
|
|
35
|
+
COL_NAMES.SALT_MASS,
|
|
36
|
+
COL_NAMES.BATCH_MOL_WEIGHT,
|
|
37
|
+
];
|
|
@@ -3,90 +3,59 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
import {siRnaBioSpringToGcrs, siRnaAxolabsToGcrs, gcrsToNucleotides, asoGapmersBioSpringToGcrs, gcrsToMermade12,
|
|
5
5
|
siRnaNucleotidesToGcrs} from '../structures-works/converters';
|
|
6
|
-
import {
|
|
6
|
+
import {weightsObj, SYNTHESIZERS} from '../structures-works/map';
|
|
7
|
+
import {SEQUENCE_TYPES, COL_NAMES, GENERATED_COL_NAMES} from './constants';
|
|
8
|
+
import {saltMass, saltMolWeigth, molecularWeight, batchMolWeight} from './calculations';
|
|
7
9
|
import {isValidSequence} from '../structures-works/sequence-codes-tools';
|
|
8
10
|
import {sequenceToMolV3000} from '../structures-works/from-monomers';
|
|
9
|
-
import {
|
|
11
|
+
import {linkStrandsV3000} from '../structures-works/mol-transformations';
|
|
12
|
+
import {stringify, download, removeEmptyRows, differenceOfTwoArrays} from '../helpers';
|
|
10
13
|
|
|
11
|
-
import {SALTS_CSV} from '
|
|
12
|
-
import {USERS_CSV} from '
|
|
13
|
-
import {ICDS} from '
|
|
14
|
-
import {SOURCES} from '
|
|
15
|
-
import {IDPS} from '
|
|
14
|
+
import {SALTS_CSV} from './salts';
|
|
15
|
+
import {USERS_CSV} from './users';
|
|
16
|
+
import {ICDS} from './ICDs';
|
|
17
|
+
import {SOURCES} from './sources';
|
|
18
|
+
import {IDPS} from './IDPs';
|
|
16
19
|
|
|
17
20
|
|
|
18
|
-
function
|
|
19
|
-
|
|
21
|
+
function parseStrandsFromDuplexCell(s: string): {SS: string, AS: string} {
|
|
22
|
+
const arr = s.slice(3).split('\r\nAS ');
|
|
23
|
+
return {SS: arr[0], AS: arr[1]};
|
|
20
24
|
}
|
|
21
25
|
|
|
22
|
-
function
|
|
23
|
-
|
|
26
|
+
function parseStrandsFromTriplexOrDimerCell(s: string): {SS: string, AS1: string, AS2: string} {
|
|
27
|
+
const arr1 = s.slice(3).split('\r\nAS1 ');
|
|
28
|
+
const arr2 = arr1[1].split('\r\nAS2 ');
|
|
29
|
+
return {SS: arr1[0], AS1: arr2[0], AS2: arr2[1]};
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
saltRowIndex == -1 || molWeightCol.get(saltRowIndex) == DG.FLOAT_NULL || equivalentsCol.get(i) == DG.INT_NULL) ?
|
|
31
|
-
DG.FLOAT_NULL :
|
|
32
|
-
molWeightCol.get(saltRowIndex) * equivalentsCol.get(i);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function saltMolWeigth(saltNamesList: string[], saltCol: DG.Column, molWeightCol: DG.Column, i: number) {
|
|
36
|
-
const saltRowIndex = saltNamesList.indexOf(saltCol.get(i));
|
|
37
|
-
return (saltRowIndex == -1) ? DG.FLOAT_NULL : molWeightCol.get(saltRowIndex);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function batchMolWeight(compoundMolWeightCol: DG.Column, saltMassCol: DG.Column, i: number) {
|
|
41
|
-
return (compoundMolWeightCol.getString(i) == '' || saltMassCol.getString(i) == '') ?
|
|
42
|
-
DG.FLOAT_NULL :
|
|
43
|
-
compoundMolWeightCol.get(i) + saltMassCol.get(i);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function molecularWeight(sequence: string, weightsObj: {[index: string]: number}): number {
|
|
47
|
-
const codes = sortByStringLengthInDescendingOrder(Object.keys(weightsObj)).concat(Object.keys(MODIFICATIONS));
|
|
48
|
-
let weight = 0;
|
|
49
|
-
let i = 0;
|
|
50
|
-
while (i < sequence.length) {
|
|
51
|
-
const matchedCode = codes.find((s) => s == sequence.slice(i, i + s.length))!;
|
|
52
|
-
weight += weightsObj[sequence.slice(i, i + matchedCode.length)];
|
|
53
|
-
i += matchedCode.length;
|
|
32
|
+
async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
33
|
+
if (GENERATED_COL_NAMES.some((colName) => !table.columns.contains(colName))) {
|
|
34
|
+
const absentColNames = differenceOfTwoArrays(GENERATED_COL_NAMES, table.columns.names()).join(`', '`);
|
|
35
|
+
grok.shell.warning(`File saved without columns '${absentColNames}'`);
|
|
54
36
|
}
|
|
55
|
-
return weight - 61.97;
|
|
56
|
-
}
|
|
57
37
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
38
|
+
const sequenceCol = table.getCol(COL_NAMES.SEQUENCE);
|
|
39
|
+
const typeCol = table.getCol(COL_NAMES.TYPE);
|
|
61
40
|
|
|
62
|
-
async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
63
|
-
if (!table.columns.contains('Compound Name')) {
|
|
64
|
-
grok.shell.warning(
|
|
65
|
-
'File saved without columns \'' +
|
|
66
|
-
[COL_NAMES.COMPOUND_NAME, COL_NAMES.COMPOUND_COMMENTS, COL_NAMES.CPD_MW,
|
|
67
|
-
COL_NAMES.SALT_MASS, COL_NAMES.BATCH_MW].join('\', \''),
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
const structureColumn = table.getCol(COL_NAMES.SEQUENCE);
|
|
71
|
-
const typeColumn = table.getCol(COL_NAMES.TYPE);
|
|
72
41
|
let result = '';
|
|
73
42
|
for (let i = 0; i < table.rowCount; i++) {
|
|
74
|
-
const format =
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
result +=
|
|
43
|
+
const format = SYNTHESIZERS.GCRS; //getFormat(sequenceCol.get(i))!;
|
|
44
|
+
if (typeCol.get(i) == SEQUENCE_TYPES.SENSE_STRAND)
|
|
45
|
+
result += `${sequenceToMolV3000(sequenceCol.get(i), false, true, format)}\n> <Sequence>\nSense Strand\n\n`;
|
|
46
|
+
else if (typeCol.get(i) == SEQUENCE_TYPES.ANTISENSE_STRAND)
|
|
47
|
+
result += `${sequenceToMolV3000(sequenceCol.get(i), true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
|
|
48
|
+
else if (typeCol.get(i) == SEQUENCE_TYPES.DUPLEX) {
|
|
49
|
+
const obj = parseStrandsFromDuplexCell(sequenceCol.get(i));
|
|
50
|
+
const as = `${sequenceToMolV3000(obj.AS, true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
|
|
51
|
+
const ss = `${sequenceToMolV3000(obj.SS, false, true, format)}\n> <Sequence>\nSense Strand\n\n`;
|
|
52
|
+
result += `${linkStrandsV3000({senseStrands: [ss], antiStrands: [as]}, true)}\n\n`;
|
|
53
|
+
} else if ([SEQUENCE_TYPES.TRIPLEX, SEQUENCE_TYPES.DIMER].includes(typeCol.get(i))) {
|
|
54
|
+
const obj = parseStrandsFromTriplexOrDimerCell(sequenceCol.get(i));
|
|
55
|
+
const as1 = `${sequenceToMolV3000(obj.AS1, true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
|
|
56
|
+
const as2 = `${sequenceToMolV3000(obj.AS2, true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
|
|
57
|
+
const ss = `${sequenceToMolV3000(obj.SS, false, true, format)}\n> <Sequence>\nSense Strand\n\n`;
|
|
58
|
+
result += `${linkStrandsV3000({senseStrands: [ss], antiStrands: [as1, as2]}, true)}\n\n`;
|
|
90
59
|
}
|
|
91
60
|
|
|
92
61
|
for (const col of table.columns) {
|
|
@@ -95,17 +64,16 @@ async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
|
95
64
|
}
|
|
96
65
|
result += '$$$$\n';
|
|
97
66
|
}
|
|
98
|
-
|
|
99
|
-
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
|
|
100
|
-
element.setAttribute('download', table.name + '.sdf');
|
|
101
|
-
element.click();
|
|
67
|
+
download(`${table.name}.sdf`, encodeURIComponent(result));
|
|
102
68
|
}
|
|
103
69
|
|
|
104
70
|
export function autostartOligoSdFileSubscription() {
|
|
105
71
|
grok.events.onViewAdded.subscribe((v: any) => {
|
|
106
|
-
if (v.type ==
|
|
72
|
+
if (v.type == DG.VIEW_TYPE.TABLE_VIEW) {
|
|
107
73
|
if (v.dataFrame.columns.contains(COL_NAMES.TYPE))
|
|
108
74
|
oligoSdFile(v.dataFrame);
|
|
75
|
+
|
|
76
|
+
// Should be removed after fixing bug https://github.com/datagrok-ai/public/issues/808
|
|
109
77
|
grok.events.onContextMenu.subscribe((args) => {
|
|
110
78
|
const seqCol = args.args.context.table.currentCol; // /^[fsACGUacgu]{6,}$/
|
|
111
79
|
if (DG.Detector.sampleCategories(seqCol,
|
|
@@ -166,56 +134,56 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
166
134
|
const sequenceCol = table.getCol(COL_NAMES.SEQUENCE);
|
|
167
135
|
const saltCol = table.getCol(COL_NAMES.SALT);
|
|
168
136
|
const equivalentsCol = table.getCol(COL_NAMES.EQUIVALENTS);
|
|
169
|
-
const
|
|
137
|
+
const typeCol = table.getCol(COL_NAMES.TYPE);
|
|
170
138
|
const chemistryNameCol = table.getCol(COL_NAMES.CHEMISTRY_NAME);
|
|
171
139
|
|
|
172
140
|
const molWeightCol = saltsDf.getCol('MOLWEIGHT');
|
|
173
141
|
const saltNamesList = saltsDf.getCol('DISPLAY').toList();
|
|
174
142
|
|
|
143
|
+
let newDf: DG.DataFrame;
|
|
144
|
+
let addColumnsPressed = false;
|
|
145
|
+
|
|
175
146
|
function addColumns(t: DG.DataFrame) {
|
|
176
|
-
if (t.columns.contains(
|
|
147
|
+
if (GENERATED_COL_NAMES.some((colName) => t.columns.contains(colName)))
|
|
177
148
|
return grok.shell.error('Columns already exist');
|
|
178
149
|
|
|
179
|
-
|
|
180
|
-
if (sequenceCol.get(i) == '')
|
|
181
|
-
t.rows.removeAt(i, 1, false);
|
|
182
|
-
}
|
|
150
|
+
t = removeEmptyRows(t, sequenceCol);
|
|
183
151
|
|
|
184
152
|
t.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => {
|
|
185
|
-
return (
|
|
153
|
+
return ([SEQUENCE_TYPES.DUPLEX, SEQUENCE_TYPES.DIMER, SEQUENCE_TYPES.TRIPLEX].includes(typeCol.get(i))) ?
|
|
154
|
+
chemistryNameCol.get(i) :
|
|
155
|
+
sequenceCol.get(i);
|
|
186
156
|
});
|
|
187
157
|
|
|
188
158
|
t.columns.addNewString(COL_NAMES.COMPOUND_COMMENTS).init((i: number) => {
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
|
|
159
|
+
if ([SEQUENCE_TYPES.SENSE_STRAND, SEQUENCE_TYPES.ANTISENSE_STRAND].includes(typeCol.get(i)))
|
|
160
|
+
return sequenceCol.get(i);
|
|
161
|
+
else if (typeCol.get(i) == SEQUENCE_TYPES.DUPLEX) {
|
|
162
|
+
const obj = parseStrandsFromDuplexCell(sequenceCol.get(i));
|
|
163
|
+
return `${chemistryNameCol.get(i)}; duplex of SS: ${obj.SS} and AS: ${obj.AS}`;
|
|
164
|
+
} else if ([SEQUENCE_TYPES.DIMER, SEQUENCE_TYPES.TRIPLEX].includes(typeCol.get(i))) {
|
|
165
|
+
const obj = parseStrandsFromTriplexOrDimerCell(sequenceCol.get(i));
|
|
166
|
+
return `${chemistryNameCol.get(i)}; duplex of SS: ${obj.SS} and AS1: ${obj.AS1} and AS2: ${obj.AS2}`;
|
|
192
167
|
}
|
|
193
|
-
return sequenceCol.get(i);
|
|
194
168
|
});
|
|
195
169
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
isValidSequence(arr[1], null).indexOfFirstNotValidChar == -1
|
|
212
|
-
) ?
|
|
213
|
-
molecularWeight(arr[0], weightsObj) + molecularWeight(arr[1], weightsObj) :
|
|
170
|
+
t.columns.addNewFloat(COL_NAMES.COMPOUND_MOL_WEIGHT).init((i: number) => {
|
|
171
|
+
if ([SEQUENCE_TYPES.SENSE_STRAND, SEQUENCE_TYPES.ANTISENSE_STRAND].includes(typeCol.get(i))) {
|
|
172
|
+
return (isValidSequence(sequenceCol.get(i), null).indexOfFirstNotValidChar == -1) ?
|
|
173
|
+
molecularWeight(sequenceCol.get(i), weightsObj) :
|
|
174
|
+
DG.FLOAT_NULL;
|
|
175
|
+
} else if (typeCol.get(i) == SEQUENCE_TYPES.DUPLEX) {
|
|
176
|
+
const obj = parseStrandsFromDuplexCell(sequenceCol.get(i));
|
|
177
|
+
return (Object.values(obj).every((seq) => isValidSequence(seq, null).indexOfFirstNotValidChar == -1)) ?
|
|
178
|
+
molecularWeight(obj.SS, weightsObj) + molecularWeight(obj.AS, weightsObj) :
|
|
179
|
+
DG.FLOAT_NULL;
|
|
180
|
+
} else if ([SEQUENCE_TYPES.DIMER, SEQUENCE_TYPES.TRIPLEX].includes(typeCol.get(i))) {
|
|
181
|
+
const obj = parseStrandsFromTriplexOrDimerCell(sequenceCol.get(i));
|
|
182
|
+
return (Object.values(obj).every((seq) => isValidSequence(seq, null).indexOfFirstNotValidChar == -1)) ?
|
|
183
|
+
molecularWeight(obj.SS, weightsObj) + molecularWeight(obj.AS1, weightsObj) +
|
|
184
|
+
molecularWeight(obj.AS2, weightsObj) :
|
|
214
185
|
DG.FLOAT_NULL;
|
|
215
186
|
}
|
|
216
|
-
return (isValidSequence(sequenceCol.get(i), null).indexOfFirstNotValidChar == -1) ?
|
|
217
|
-
molecularWeight(sequenceCol.get(i), weightsObj) :
|
|
218
|
-
DG.FLOAT_NULL;
|
|
219
187
|
});
|
|
220
188
|
|
|
221
189
|
t.columns.addNewFloat(COL_NAMES.SALT_MASS).init((i: number) =>
|
|
@@ -224,15 +192,24 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
224
192
|
t.columns.addNewFloat(COL_NAMES.SALT_MOL_WEIGHT).init((i: number) =>
|
|
225
193
|
saltMolWeigth(saltNamesList, saltCol, molWeightCol, i));
|
|
226
194
|
|
|
227
|
-
t.
|
|
228
|
-
|
|
195
|
+
const compoundMolWeightCol = t.getCol(COL_NAMES.COMPOUND_MOL_WEIGHT);
|
|
196
|
+
const saltMassCol = t.getCol(COL_NAMES.SALT_MASS);
|
|
197
|
+
t.columns.addNewFloat(COL_NAMES.BATCH_MOL_WEIGHT).init((i: number) =>
|
|
198
|
+
batchMolWeight(compoundMolWeightCol, saltMassCol, i));
|
|
229
199
|
|
|
200
|
+
grok.shell.getTableView(table.name).grid.columns.setOrder(Object.values(COL_NAMES));
|
|
230
201
|
addColumnsPressed = true;
|
|
231
202
|
return newDf = t;
|
|
232
203
|
}
|
|
233
204
|
|
|
234
|
-
|
|
235
|
-
|
|
205
|
+
function updateCalculatedColumns(t: DG.DataFrame, i: number): void {
|
|
206
|
+
const smValue = saltMass(saltNamesList, molWeightCol, equivalentsCol, i, saltCol);
|
|
207
|
+
t.getCol(COL_NAMES.SALT_MASS).set(i, smValue, false);
|
|
208
|
+
const smwValue = saltMolWeigth(saltNamesList, saltCol, molWeightCol, i);
|
|
209
|
+
t.getCol(COL_NAMES.SALT_MOL_WEIGHT).set(i, smwValue, false);
|
|
210
|
+
const bmw = batchMolWeight(t.getCol(COL_NAMES.COMPOUND_MOL_WEIGHT), t.getCol(COL_NAMES.SALT_MASS), i);
|
|
211
|
+
t.getCol(COL_NAMES.BATCH_MOL_WEIGHT).set(i, bmw, false);
|
|
212
|
+
}
|
|
236
213
|
|
|
237
214
|
const d = ui.div([
|
|
238
215
|
ui.icons.edit(() => {
|
|
@@ -240,18 +217,15 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
240
217
|
if (table.getCol(COL_NAMES.IDP).type != DG.COLUMN_TYPE.STRING)
|
|
241
218
|
table.changeColumnType(COL_NAMES.IDP, DG.COLUMN_TYPE.STRING);
|
|
242
219
|
d.append(
|
|
243
|
-
ui.
|
|
244
|
-
addColumns(table)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
COL_NAMES.SALT_MASS, COL_NAMES.BATCH_MW].join('\', \''), '',
|
|
248
|
-
),
|
|
249
|
-
ui.button('Save SD file', () => saveTableAsSdFile(addColumnsPressed ? newDf : table)),
|
|
220
|
+
ui.divH([
|
|
221
|
+
ui.icons.add(() => addColumns(table), `Add columns: '${GENERATED_COL_NAMES.join(`', '`)}'`),
|
|
222
|
+
ui.icons.save(() => saveTableAsSdFile(addColumnsPressed ? newDf : table), 'Save SD file'),
|
|
223
|
+
]),
|
|
250
224
|
);
|
|
251
225
|
|
|
252
226
|
const view = grok.shell.getTableView(table.name);
|
|
253
|
-
|
|
254
|
-
view.dataFrame.getCol(COL_NAMES.TYPE).setTag(DG.TAGS.CHOICES,
|
|
227
|
+
view.grid.setOptions({rowHeight: 45});
|
|
228
|
+
view.dataFrame.getCol(COL_NAMES.TYPE).setTag(DG.TAGS.CHOICES, stringify(Object.values(SEQUENCE_TYPES)));
|
|
255
229
|
view.dataFrame.getCol(COL_NAMES.OWNER).setTag(DG.TAGS.CHOICES, stringify(usersDf.columns.byIndex(0).toList()));
|
|
256
230
|
view.dataFrame.getCol(COL_NAMES.SALT).setTag(DG.TAGS.CHOICES, stringify(saltsDf.columns.byIndex(0).toList()));
|
|
257
231
|
view.dataFrame.getCol(COL_NAMES.SOURCE).setTag(DG.TAGS.CHOICES, stringify(sourcesDf.columns.byIndex(0).toList()));
|
|
@@ -275,15 +249,6 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
275
249
|
if ([COL_NAMES.SALT, COL_NAMES.EQUIVALENTS, COL_NAMES.SALT_MOL_WEIGHT].includes(colName))
|
|
276
250
|
updateCalculatedColumns(view.dataFrame, view.dataFrame.currentRowIdx);
|
|
277
251
|
});
|
|
278
|
-
|
|
279
|
-
function updateCalculatedColumns(t: DG.DataFrame, i: number): void {
|
|
280
|
-
const smValue = saltMass(saltNamesList, molWeightCol, equivalentsCol, i, saltCol);
|
|
281
|
-
t.getCol(COL_NAMES.SALT_MASS).set(i, smValue, false);
|
|
282
|
-
const smwValue = saltMolWeigth(saltNamesList, saltCol, molWeightCol, i);
|
|
283
|
-
t.getCol(COL_NAMES.SALT_MOL_WEIGHT).set(i, smwValue, false);
|
|
284
|
-
const bmw = batchMolWeight(t.getCol(COL_NAMES.CPD_MW), t.getCol(COL_NAMES.SALT_MASS), i);
|
|
285
|
-
t.getCol(COL_NAMES.BATCH_MW).set(i, bmw, false);
|
|
286
|
-
}
|
|
287
252
|
}),
|
|
288
253
|
]);
|
|
289
254
|
grok.shell.v.setRibbonPanels([[d]]);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/helpers.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as DG from 'datagrok-api/dg';
|
|
2
|
+
|
|
3
|
+
export function sortByStringLengthInDescendingOrder(array: string[]): string[] {
|
|
4
|
+
return array.sort(function(a, b) {return b.length - a.length;});
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function stringify(items: string[]): string {
|
|
8
|
+
return '["' + items.join('", "') + '"]';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function download(name: string, href: string): void {
|
|
12
|
+
const element = document.createElement('a');
|
|
13
|
+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + href);
|
|
14
|
+
element.setAttribute('download', name);
|
|
15
|
+
element.click();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function removeEmptyRows(t: DG.DataFrame, colToCheck: DG.Column): DG.DataFrame {
|
|
19
|
+
for (let i = t.rowCount - 1; i > -1; i--) {
|
|
20
|
+
if (colToCheck.getString(i) == '')
|
|
21
|
+
t.rows.removeAt(i, 1, false);
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function differenceOfTwoArrays(a: string[], b: string[]): string[] {
|
|
27
|
+
return a.filter((x) => !b.includes(x));
|
|
28
|
+
}
|