@datagrok/sequence-translator 0.0.3 → 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.
@@ -4,10 +4,10 @@ import * as ui from 'datagrok-api/ui';
4
4
  import * as DG from 'datagrok-api/dg';
5
5
  // @ts-ignore
6
6
  import * as svg from 'save-svg-as-png';
7
- import $ from "cash-dom";
7
+ import $ from 'cash-dom';
8
8
 
9
- import {drawAxolabsPattern} from "./drawAxolabsPattern";
10
- import {axolabsMap} from "./axolabsMap";
9
+ import {drawAxolabsPattern} from './drawAxolabsPattern';
10
+ import {axolabsMap} from './axolabsMap';
11
11
 
12
12
  const baseChoices: string[] = Object.keys(axolabsMap);
13
13
  const defaultBase: string = baseChoices[0];
@@ -28,37 +28,45 @@ function findDuplicates(data: Int32Array | Float32Array | Float64Array | Uint32A
28
28
 
29
29
  async function isCurrentUserCreatedThisPattern(patternName: string): Promise<boolean> {
30
30
  return await grok.dapi.users.current().then((user) => {
31
- let [firstName, lastName] = getUserName(patternName);
31
+ const [firstName, lastName] = getUserName(patternName);
32
32
  return (user.firstName != firstName || user.lastName != lastName);
33
33
  });
34
34
  }
35
35
 
36
36
  function getShortName(patternName: string): string {
37
37
  let first = patternName.length + 1;
38
- for (let i = 0; i < patternName.length; i++)
38
+ for (let i = 0; i < patternName.length; i++) {
39
39
  if (patternName[i] == '(') {
40
40
  first = i;
41
41
  break;
42
42
  }
43
+ }
43
44
  return patternName.slice(0, first - 1);
44
45
  }
45
46
 
46
47
  function getUserName(patternName: string): string[] {
47
48
  let first = -1;
48
- for (let i = 0; i < patternName.length; i++)
49
+ for (let i = 0; i < patternName.length; i++) {
49
50
  if (patternName[i] == '(') {
50
51
  first = i;
51
52
  break;
52
53
  }
54
+ }
53
55
  return (first == -1) ? ['', ''] : patternName.slice(first + 9, patternName.length - 1).split(' ').slice(1);
54
56
  }
55
57
 
56
- function translateSequence(sequence: string, bases: any, ptoLinkages: any, startModification: any, endModification: any, firstPtoExist: boolean) {
58
+ function translateSequence(
59
+ sequence: string,
60
+ bases: any,
61
+ ptoLinkages: any,
62
+ startModification: any,
63
+ endModification: any,
64
+ firstPtoExist: boolean): string {
57
65
  let counter: number = -1;
58
- let mainSequence = sequence.replace(/[AUGC]/g, function (x: string) {
66
+ let mainSequence = sequence.replace(/[AUGC]/g, function(x: string) {
59
67
  counter++;
60
- let indexOfSymbol = axolabsMap["RNA"]["symbols"].indexOf(x);
61
- let symbol = axolabsMap[bases[counter].value]["symbols"][indexOfSymbol];
68
+ const indexOfSymbol = axolabsMap['RNA']['symbols'].indexOf(x);
69
+ const symbol = axolabsMap[bases[counter].value]['symbols'][indexOfSymbol];
62
70
  return (ptoLinkages[counter].value) ? symbol + 's' : symbol;
63
71
  });
64
72
  if (mainSequence.slice(0, 5).split('mU').length == 3)
@@ -70,27 +78,34 @@ function translateSequence(sequence: string, bases: any, ptoLinkages: any, start
70
78
 
71
79
  function addColumnWithIds(tableName: string, columnName: string, patternName: string) {
72
80
  const nameOfNewColumn = 'ID ' + patternName;
73
- let columns = grok.shell.table(tableName).columns;
81
+ const columns = grok.shell.table(tableName).columns;
74
82
  if (columns.contains(nameOfNewColumn))
75
83
  columns.remove(nameOfNewColumn);
76
84
  const columnWithIds = columns.byName(columnName);
77
85
  return columns.addNewString(nameOfNewColumn).init((i: number) => columnWithIds.get(i) + '_' + patternName);
78
86
  }
79
87
 
80
- function addColumnWithTranslatedSequences(tableName: string, columnName: string, bases: any, ptoLinkages: any, startModification: any, endModification: any, firstPtoExist: boolean) {
88
+ function addColumnWithTranslatedSequences(
89
+ tableName: string,
90
+ columnName: string,
91
+ bases: any,
92
+ ptoLinkages: any,
93
+ startModification: any,
94
+ endModification: any,
95
+ firstPtoExist: boolean) {
81
96
  const nameOfNewColumn = 'Axolabs ' + columnName;
82
- let columns = grok.shell.table(tableName).columns;
97
+ const columns = grok.shell.table(tableName).columns;
83
98
  if (columns.contains(nameOfNewColumn))
84
99
  columns.remove(nameOfNewColumn);
85
100
  const columnWithInputSequences = columns.byName(columnName);
86
101
  return columns.addNewString(nameOfNewColumn).init((i: number) => {
87
- return translateSequence(columnWithInputSequences.getString(i), bases, ptoLinkages, startModification, endModification, firstPtoExist);
102
+ return translateSequence(columnWithInputSequences.getString(i),
103
+ bases, ptoLinkages, startModification, endModification, firstPtoExist);
88
104
  });
89
105
  }
90
106
 
91
107
  export function defineAxolabsPattern() {
92
-
93
- let enumerateModifications = [defaultBase];
108
+ const enumerateModifications = [defaultBase];
94
109
  let maximalSsLength = defaultSequenceLength;
95
110
  let maximalAsLength = defaultSequenceLength;
96
111
 
@@ -124,17 +139,18 @@ export function defineAxolabsPattern() {
124
139
  updateOutputExamples();
125
140
  });
126
141
  let isOverhang = false;
127
- if (asBases[i].value.slice(-3) == '(o)') {
142
+ if (asBases[i].value.slice(-3) == '(o)')
128
143
  isOverhang = true;
129
- } else {
144
+ else
130
145
  nucleotideCounter++;
131
- }
146
+
132
147
  asModificationItems.append(
133
148
  ui.divH([
134
- ui.div([ui.label(asBases[i].value.slice(-3) == '(o)' ? '' : String(nucleotideCounter))], {style: {width: '20px'}})!,
149
+ ui.div([ui.label(asBases[i].value.slice(-3) == '(o)' ? '' : String(nucleotideCounter))],
150
+ {style: {width: '20px'}})!,
135
151
  ui.block75([asBases[i]])!,
136
- ui.div([asPtoLinkages[i]])!
137
- ], {style: {alignItems: "center"}})
152
+ ui.div([asPtoLinkages[i]])!,
153
+ ], {style: {alignItems: 'center'}}),
138
154
  );
139
155
  }
140
156
  }
@@ -169,17 +185,18 @@ export function defineAxolabsPattern() {
169
185
  updateOutputExamples();
170
186
  });
171
187
  let isOverhang = false;
172
- if (ssBases[i].value.slice(-3) == '(o)') {
188
+ if (ssBases[i].value.slice(-3) == '(o)')
173
189
  isOverhang = true;
174
- } else {
190
+ else
175
191
  nucleotideCounter++;
176
- }
192
+
177
193
  ssModificationItems.append(
178
194
  ui.divH([
179
- ui.div([ui.label(ssBases[i].value.slice(-3) == '(o)' ? '' : String(nucleotideCounter))], {style: {width: '20px'}})!,
195
+ ui.div([ui.label(ssBases[i].value.slice(-3) == '(o)' ? '' : String(nucleotideCounter))],
196
+ {style: {width: '20px'}})!,
180
197
  ui.block75([ssBases[i]])!,
181
- ui.div([ssPtoLinkages[i]])!
182
- ], {style: {alignItems: "center"}})
198
+ ui.div([ssPtoLinkages[i]])!,
199
+ ], {style: {alignItems: 'center'}}),
183
200
  );
184
201
  }
185
202
  }
@@ -197,29 +214,30 @@ export function defineAxolabsPattern() {
197
214
  updateOutputExamples();
198
215
  } else {
199
216
  ui.dialog('Sequence length is out of range')
200
- .add(ui.divText('Sequence length should be less than ' + maximalValidSequenceLength.toString() + ' due to UI constrains.'))
217
+ .add(ui.divText('Sequence length should be less than ' +
218
+ maximalValidSequenceLength.toString() + ' due to UI constrains.'))
201
219
  .add(ui.divText('Please change sequence length in order to define new pattern.'))
202
220
  .show();
203
221
  }
204
222
  }
205
223
 
206
- function updatePto(newPtoValue: boolean) {
207
- for (let i = 0; i < ssPtoLinkages.length; i++) {
224
+ function updatePto(newPtoValue: boolean): void {
225
+ for (let i = 0; i < ssPtoLinkages.length; i++)
208
226
  ssPtoLinkages[i].value = newPtoValue;
209
- }
210
- for (let i = 0; i < asPtoLinkages.length; i++) {
227
+
228
+ for (let i = 0; i < asPtoLinkages.length; i++)
211
229
  asPtoLinkages[i].value = newPtoValue;
212
- }
230
+
213
231
  updateSvgScheme();
214
232
  }
215
233
 
216
- function updateBases(newBasisValue: string) {
217
- for (let i = 0; i < ssBases.length; i++) {
234
+ function updateBases(newBasisValue: string): void {
235
+ for (let i = 0; i < ssBases.length; i++)
218
236
  ssBases[i].value = newBasisValue;
219
- }
220
- for (let i = 0; i < asBases.length; i++) {
237
+
238
+ for (let i = 0; i < asBases.length; i++)
221
239
  asBases[i].value = newBasisValue;
222
- }
240
+
223
241
  updateSvgScheme();
224
242
  }
225
243
 
@@ -230,9 +248,12 @@ export function defineAxolabsPattern() {
230
248
  }
231
249
 
232
250
  function updateOutputExamples() {
233
- ssOutputExample.value = translateSequence(ssInputExample.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value);
234
- if (createAsStrand.value)
235
- asOutputExample.value = translateSequence(asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstAsPto.value);
251
+ ssOutputExample.value = translateSequence(
252
+ ssInputExample.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value);
253
+ if (createAsStrand.value) {
254
+ asOutputExample.value = translateSequence(
255
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstAsPto.value);
256
+ }
236
257
  }
237
258
 
238
259
  function updateSvgScheme() {
@@ -251,17 +272,18 @@ export function defineAxolabsPattern() {
251
272
  asThreeModification.value,
252
273
  asFiveModification.value,
253
274
  comment.value,
254
- enumerateModifications
255
- )
256
- ])
275
+ enumerateModifications,
276
+ ),
277
+ ]),
257
278
  );
258
279
  }
259
280
 
260
281
  function detectDefaultBasis(array: string[]) {
261
- let modeMap: {[index: string]: number} = {};
262
- let maxEl = array[0], maxCount = 1;
263
- for(let i = 0; i < array.length; i++) {
264
- let el = array[i];
282
+ const modeMap: {[index: string]: number} = {};
283
+ let maxEl = array[0];
284
+ let maxCount = 1;
285
+ for (let i = 0; i < array.length; i++) {
286
+ const el = array[i];
265
287
  if (modeMap[el] == null)
266
288
  modeMap[el] = 1;
267
289
  else
@@ -275,9 +297,9 @@ export function defineAxolabsPattern() {
275
297
  }
276
298
 
277
299
  async function parsePatternAndUpdateUi(newName: string) {
278
- let pi = DG.TaskBarProgressIndicator.create('Loading pattern...');
300
+ const pi = DG.TaskBarProgressIndicator.create('Loading pattern...');
279
301
  await grok.dapi.userDataStorage.get(userStorageKey, false).then((entities) => {
280
- let obj = JSON.parse(entities[newName]);
302
+ const obj = JSON.parse(entities[newName]);
281
303
  sequenceBase.value = detectDefaultBasis(obj['asBases'].concat(obj['ssBases']));
282
304
  createAsStrand.value = (obj['asBases'].length > 0);
283
305
  saveAs.value = newName;
@@ -313,7 +335,7 @@ export function defineAxolabsPattern() {
313
335
  }
314
336
 
315
337
  function checkWhetherAllValuesInColumnHaveTheSameLength(colName: string): boolean {
316
- let col = tables.value.columns.byName(colName);
338
+ const col = tables.value.columns.byName(colName);
317
339
  let allLengthsAreTheSame = true;
318
340
  for (let i = 1; i < col.length; i++) {
319
341
  if (col.get(i - 1).length != col.get(i).length) {
@@ -322,14 +344,14 @@ export function defineAxolabsPattern() {
322
344
  }
323
345
  }
324
346
  if (!allLengthsAreTheSame) {
325
- let dialog = ui.dialog('Sequences lengths mismatch');
347
+ const dialog = ui.dialog('Sequences lengths mismatch');
326
348
  $(dialog.getButton('OK')).hide();
327
349
  dialog
328
350
  .add(ui.divText('The sequence length should match the number of Raw sequences in the input file'))
329
- .add(ui.divText("'ADD COLUMN' to see sequences lengths"))
351
+ .add(ui.divText('\'ADD COLUMN\' to see sequences lengths'))
330
352
  .addButton('ADD COLUMN', () => {
331
353
  tables.value.columns.addNewInt('Sequences lengths in ' + colName).init((j: number) => col.get(j).length);
332
- grok.shell.info("Column with lengths added to '" + tables.value.name + "'");
354
+ grok.shell.info('Column with lengths added to \'' + tables.value.name + '\'');
333
355
  dialog.close();
334
356
  grok.shell.v = grok.shell.getTableView(tables.value.name);
335
357
  })
@@ -339,47 +361,50 @@ export function defineAxolabsPattern() {
339
361
  }
340
362
 
341
363
  async function getCurrentUserName(): Promise<string> {
342
- return await grok.dapi.users.current().then((user) => {return ' (created by ' + user.firstName + ' ' + user.lastName + ')'});
364
+ return await grok.dapi.users.current().then((user) => {
365
+ return ' (created by ' + user.firstName + ' ' + user.lastName + ')';
366
+ });
343
367
  }
344
368
 
345
369
  async function postPatternToUserStorage() {
346
- let author = await getCurrentUserName();
370
+ const author = await getCurrentUserName();
347
371
  if (!saveAs.stringValue.includes('(created by '))
348
372
  saveAs.value = saveAs.stringValue + author;
349
373
  return grok.dapi.userDataStorage.postValue(
350
374
  userStorageKey,
351
375
  saveAs.stringValue,
352
376
  JSON.stringify({
353
- "ssBases": ssBases.slice(0, ssLength.value).map((e) => e.value),
354
- "asBases": asBases.slice(0, asLength.value).map((e) => e.value),
355
- "ssPtoLinkages": [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value).map((e) => e.value)),
356
- "asPtoLinkages": [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value).map((e) => e.value)),
357
- "ssThreeModification": ssThreeModification.value,
358
- "ssFiveModification": ssFiveModification.value,
359
- "asThreeModification": asThreeModification.value,
360
- "asFiveModification": asFiveModification.value,
361
- "comment": comment.value
377
+ 'ssBases': ssBases.slice(0, ssLength.value).map((e) => e.value),
378
+ 'asBases': asBases.slice(0, asLength.value).map((e) => e.value),
379
+ 'ssPtoLinkages': [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value).map((e) => e.value)),
380
+ 'asPtoLinkages': [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value).map((e) => e.value)),
381
+ 'ssThreeModification': ssThreeModification.value,
382
+ 'ssFiveModification': ssFiveModification.value,
383
+ 'asThreeModification': asThreeModification.value,
384
+ 'asFiveModification': asFiveModification.value,
385
+ 'comment': comment.value,
362
386
  }),
363
- false
364
- ).then(() => grok.shell.info("Pattern '" + saveAs.value + "' was successfully uploaded!"));
387
+ false,
388
+ ).then(() => grok.shell.info('Pattern \'' + saveAs.value + '\' was successfully uploaded!'));
365
389
  }
366
390
 
367
391
  async function updatePatternsList() {
368
392
  grok.dapi.userDataStorage.get(userStorageKey, false).then(async (entities) => {
369
- let lstMy: string[] = [],
370
- lstOthers: string[] = [];
393
+ const lstMy: string[] = [];
394
+ const lstOthers: string[] = [];
371
395
 
372
- for (let ent of Object.keys(entities))
396
+ for (const ent of Object.keys(entities)) {
373
397
  if (await isCurrentUserCreatedThisPattern(ent))
374
398
  lstOthers.push(ent);
375
399
  else
376
400
  lstMy.push(getShortName(ent));
401
+ }
377
402
 
378
403
  let loadPattern = ui.choiceInput('Load Pattern', '', lstMy, (v: string) => parsePatternAndUpdateUi(v));
379
404
 
380
- let myOrOthersPatternList = ui.choiceInput('', 'Mine', ['Mine', 'Others'], (v: string) => {
381
- let currentList = v == 'Mine' ? lstMy : lstOthers;
382
- loadPattern = ui.choiceInput('Load Pattern', '', currentList, (v: string) => parsePatternAndUpdateUi(v))
405
+ const myOrOthersPatternList = ui.choiceInput('', 'Mine', ['Mine', 'Others'], (v: string) => {
406
+ const currentList = v == 'Mine' ? lstMy : lstOthers;
407
+ loadPattern = ui.choiceInput('Load Pattern', '', currentList, (v: string) => parsePatternAndUpdateUi(v));
383
408
 
384
409
  loadPattern.root.append(myOrOthersPatternList.input);
385
410
  loadPattern.root.append(loadPattern.input);
@@ -392,17 +417,17 @@ export function defineAxolabsPattern() {
392
417
  loadPattern.root.append(
393
418
  ui.div([
394
419
  ui.button(ui.iconFA('trash-alt', () => {}), async () => {
395
- if (loadPattern.value == null) {
420
+ if (loadPattern.value == null)
396
421
  grok.shell.warning('Choose pattern to delete');
397
- } else if (await isCurrentUserCreatedThisPattern(saveAs.value)) {
422
+ else if (await isCurrentUserCreatedThisPattern(saveAs.value))
398
423
  grok.shell.warning('Cannot delete pattern, created by other user');
399
- } else {
424
+ else {
400
425
  await grok.dapi.userDataStorage.remove(userStorageKey, loadPattern.value, false)
401
- .then(() => grok.shell.info("Pattern '" + loadPattern.value + "' deleted"));
426
+ .then(() => grok.shell.info('Pattern \'' + loadPattern.value + '\' deleted'));
402
427
  }
403
428
  await updatePatternsList();
404
- })
405
- ], 'ui-input-options')
429
+ }),
430
+ ], 'ui-input-options'),
406
431
  );
407
432
  });
408
433
  loadPattern.root.append(myOrOthersPatternList.input);
@@ -416,17 +441,17 @@ export function defineAxolabsPattern() {
416
441
  loadPattern.root.append(
417
442
  ui.div([
418
443
  ui.button(ui.iconFA('trash-alt', () => {}), async () => {
419
- if (loadPattern.value == null) {
444
+ if (loadPattern.value == null)
420
445
  grok.shell.warning('Choose pattern to delete');
421
- } else if (await isCurrentUserCreatedThisPattern(saveAs.value)) {
446
+ else if (await isCurrentUserCreatedThisPattern(saveAs.value))
422
447
  grok.shell.warning('Cannot delete pattern, created by other user');
423
- } else {
448
+ else {
424
449
  await grok.dapi.userDataStorage.remove(userStorageKey, loadPattern.value, false)
425
- .then(() => grok.shell.info("Pattern '" + loadPattern.value + "' deleted"));
450
+ .then(() => grok.shell.info('Pattern \'' + loadPattern.value + '\' deleted'));
426
451
  }
427
452
  await updatePatternsList();
428
- })
429
- ], 'ui-input-options')
453
+ }),
454
+ ], 'ui-input-options'),
430
455
  );
431
456
  });
432
457
  }
@@ -435,10 +460,10 @@ export function defineAxolabsPattern() {
435
460
  await grok.dapi.userDataStorage.get(userStorageKey, false)
436
461
  .then((entities) => {
437
462
  if (Object.keys(entities).includes(saveAs.value)) {
438
- let dialog = ui.dialog('Pattern already exists');
463
+ const dialog = ui.dialog('Pattern already exists');
439
464
  $(dialog.getButton('OK')).hide();
440
465
  dialog
441
- .add(ui.divText("Pattern name '" + saveAs.value + "' already exists."))
466
+ .add(ui.divText('Pattern name \'' + saveAs.value + '\' already exists.'))
442
467
  .add(ui.divText('Replace pattern?'))
443
468
  .addButton('YES', async () => {
444
469
  await grok.dapi.userDataStorage.remove(userStorageKey, saveAs.value, false)
@@ -446,48 +471,47 @@ export function defineAxolabsPattern() {
446
471
  dialog.close();
447
472
  })
448
473
  .show();
449
- } else {
474
+ } else
450
475
  postPatternToUserStorage();
451
- }
452
476
  });
453
477
  await updatePatternsList();
454
478
  }
455
479
 
456
- let inputSsColumnDiv = ui.div([]),
457
- inputAsColumnDiv = ui.div([]),
458
- inputIdColumnDiv = ui.div([]),
459
- ssModificationItems = ui.div([]),
460
- asModificationItems = ui.div([]),
461
- svgDiv = ui.div([]),
462
- asExampleDiv = ui.div([]),
463
- appAxolabsDescription = ui.div([]),
464
- loadPatternDiv = ui.div([]),
465
- asModificationDiv = ui.div([]),
466
- firstAsPtoDiv = ui.div([]),
467
- isEnumerateModificationsDiv = ui.divH([ui.boolInput(defaultBase, true, (v: boolean) => {
468
- if (v) {
469
- if (!enumerateModifications.includes(defaultBase))
470
- enumerateModifications.push(defaultBase);
471
- } else {
472
- const index = enumerateModifications.indexOf(defaultBase, 0);
473
- if (index > -1)
474
- enumerateModifications.splice(index, 1);
475
- }
476
- updateSvgScheme();
477
- updateOutputExamples();
478
- }).root]);
480
+ const inputSsColumnDiv = ui.div([]);
481
+ const inputAsColumnDiv = ui.div([]);
482
+ const inputIdColumnDiv = ui.div([]);
483
+ const ssModificationItems = ui.div([]);
484
+ const asModificationItems = ui.div([]);
485
+ const svgDiv = ui.div([]);
486
+ const asExampleDiv = ui.div([]);
487
+ const appAxolabsDescription = ui.div([]);
488
+ const loadPatternDiv = ui.div([]);
489
+ const asModificationDiv = ui.div([]);
490
+ const firstAsPtoDiv = ui.div([]);
491
+ const isEnumerateModificationsDiv = ui.divH([ui.boolInput(defaultBase, true, (v: boolean) => {
492
+ if (v) {
493
+ if (!enumerateModifications.includes(defaultBase))
494
+ enumerateModifications.push(defaultBase);
495
+ } else {
496
+ const index = enumerateModifications.indexOf(defaultBase, 0);
497
+ if (index > -1)
498
+ enumerateModifications.splice(index, 1);
499
+ }
500
+ updateSvgScheme();
501
+ updateOutputExamples();
502
+ }).root]);
479
503
 
480
- let ssBases = Array(defaultSequenceLength).fill(ui.choiceInput('', defaultBase, baseChoices)),
481
- asBases = Array(defaultSequenceLength).fill(ui.choiceInput('', defaultBase, baseChoices)),
482
- ssPtoLinkages = Array(defaultSequenceLength).fill(ui.boolInput('', defaultPto)),
483
- asPtoLinkages = Array(defaultSequenceLength).fill(ui.boolInput('', defaultPto));
504
+ let ssBases = Array(defaultSequenceLength).fill(ui.choiceInput('', defaultBase, baseChoices));
505
+ let asBases = Array(defaultSequenceLength).fill(ui.choiceInput('', defaultBase, baseChoices));
506
+ let ssPtoLinkages = Array(defaultSequenceLength).fill(ui.boolInput('', defaultPto));
507
+ let asPtoLinkages = Array(defaultSequenceLength).fill(ui.boolInput('', defaultPto));
484
508
 
485
- let ssLength = ui.intInput('SS Length', defaultSequenceLength, () => updateUiForNewSequenceLength());
486
- let asLength = ui.intInput('AS Length', defaultSequenceLength, () => updateUiForNewSequenceLength());
487
- let asLengthDiv = ui.div([asLength.root]);
509
+ const ssLength = ui.intInput('SS Length', defaultSequenceLength, () => updateUiForNewSequenceLength());
510
+ const asLength = ui.intInput('AS Length', defaultSequenceLength, () => updateUiForNewSequenceLength());
511
+ const asLengthDiv = ui.div([asLength.root]);
488
512
 
489
513
  function validateSsColumn(colName: string) {
490
- let allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
514
+ const allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
491
515
  const firstSequence = tables.value.columns.byName(colName).get(0);
492
516
  if (allLengthsAreTheSame && firstSequence.length != ssLength.value)
493
517
  ssLength.value = tables.value.columns.byName(colName).get(0).length;
@@ -495,7 +519,7 @@ export function defineAxolabsPattern() {
495
519
  }
496
520
 
497
521
  function validateAsColumn(colName: string) {
498
- let allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
522
+ const allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
499
523
  const firstSequence = tables.value.columns.byName(colName).get(0);
500
524
  if (allLengthsAreTheSame && firstSequence.length != asLength.value)
501
525
  asLength.value = tables.value.columns.byName(colName).get(0).length;
@@ -511,18 +535,18 @@ export function defineAxolabsPattern() {
511
535
  else if (col.categories.length < col.length) {
512
536
  const duplicates = findDuplicates(col.getRawData());
513
537
  ui.dialog('Non-unique IDs')
514
- .add(ui.divText("Press 'OK' to select rows with non-unique values"))
538
+ .add(ui.divText('Press \'OK\' to select rows with non-unique values'))
515
539
  .onOK(() => {
516
- let selection = tables.value.selection;
540
+ const selection = tables.value.selection;
517
541
  selection.init((i: number) => duplicates.indexOf(col.get(i)) > -1);
518
542
  grok.shell.v = grok.shell.getTableView(tables.value.name);
519
- grok.shell.info("Rows are selected in table '" + tables.value.name + "'");
543
+ grok.shell.info('Rows are selected in table \'' + tables.value.name + '\'');
520
544
  })
521
545
  .show();
522
546
  }
523
547
  }
524
548
 
525
- let tables = ui.tableInput('Tables', grok.shell.tables[0], grok.shell.tables, (t: DG.DataFrame) => {
549
+ const tables = ui.tableInput('Tables', grok.shell.tables[0], grok.shell.tables, (t: DG.DataFrame) => {
526
550
  inputSsColumn = ui.choiceInput('SS Column', '', t.columns.names(), (colName: string) => validateSsColumn(colName));
527
551
  inputSsColumnDiv.innerHTML = '';
528
552
  inputSsColumnDiv.append(inputSsColumn.root);
@@ -543,23 +567,23 @@ export function defineAxolabsPattern() {
543
567
 
544
568
  updatePatternsList();
545
569
 
546
- let sequenceBase = ui.choiceInput('Sequence Basis', defaultBase, baseChoices, (v: string) => {
570
+ const sequenceBase = ui.choiceInput('Sequence Basis', defaultBase, baseChoices, (v: string) => {
547
571
  updateBases(v);
548
572
  updateOutputExamples();
549
573
  });
550
574
 
551
- let fullyPto = ui.boolInput('Fully PTO', defaultPto, (v: boolean) => {
575
+ const fullyPto = ui.boolInput('Fully PTO', defaultPto, (v: boolean) => {
552
576
  firstSsPto.value = v;
553
577
  firstAsPto.value = v;
554
578
  updatePto(v);
555
579
  updateOutputExamples();
556
580
  });
557
581
 
558
- let firstSsPto = ui.boolInput('First SS PTO', fullyPto.value, () => updateSvgScheme());
559
- let firstAsPto = ui.boolInput('First AS PTO', fullyPto.value, () => updateSvgScheme());
582
+ const firstSsPto = ui.boolInput('First SS PTO', fullyPto.value, () => updateSvgScheme());
583
+ const firstAsPto = ui.boolInput('First AS PTO', fullyPto.value, () => updateSvgScheme());
560
584
  firstAsPtoDiv.append(firstAsPto.root);
561
585
 
562
- let createAsStrand = ui.boolInput('Create AS Strand', true, (v: boolean) => {
586
+ const createAsStrand = ui.boolInput('Create AS Strand', true, (v: boolean) => {
563
587
  asModificationSection.hidden = (!v);
564
588
  inputAsColumnDiv.hidden = (!v);
565
589
  asLengthDiv.hidden = (!v);
@@ -569,62 +593,61 @@ export function defineAxolabsPattern() {
569
593
  updateSvgScheme();
570
594
  });
571
595
 
572
- let saveAs = ui.textInput('Save As', 'Pattern Name', () => updateSvgScheme());
596
+ const saveAs = ui.textInput('Save As', 'Pattern Name', () => updateSvgScheme());
573
597
  saveAs.setTooltip('Name Of New Pattern');
574
598
 
575
- let ssThreeModification = ui.stringInput("SS 3' Modification", "", () => {
599
+ const ssThreeModification = ui.stringInput('SS 3\' Modification', '', () => {
576
600
  updateSvgScheme();
577
601
  updateOutputExamples();
578
602
  });
579
- ssThreeModification.setTooltip("Additional SS 3' Modification");
603
+ ssThreeModification.setTooltip('Additional SS 3\' Modification');
580
604
 
581
- let ssFiveModification = ui.stringInput("SS 5' Modification", "", () => {
605
+ const ssFiveModification = ui.stringInput('SS 5\' Modification', '', () => {
582
606
  updateSvgScheme();
583
607
  updateOutputExamples();
584
608
  });
585
- ssFiveModification.setTooltip("Additional SS 5' Modification");
609
+ ssFiveModification.setTooltip('Additional SS 5\' Modification');
586
610
 
587
- let asThreeModification = ui.stringInput("AS 3' Modification", "", () => {
611
+ const asThreeModification = ui.stringInput('AS 3\' Modification', '', () => {
588
612
  updateSvgScheme();
589
613
  updateOutputExamples();
590
614
  });
591
- asThreeModification.setTooltip("Additional AS 3' Modification");
615
+ asThreeModification.setTooltip('Additional AS 3\' Modification');
592
616
 
593
- let asFiveModification = ui.stringInput("AS 5' Modification", "", () => {
617
+ const asFiveModification = ui.stringInput('AS 5\' Modification', '', () => {
594
618
  updateSvgScheme();
595
619
  updateOutputExamples();
596
620
  });
597
- asFiveModification.setTooltip("Additional AS 5' Modification");
621
+ asFiveModification.setTooltip('Additional AS 5\' Modification');
598
622
 
599
623
  asModificationDiv.append(asThreeModification.root);
600
624
  asModificationDiv.append(asFiveModification.root);
601
625
 
602
- let comment = ui.textInput('Comment', '', () => updateSvgScheme());
626
+ const comment = ui.textInput('Comment', '', () => updateSvgScheme());
603
627
 
604
- let savePatternButton = ui.button('Save', () => {
605
- if (saveAs.value != '') {
606
- savePattern().then(r => grok.shell.info('Pattern saved'));
607
- } else {
608
- let name = ui.stringInput('Enter Name', '');
628
+ const savePatternButton = ui.button('Save', () => {
629
+ if (saveAs.value != '')
630
+ savePattern().then((r) => grok.shell.info('Pattern saved'));
631
+ else {
632
+ const name = ui.stringInput('Enter Name', '');
609
633
  ui.dialog('Pattern Name')
610
634
  .add(name.root)
611
635
  .onOK(() => {
612
636
  saveAs.value = name.value;
613
- savePattern().then(r => grok.shell.info('Pattern saved'));
637
+ savePattern().then((r) => grok.shell.info('Pattern saved'));
614
638
  })
615
639
  .show();
616
640
  }
617
641
  });
618
642
 
619
- let convertSequenceButton = ui.button('Convert Sequences', () => {
620
- if (inputSsColumn.value == null || (createAsStrand.value && inputAsColumn.value == null)) {
621
- grok.shell.info("Please select table and columns on which to apply pattern");
622
- }
643
+ const convertSequenceButton = ui.button('Convert Sequences', () => {
644
+ if (inputSsColumn.value == null || (createAsStrand.value && inputAsColumn.value == null))
645
+ grok.shell.info('Please select table and columns on which to apply pattern');
623
646
  else if (ssLength.value != ssInputExample.value.length || asLength.value != asInputExample.value.length) {
624
- let dialog = ui.dialog("Length Mismatch")
647
+ const dialog = ui.dialog('Length Mismatch');
625
648
  $(dialog.getButton('OK')).hide();
626
649
  dialog
627
- .add(ui.divText("Length of sequences in columns doesn't match entered length. Update length value?"))
650
+ .add(ui.divText('Length of sequences in columns doesn\'t match entered length. Update length value?'))
628
651
  .addButton('YES', () => {
629
652
  ssLength.value = tables.value.columns.byName(inputSsColumn.value).getString(0).length;
630
653
  asLength.value = tables.value.columns.byName(inputAsColumn.value).getString(0).length;
@@ -634,18 +657,26 @@ export function defineAxolabsPattern() {
634
657
  } else {
635
658
  if (inputIdColumn.value != null)
636
659
  addColumnWithIds(tables.value.name, inputIdColumn.value, getShortName(saveAs.value));
637
- addColumnWithTranslatedSequences(tables.value.name, inputSsColumn.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value);
638
- if (createAsStrand.value)
639
- addColumnWithTranslatedSequences(tables.value.name, inputAsColumn.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstAsPto.value);
660
+ addColumnWithTranslatedSequences(
661
+ tables.value.name, inputSsColumn.value, ssBases, ssPtoLinkages,
662
+ ssFiveModification, ssThreeModification, firstSsPto.value);
663
+ if (createAsStrand.value) {
664
+ addColumnWithTranslatedSequences(
665
+ tables.value.name, inputAsColumn.value, asBases, asPtoLinkages,
666
+ asFiveModification, asThreeModification, firstAsPto.value);
667
+ }
640
668
  grok.shell.v = grok.shell.getTableView(tables.value.name);
641
- grok.shell.info(((createAsStrand.value) ? "Columns were" : "Column was") + " added to table '" + tables.value.name + "'");
669
+ grok.shell.info(((createAsStrand.value) ? 'Columns were' : 'Column was') +
670
+ ' added to table \'' + tables.value.name + '\'');
642
671
  }
643
672
  });
644
673
 
645
- let ssInputExample = ui.textInput('Sense Strand', generateExample(ssLength.value, sequenceBase.value),() => {
646
- ssOutputExample.value = translateSequence(ssInputExample.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value)
674
+ const ssInputExample = ui.textInput('Sense Strand', generateExample(ssLength.value, sequenceBase.value), () => {
675
+ ssOutputExample.value = translateSequence(ssInputExample.value, ssBases, ssPtoLinkages,
676
+ ssFiveModification, ssThreeModification, firstSsPto.value);
647
677
  });
648
- let ssOutputExample = ui.textInput(' ', translateSequence(ssInputExample.value, ssBases, ssPtoLinkages, ssThreeModification, ssFiveModification, firstSsPto.value));
678
+ const ssOutputExample = ui.textInput(' ', translateSequence(
679
+ ssInputExample.value, ssBases, ssPtoLinkages, ssThreeModification, ssFiveModification, firstSsPto.value));
649
680
  (ssInputExample.input as HTMLElement).style.resize = 'none';
650
681
  (ssInputExample.input as HTMLElement).style.minWidth = exampleMinWidth;
651
682
  (ssOutputExample.input as HTMLElement).style.resize = 'none';
@@ -655,15 +686,18 @@ export function defineAxolabsPattern() {
655
686
  ssOutputExample.root.append(
656
687
  ui.div([
657
688
  ui.button(ui.iconFA('copy', () => {}), () => {
658
- navigator.clipboard.writeText(ssOutputExample.value).then(() => grok.shell.info('Sequence was copied to clipboard'));
659
- })
660
- ], 'ui-input-options')
689
+ navigator.clipboard.writeText(ssOutputExample.value).then(() =>
690
+ grok.shell.info('Sequence was copied to clipboard'));
691
+ }),
692
+ ], 'ui-input-options'),
661
693
  );
662
694
 
663
- let asInputExample = ui.textInput('Antisense Strand', generateExample(asLength.value, sequenceBase.value),() => {
664
- asOutputExample.value = translateSequence(asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value);
695
+ const asInputExample = ui.textInput('Antisense Strand', generateExample(asLength.value, sequenceBase.value), () => {
696
+ asOutputExample.value = translateSequence(
697
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value);
665
698
  });
666
- let asOutputExample = ui.textInput(' ', translateSequence(asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value));
699
+ const asOutputExample = ui.textInput(' ', translateSequence(
700
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value));
667
701
  (asInputExample.input as HTMLElement).style.resize = 'none';
668
702
  (asInputExample.input as HTMLElement).style.minWidth = exampleMinWidth;
669
703
  (asOutputExample.input as HTMLElement).style.resize = 'none';
@@ -673,40 +707,41 @@ export function defineAxolabsPattern() {
673
707
  asOutputExample.root.append(
674
708
  ui.div([
675
709
  ui.button(ui.iconFA('copy', () => {}), () => {
676
- navigator.clipboard.writeText(asOutputExample.value).then(() => grok.shell.info('Sequence was copied to clipboard'));
677
- })
678
- ], 'ui-input-options')
710
+ navigator.clipboard.writeText(asOutputExample.value).then(() =>
711
+ grok.shell.info('Sequence was copied to clipboard'));
712
+ }),
713
+ ], 'ui-input-options'),
679
714
  );
680
715
  asExampleDiv.append(asInputExample.root);
681
716
  asExampleDiv.append(asOutputExample.root);
682
717
 
683
718
  updateUiForNewSequenceLength();
684
719
 
685
- let exampleSection = ui.div([
720
+ const exampleSection = ui.div([
686
721
  ui.h1('Example'),
687
722
  ssInputExample.root,
688
723
  ssOutputExample.root,
689
- asExampleDiv
724
+ asExampleDiv,
690
725
  ], 'ui-form');
691
726
 
692
- let inputsSection = ui.div([
727
+ const inputsSection = ui.div([
693
728
  ui.h1('Inputs'),
694
729
  ui.divH([
695
730
  tables.root,
696
- inputSsColumnDiv
731
+ inputSsColumnDiv,
697
732
  ]),
698
733
  ui.divH([
699
734
  inputAsColumnDiv,
700
- inputIdColumnDiv
735
+ inputIdColumnDiv,
701
736
  ]),
702
737
  ui.buttonsInput([
703
- convertSequenceButton
704
- ])
738
+ convertSequenceButton,
739
+ ]),
705
740
  ], 'ui-form');
706
741
 
707
- let mainSection = ui.panel([
742
+ const mainSection = ui.panel([
708
743
  ui.block([
709
- svgDiv
744
+ svgDiv,
710
745
  ], {style: {overflowX: 'scroll'}}),
711
746
  ui.button('Download', () => svg.saveSvgAsPng(document.getElementById('mySvg'), saveAs.value)),
712
747
  isEnumerateModificationsDiv,
@@ -715,11 +750,11 @@ export function defineAxolabsPattern() {
715
750
  ui.divH([
716
751
  ui.h1('Pattern'),
717
752
  ui.div([
718
- ui.iconFA('question-circle',() => {
753
+ ui.iconFA('question-circle', () => {
719
754
  appAxolabsDescription.innerHTML = '';
720
755
  appAxolabsDescription.append(info);
721
- })
722
- ], {style: {padding: '2px'}})
756
+ }),
757
+ ], {style: {padding: '2px'}}),
723
758
  ]),
724
759
  ui.divH([
725
760
  ui.div([
@@ -730,8 +765,8 @@ export function defineAxolabsPattern() {
730
765
  loadPatternDiv,
731
766
  saveAs.root,
732
767
  ui.buttonsInput([
733
- savePatternButton
734
- ])
768
+ savePatternButton,
769
+ ]),
735
770
  ], 'ui-form'),
736
771
  ui.div([
737
772
  createAsStrand.root,
@@ -741,56 +776,56 @@ export function defineAxolabsPattern() {
741
776
  ssFiveModification.root,
742
777
  ssThreeModification.root,
743
778
  asModificationDiv,
744
- ], 'ui-form')
745
- ], 'ui-form')
779
+ ], 'ui-form'),
780
+ ], 'ui-form'),
746
781
  ], 'ui-form'),
747
782
  inputsSection,
748
- exampleSection
749
- ], {style: {flexWrap: 'wrap'}})
783
+ exampleSection,
784
+ ], {style: {flexWrap: 'wrap'}}),
750
785
  ]);
751
786
 
752
- let ssModificationSection = ui.panel([
787
+ const ssModificationSection = ui.panel([
753
788
  ui.h1('Sense Strand'),
754
789
  ui.divH([
755
790
  ui.div([ui.divText('#')], {style: {width: '20px'}})!,
756
791
  ui.block75([ui.divText('Modification')])!,
757
- ui.div([ui.divText('PTO')], {style: {paddingRight: '8px'}})!
792
+ ui.div([ui.divText('PTO')], {style: {paddingRight: '8px'}})!,
758
793
  ]),
759
- ssModificationItems
794
+ ssModificationItems,
760
795
  ])!;
761
796
 
762
- let asModificationSection = ui.panel([
797
+ const asModificationSection = ui.panel([
763
798
  ui.h1('Antisense Strand'),
764
799
  ui.divH([
765
800
  ui.div([ui.divText('#')], {style: {width: '20px'}})!,
766
801
  ui.block75([ui.divText('Modification')])!,
767
- ui.div([ui.divText('PTO')], {style: {paddingRight: '8px'}})!
802
+ ui.div([ui.divText('PTO')], {style: {paddingRight: '8px'}})!,
768
803
  ]),
769
- asModificationItems
804
+ asModificationItems,
770
805
  ])!;
771
806
 
772
- let info = ui.info(
807
+ const info = ui.info(
773
808
  [
774
- ui.divText("\n How to define new pattern:",{style: {'font-weight': 'bolder'}}),
775
- ui.divText("1. Choose table and columns with sense and antisense strands"),
776
- ui.divText("2. Choose lengths of both strands by editing checkboxes below"),
777
- ui.divText("3. Choose basis and PTO status for each nucleotide"),
778
- ui.divText("4. Set additional modifications for sequence edges"),
779
- ui.divText("5. Press 'Convert Sequences' button"),
780
- ui.divText("This will add the result column(s) to the right of the table"),
781
- ], 'Create and apply Axolabs translation patterns.'
809
+ ui.divText('\n How to define new pattern:', {style: {'font-weight': 'bolder'}}),
810
+ ui.divText('1. Choose table and columns with sense and antisense strands'),
811
+ ui.divText('2. Choose lengths of both strands by editing checkboxes below'),
812
+ ui.divText('3. Choose basis and PTO status for each nucleotide'),
813
+ ui.divText('4. Set additional modifications for sequence edges'),
814
+ ui.divText('5. Press \'Convert Sequences\' button'),
815
+ ui.divText('This will add the result column(s) to the right of the table'),
816
+ ], 'Create and apply Axolabs translation patterns.',
782
817
  );
783
818
 
784
819
  return ui.splitH([
785
820
  ui.div([
786
821
  appAxolabsDescription,
787
- mainSection!
822
+ mainSection!,
788
823
  ])!,
789
824
  ui.box(
790
825
  ui.divH([
791
826
  ssModificationSection,
792
- asModificationSection
793
- ]), {style: {maxWidth: '360px'}}
794
- )
827
+ asModificationSection,
828
+ ]), {style: {maxWidth: '360px'}},
829
+ ),
795
830
  ]);
796
- }
831
+ }