@datagrok/sequence-translator 0.0.4 → 0.0.8

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