@datagrok/sequence-translator 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.0.9",
4
+ "version": "1.0.11",
5
5
  "author": {
6
6
  "name": "Vadym Kovadlo",
7
7
  "email": "vkovadlo@datagrok.ai"
@@ -13,9 +13,9 @@
13
13
  "directory": "packages/SequenceTranslator"
14
14
  },
15
15
  "dependencies": {
16
- "@datagrok-libraries/utils": "^1.9.2",
16
+ "@datagrok-libraries/utils": "^1.11.1",
17
17
  "@types/react": "^18.0.15",
18
- "datagrok-api": "^1.6.0",
18
+ "datagrok-api": "^1.7.2",
19
19
  "datagrok-tools": "^4.1.2",
20
20
  "npm": "^8.11.0",
21
21
  "openchemlib": "6.0.1",
@@ -1,11 +1,12 @@
1
1
  import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
- import {siRnaAxolabsToGcrs, gcrsToNucleotides, asoGapmersBioSpringToGcrs, gcrsToMermade12,
5
- } from '../structures-works/converters';
4
+ import {siRnaBioSpringToGcrs, siRnaAxolabsToGcrs, gcrsToNucleotides, asoGapmersBioSpringToGcrs, gcrsToMermade12,
5
+ siRnaNucleotidesToGcrs} from '../structures-works/converters';
6
6
  import {map, COL_NAMES, MODIFICATIONS} from '../structures-works/map';
7
7
  import {isValidSequence} from '../structures-works/sequence-codes-tools';
8
8
  import {sequenceToMolV3000} from '../structures-works/from-monomers';
9
+ import {linkV3000} from '../structures-works/mol-transformations';
9
10
 
10
11
  import {SALTS_CSV} from '../salts';
11
12
  import {USERS_CSV} from '../users';
@@ -54,6 +55,10 @@ function molecularWeight(sequence: string, weightsObj: {[index: string]: number}
54
55
  return weight - 61.97;
55
56
  }
56
57
 
58
+ function parseStrandsFromDuplexCell(s: string): string[] {
59
+ return s.slice(3).split('\r\nAS ');
60
+ }
61
+
57
62
  async function saveTableAsSdFile(table: DG.DataFrame) {
58
63
  if (!table.columns.contains('Compound Name')) {
59
64
  grok.shell.warning(
@@ -67,9 +72,23 @@ async function saveTableAsSdFile(table: DG.DataFrame) {
67
72
  let result = '';
68
73
  for (let i = 0; i < table.rowCount; i++) {
69
74
  const format = 'Janssen GCRS Codes'; //getFormat(structureColumn.get(i))!;
70
- result += (typeColumn.get(i) == 'SS') ?
71
- sequenceToMolV3000(structureColumn.get(i), false, true, format) + '\n' + `> <Sequence>\nSense Strand\n\n` :
72
- sequenceToMolV3000(structureColumn.get(i), true, true, format) + '\n' + `> <Sequence>\nAnti Sense\n\n`;
75
+ if (typeColumn.get(i) == 'Duplex') {
76
+ const array = parseStrandsFromDuplexCell(structureColumn.get(i));
77
+ const as = sequenceToMolV3000(array[1], true, true, format) +
78
+ '\n' + `> <Sequence>\nAnti Sense\n\n`;
79
+ const ss = sequenceToMolV3000(array[0], false, true, format) +
80
+ '\n' + `> <Sequence>\nSense Strand\n\n`;
81
+ result += linkV3000([ss, as], true, true) + '\n\n';
82
+ } else if (typeColumn.get(i) == 'SS') {
83
+ const molSS = sequenceToMolV3000(structureColumn.get(i), false, true, format) +
84
+ '\n' + `> <Sequence>\nSense Strand\n\n`;
85
+ result += molSS;
86
+ } else if (typeColumn.get(i) == 'AS') {
87
+ const molAS = sequenceToMolV3000(structureColumn.get(i), true, true, format) +
88
+ '\n' + `> <Sequence>\nAnti Sense\n\n`;
89
+ result += molAS;
90
+ }
91
+
73
92
  for (const col of table.columns) {
74
93
  if (col.name != COL_NAMES.SEQUENCE)
75
94
  result += `> <${col.name}>\n${col.get(i)}\n\n`;
@@ -90,6 +109,13 @@ export function autostartOligoSdFileSubscription() {
90
109
  grok.events.onContextMenu.subscribe((args) => {
91
110
  const seqCol = args.args.context.table.currentCol; // /^[fsACGUacgu]{6,}$/
92
111
  if (DG.Detector.sampleCategories(seqCol,
112
+ (s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C){6,}$/.test(s))) {
113
+ args.args.menu.item('Convert raw nucleotides to GCRS', () => {
114
+ args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
115
+ return siRnaNucleotidesToGcrs(seqCol.get(i));
116
+ });
117
+ });
118
+ } else if (DG.Detector.sampleCategories(seqCol,
93
119
  (s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|f|s|A|C|G|U|a|c|g|u){6,}$/.test(s))) {
94
120
  args.args.menu.item('Convert Axolabs to GCRS', () => {
95
121
  args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
@@ -121,7 +147,7 @@ export function autostartOligoSdFileSubscription() {
121
147
  (s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|\*|1|2|3|4|5|6|7|8){6,}$/.test(s))) {
122
148
  args.args.menu.item('Convert Biospring to GCRS', () => {
123
149
  args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
124
- return siRnaAxolabsToGcrs(seqCol.get(i));
150
+ return siRnaBioSpringToGcrs(seqCol.get(i));
125
151
  });
126
152
  });
127
153
  }
@@ -141,6 +167,7 @@ export function oligoSdFile(table: DG.DataFrame) {
141
167
  const saltCol = table.getCol(COL_NAMES.SALT);
142
168
  const equivalentsCol = table.getCol(COL_NAMES.EQUIVALENTS);
143
169
  const typeColumn = table.getCol(COL_NAMES.TYPE);
170
+ const chemistryNameCol = table.getCol(COL_NAMES.CHEMISTRY_NAME);
144
171
 
145
172
  const molWeightCol = saltsDf.getCol('MOLWEIGHT');
146
173
  const saltNamesList = saltsDf.getCol('DISPLAY').toList();
@@ -154,12 +181,17 @@ export function oligoSdFile(table: DG.DataFrame) {
154
181
  t.rows.removeAt(i, 1, false);
155
182
  }
156
183
 
157
- t.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => sequenceCol.get(i));
184
+ t.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => {
185
+ return (typeColumn.get(i) == 'Duplex') ? chemistryNameCol.get(i) : sequenceCol.get(i);
186
+ });
158
187
 
159
- t.columns.addNewString(COL_NAMES.COMPOUND_COMMENTS).init((i: number) => (i > 2 && typeColumn.get(i) == 'Duplex') ?
160
- sequenceCol.get(i) + '; duplex of SS: ' + sequenceCol.get(i - 2) + ' and AS: ' + sequenceCol.get(i - 1) :
161
- sequenceCol.get(i),
162
- );
188
+ t.columns.addNewString(COL_NAMES.COMPOUND_COMMENTS).init((i: number) => {
189
+ if (typeColumn.get(i) == 'Duplex') {
190
+ const arr = parseStrandsFromDuplexCell(sequenceCol.get(i));
191
+ return chemistryNameCol.get(i) + '; duplex of SS: ' + arr[0] + ' and AS: ' + arr[1];
192
+ }
193
+ return sequenceCol.get(i);
194
+ });
163
195
 
164
196
  const weightsObj: {[code: string]: number} = {};
165
197
  for (const synthesizer of Object.keys(map)) {
@@ -172,6 +204,15 @@ export function oligoSdFile(table: DG.DataFrame) {
172
204
  weightsObj[key] = value.molecularWeight;
173
205
 
174
206
  t.columns.addNewFloat(COL_NAMES.CPD_MW).init((i: number) => {
207
+ if (typeColumn.get(i) == 'Duplex') {
208
+ const arr = parseStrandsFromDuplexCell(sequenceCol.get(i));
209
+ return (
210
+ isValidSequence(arr[0], null).indexOfFirstNotValidChar == -1 &&
211
+ isValidSequence(arr[1], null).indexOfFirstNotValidChar == -1
212
+ ) ?
213
+ molecularWeight(arr[0], weightsObj) + molecularWeight(arr[1], weightsObj) :
214
+ DG.FLOAT_NULL;
215
+ }
175
216
  return (isValidSequence(sequenceCol.get(i), null).indexOfFirstNotValidChar == -1) ?
176
217
  molecularWeight(sequenceCol.get(i), weightsObj) :
177
218
  DG.FLOAT_NULL;
@@ -1,5 +1,5 @@
1
1
  const rnaColor = 'rgb(255,230,153)';
2
- const invAbasicColor = 'rgb(255,230,153)';
2
+ const invAbasicColor = 'rgb(203,119,211)';
3
3
  export const axolabsMap:
4
4
  {[index: string]: {fullName: string, symbols: [string, string, string, string], color: string}} =
5
5
  {
@@ -703,6 +703,7 @@ export function defineAxolabsPattern() {
703
703
  grok.shell.v = grok.shell.getTableView(tables.value!.name);
704
704
  grok.shell.info(((createAsStrand.value) ? 'Columns were' : 'Column was') +
705
705
  ' added to table \'' + tables.value!.name + '\'');
706
+ updateOutputExamples();
706
707
  }
707
708
  });
708
709
 
@@ -38,8 +38,11 @@ function getTextWidth(text: string, font: number): number {
38
38
  function getTextInsideCircle(
39
39
  bases: string[], index: number, nucleotideCounter: number,
40
40
  numberOfNucleotides: number, enumerateModifications: string[]): string {
41
- return (bases[index].slice(-3) == '(o)') || !enumerateModifications.includes(bases[index]) ? '' :
42
- ['A', 'G', 'C', 'U', 'T'].includes(bases[index]) ? bases[index] : String(numberOfNucleotides - nucleotideCounter);
41
+ return ((bases[index].slice(-3) == '(o)') || !enumerateModifications.includes(bases[index])) ?
42
+ '' :
43
+ (['A', 'G', 'C', 'U', 'T'].includes(bases[index])) ?
44
+ bases[index] :
45
+ '';//String(numberOfNucleotides - nucleotideCounter);
43
46
  }
44
47
 
45
48
  function getFontColorVisibleOnBackground(rgbString: string): string {
@@ -157,6 +160,7 @@ export function drawAxolabsPattern(
157
160
  Math.max(xOfSsRightModifications, xOfAsRightModifications) +
158
161
  widthOfLeftModification + baseDiameter * (Math.max(ssRightOverhangs, asRightOverhangs));
159
162
  const yOfTitle = baseRadius;
163
+ const yOfNumbers = 2 * baseRadius;
160
164
  const yOfSsTexts = 4 * baseRadius;
161
165
  const yOfAsTexts = 7 * baseRadius;
162
166
  const yOfComment = asExists ? 11 * baseRadius : 8.5 * baseRadius;
@@ -188,14 +192,15 @@ export function drawAxolabsPattern(
188
192
  }
189
193
  let nucleotideCounter = numberOfSsNucleotides;
190
194
  for (let i = ssBases.length - 1; i > -1; i--) {
195
+ const xOfNumbers = getXOfBaseCircles(i, ssRightOverhangs) +
196
+ getShiftToAlignNumberInsideCircle(ssBases, ssBases.length - i, numberOfSsNucleotides - nucleotideCounter);
191
197
  if (ssBases[i].slice(-3) != '(o)')
192
198
  nucleotideCounter--;
193
199
  image.append(
200
+ svg.text(String(numberOfSsNucleotides - nucleotideCounter), xOfNumbers, yOfNumbers, legendFontSize, fontColor),
194
201
  svg.circle(getXOfBaseCircles(i, ssRightOverhangs), yOfSsCircles, baseRadius, getBaseColor(ssBases[i])),
195
202
  svg.text(getTextInsideCircle(ssBases, i, nucleotideCounter, numberOfSsNucleotides, enumerateModifications),
196
- getXOfBaseCircles(i, ssRightOverhangs) +
197
- getShiftToAlignNumberInsideCircle(ssBases, ssBases.length - i, numberOfSsNucleotides - nucleotideCounter),
198
- yOfSsTexts, baseFontSize, getFontColorVisibleOnBackground(axolabsMap[ssBases[i]]['color'])),
203
+ xOfNumbers, yOfSsTexts, baseFontSize, getFontColorVisibleOnBackground(axolabsMap[ssBases[i]]['color'])),
199
204
  ssPtoStatuses[i] ?
200
205
  svg.star(getXOfBaseCircles(i, ssRightOverhangs) + baseRadius, yOfSsTexts + psLinkageRadius, psLinkageColor) :
201
206
  '',
@@ -19,8 +19,7 @@ export function mainView() {
19
19
  try {
20
20
  sequence = sequence.replace(/\s/g, '');
21
21
  const output = isValidSequence(sequence, null);
22
- output.synthesizer = [inputFormat];
23
- // inputFormatChoiceInput.value = output.synthesizer![0];
22
+ inputFormatChoiceInput.value = output.synthesizer![0];
24
23
  const outputSequenceObj = convertSequence(sequence, output);
25
24
  const tableRows = [];
26
25
 
@@ -1,13 +1,16 @@
1
1
  import * as DG from 'datagrok-api/dg';
2
- import {runTests, tests} from '@datagrok-libraries/utils/src/test';
2
+ import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
3
3
  import './tests/smiles-tests';
4
4
 
5
5
  export const _package = new DG.Package();
6
6
  export {tests};
7
7
 
8
8
  //name: test
9
+ //input: string category {optional: true}
10
+ //input: string test {optional: true}
11
+ //input: object testContext {optional: true}
9
12
  //output: dataframe result
10
- export async function test(): Promise<DG.DataFrame> {
11
- const data = await runTests();
13
+ export async function test(category: string, test: string, testContext: TestContext): Promise<DG.DataFrame> {
14
+ const data = await runTests({category, test, testContext});
12
15
  return DG.DataFrame.fromObjects(data)!;
13
16
  }
@@ -96,9 +96,10 @@ export function asoGapmersBioSpringToGcrs(nucleotides: string): string {
96
96
  //output: string result {semType: BioSpring / Gapmers}
97
97
  export function asoGapmersGcrsToBioSpring(nucleotides: string): string {
98
98
  const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
99
+ 'fU': '1', 'fA': '2', 'fC': '3', 'fG': '4', 'mU': '5', 'mA': '6', 'mC': '7', 'mG': '8',
99
100
  'moeT': '5', 'moeA': '6', 'moe5mC': '7', 'moeG': '8', 'moeU': '5', '5mC': '9', 'nps': '*', 'ps': '*', 'U': 'T',
100
101
  };
101
- return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|moeT|moeA|moe5mC|moeG|moeU|5mC|nps|ps|U)/g,
102
+ return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|fU|fA|fC|fG|mU|mA|mC|mG|moeT|moeA|moe5mC|moeG|moeU|5mC|nps|ps|U)/g,
102
103
  function(x: string) {return obj[x];});
103
104
  }
104
105