@datagrok/sequence-translator 1.0.14 → 1.0.15

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.14",
4
+ "version": "1.0.15",
5
5
  "author": {
6
6
  "name": "Alexey Choposky",
7
7
  "email": "achopovsky@datagrok.ai"
@@ -13,7 +13,7 @@
13
13
  "directory": "packages/SequenceTranslator"
14
14
  },
15
15
  "dependencies": {
16
- "@datagrok-libraries/utils": "^1.15.5",
16
+ "@datagrok-libraries/utils": "^1.17.2",
17
17
  "@types/react": "^18.0.15",
18
18
  "@datagrok-libraries/bio": "^5.11.1",
19
19
  "datagrok-api": "^1.7.2",
@@ -24,25 +24,6 @@
24
24
  "ts-loader": "^9.3.1",
25
25
  "typescript": "^4.7.4"
26
26
  },
27
- "scripts": {
28
- "link-api": "npm link datagrok-api",
29
- "link-all": "npm link datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
30
- "debug-sequencetranslator": "grok publish",
31
- "release-sequencetranslator": "grok publish localhost --release",
32
- "build-sequencetranslator": "webpack",
33
- "build": "webpack",
34
- "debug-sequencetranslator-public": "grok publish public",
35
- "release-sequencetranslator-public": "grok publish public --release",
36
- "debug-sequencetranslator-local": "grok publish local",
37
- "release-sequencetranslator-local": "grok publish local --release",
38
- "test": "jest",
39
- "test-dev": "set HOST=dev && jest",
40
- "test-local": "set HOST=localhost && jest"
41
- },
42
- "sources": [
43
- "css/style.css",
44
- "vendors/openchemlib-full.js"
45
- ],
46
27
  "devDependencies": {
47
28
  "@types/jest": "^27.0.0",
48
29
  "@types/jquery": "^3.5.14",
@@ -62,5 +43,27 @@
62
43
  "@types/node-fetch": "^2.6.2",
63
44
  "node-fetch": "^2.6.7"
64
45
  },
46
+ "grokDependencies": {
47
+ "@datagrok/chem": "1.3.32"
48
+ },
49
+ "scripts": {
50
+ "link-api": "npm link datagrok-api",
51
+ "link-all": "npm link datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
52
+ "debug-sequencetranslator": "grok publish",
53
+ "release-sequencetranslator": "grok publish localhost --release",
54
+ "build-sequencetranslator": "webpack",
55
+ "build": "webpack",
56
+ "debug-sequencetranslator-public": "grok publish public",
57
+ "release-sequencetranslator-public": "grok publish public --release",
58
+ "debug-sequencetranslator-local": "grok publish local",
59
+ "release-sequencetranslator-local": "grok publish local --release",
60
+ "test": "jest",
61
+ "test-dev": "set HOST=dev && jest",
62
+ "test-local": "set HOST=localhost && jest"
63
+ },
64
+ "sources": [
65
+ "css/style.css",
66
+ "vendors/openchemlib-full.js"
67
+ ],
65
68
  "category": "Bioinformatics"
66
69
  }
@@ -1,10 +1,8 @@
1
1
  from io import TextIOWrapper
2
2
 
3
- from rdkit.Chem import AllChem
4
3
  from rdkit import Chem
5
4
 
6
5
  import orjson
7
- import json
8
6
 
9
7
  import click
10
8
 
@@ -12,16 +10,55 @@ from click_default_group import DefaultGroup
12
10
  from rdkit.Chem.rdchem import Mol
13
11
 
14
12
 
15
- def smiles2molfile(smiles: str) -> str:
16
- mol: Mol = Chem.MolFromSmiles(smiles)
13
+ def molAddCollection(mol: Mol, name: str, title: str = None) -> str:
14
+ """
15
+ Get and postprocess (atom's CFG, title, e.t.c.) molblock
16
+ :param mol: Mol molecule structure / object
17
+ :param name: Monomer name to add to molblock title
18
+ :param title: title to replace in Chem.MolToMolBlock() string output
19
+ :return: molblock string
20
+ """
17
21
  res: str = Chem.MolToMolBlock(mol, forceV3000=True) # MolToMolFile
18
- return res
19
22
 
23
+ mb_line_list: list[str] = res.split('\n')
24
+ if title:
25
+ mb_line_list[1] = title
26
+
27
+ if name and name not in mb_line_list[1]:
28
+ mb_line_list[1] += '|' + name
29
+
30
+ end_bond_idx: int = mb_line_list.index('M V30 END BOND')
31
+ chirality = [atom.GetChiralTag() for atom in mol.GetAtoms()]
32
+ begin_atom_idx = mb_line_list.index('M V30 BEGIN ATOM')
33
+ end_atom_idx = mb_line_list.index('M V30 END ATOM')
34
+ for atom_idx in range(1, end_atom_idx - begin_atom_idx):
35
+ line_idx = begin_atom_idx + atom_idx
36
+ atom_ch = chirality[atom_idx - 1]
37
+ if atom_ch != Chem.rdchem.CHI_UNSPECIFIED:
38
+ mb_line_list[line_idx] += " CFG={0}".format(int(atom_ch))
39
+
40
+ steabs: list[int] = [i + 1 for (i, ch) in enumerate(chirality) if ch != Chem.rdchem.CHI_UNSPECIFIED]
41
+ if len(steabs) > 0:
42
+ steabs_str: str = "M V30 MDLV30/STEABS ATOMS=({count} {list})" \
43
+ .format(count=len(steabs), list=' '.join([str(idx) for idx in steabs]))
44
+
45
+ mb_line_list = mb_line_list[:(end_bond_idx + 1)] + \
46
+ ["M V30 BEGIN COLLECTION", steabs_str, "M V30 END COLLECTION"] + \
47
+ mb_line_list[(end_bond_idx + 1):]
20
48
 
21
- def molV2000toMolV3000(molV2K: str) -> str:
22
- mol: str = Chem.MolFromMolBlock(molV2K)
23
- res: str = Chem.MolToMolBlock(mol, forceV3000=True)
24
- return res.replace('Pol', 'O ')
49
+ return '\n'.join(mb_line_list)
50
+
51
+
52
+ def molfile2molfile(src_mol: str, name: str) -> str:
53
+ mol: Mol = Chem.MolFromMolBlock(src_mol)
54
+ src_mf_lines = src_mol.split('\n')
55
+ title = src_mf_lines[1]
56
+ return molAddCollection(mol, name, title=title)
57
+
58
+
59
+ def smiles2molfile(smiles: str, name: str) -> str:
60
+ mol: Mol = Chem.MolFromSmiles(smiles)
61
+ return molAddCollection(mol, name)
25
62
 
26
63
 
27
64
  CodesType = dict[str, dict[str, list[str]]]
@@ -29,13 +66,13 @@ CodesType = dict[str, dict[str, list[str]]]
29
66
 
30
67
  class Monomer:
31
68
  def __init__(self,
32
- symbol: str, name: str, smiles: str,
69
+ symbol: str, name: str, molfile: str, smiles: str,
33
70
  codes: CodesType):
34
71
  self.monomerType = 'Backbone'
35
72
  self.smiles = smiles
36
73
  self.name = name
37
74
  self.author = 'SequenceTranslator'
38
- self.molfile = smiles2molfile(smiles)
75
+ self.molfile = molfile2molfile(molfile, name) if molfile else smiles2molfile(smiles, name)
39
76
  self.naturalAnalog = ''
40
77
  self.rgroups = [
41
78
  {
@@ -58,8 +95,9 @@ class Monomer:
58
95
 
59
96
  @staticmethod
60
97
  def from_json(src_json: {}):
61
- obj = Monomer(src_json['symbol'], src_json['name'], src_json['smiles'], src_json['codes'])
62
- obj.molfile = src_json['molfile']
98
+ obj = Monomer(src_json['symbol'], src_json['name'],
99
+ src_json['molfile'], src_json['smiles'],
100
+ src_json['codes'])
63
101
  return obj
64
102
 
65
103
  def to_json(self):
@@ -89,7 +127,7 @@ def codes2monomers(codes_json: {}) -> dict[str, Monomer]:
89
127
  symbol = monomer_json['name']
90
128
  name = monomer_json['name']
91
129
  smiles = monomer_json['SMILES']
92
- monomers_res[monomer_name] = Monomer(symbol, name, smiles, {})
130
+ monomers_res[monomer_name] = Monomer(symbol, name, None, smiles, {})
93
131
  codes = monomers_res[monomer_name].codes
94
132
  if codes_src not in codes:
95
133
  codes[codes_src] = {}
@@ -44,22 +44,22 @@ export const AXOLABS_MAP:
44
44
  color: 'rgb(255,192,0)',
45
45
  },
46
46
  'A': {
47
- fullName: 'Adenine',
47
+ fullName: 'Adenosine',
48
48
  symbols: ['a', 'a', 'a', 'a'],
49
49
  color: RNA_COLOR,
50
50
  },
51
51
  'C': {
52
- fullName: 'Cytosine',
52
+ fullName: 'Cytidine',
53
53
  symbols: ['c', 'c', 'c', 'c'],
54
54
  color: RNA_COLOR,
55
55
  },
56
56
  'G': {
57
- fullName: 'Guanine',
57
+ fullName: 'Guanosine',
58
58
  symbols: ['g', 'g', 'g', 'g'],
59
59
  color: RNA_COLOR,
60
60
  },
61
61
  'U': {
62
- fullName: 'Uracil',
62
+ fullName: 'Uridine',
63
63
  symbols: ['u', 'u', 'u', 'u'],
64
64
  color: RNA_COLOR,
65
65
  },
@@ -1,36 +1,30 @@
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
+
5
+ import * as rxjs from 'rxjs';
4
6
  import {convertSequence, undefinedInputSequence, isValidSequence} from '../structures-works/sequence-codes-tools';
5
7
  import {map} from '../structures-works/map';
6
8
  import {MODIFICATIONS} from '../structures-works/const';
7
9
  import {sequenceToSmiles, sequenceToMolV3000} from '../structures-works/from-monomers';
8
10
  import $ from 'cash-dom';
9
11
  import {download} from '../helpers';
12
+ import {extractAtomDataV3000} from '../structures-works/mol-transformations';
13
+ import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
10
14
 
11
15
  const defaultInput = 'fAmCmGmAmCpsmU'; // todo: capitalize constants
12
16
  const sequenceWasCopied = 'Copied'; // todo: wrap hardcoded literals into constants
13
17
  const tooltipSequence = 'Copy sequence';
14
18
 
15
19
  export async function mainView(): Promise<HTMLDivElement> {
16
- const monomersLibAddress = 'System:AppData/SequenceTranslator/helmLib.json';
20
+ const onInput: rxjs.Subject<string> = new rxjs.Subject<string>();
21
+
17
22
  async function updateTableAndMolecule(sequence: string, inputFormat: string): Promise<void> {
18
23
  moleculeSvgDiv.innerHTML = '';
19
24
  outputTableDiv.innerHTML = '';
20
25
  const pi = DG.TaskBarProgressIndicator.create('Rendering table and molecule...');
21
26
  let errorsExist = false;
22
27
 
23
- // external helm-like monomers library
24
- const fileExists = await grok.dapi.files.exists(monomersLibAddress);
25
- if (!fileExists) {
26
- // todo: improve behaviour in this case
27
- grok.shell.warning('Please, provide the file with monomers library as System:AppData/SequenceTranslator/helmLib.json');
28
- pi.close();
29
- return;
30
- }
31
-
32
- const monomersLib = await grok.dapi.files.readAsText(monomersLibAddress);
33
-
34
28
  try {
35
29
  sequence = sequence.replace(/\s/g, '');
36
30
  const output = isValidSequence(sequence, null);
@@ -46,16 +40,16 @@ export async function mainView(): Promise<HTMLDivElement> {
46
40
  tableRows.push({
47
41
  'key': key,
48
42
  'value': ('indexOfFirstNotValidChar' in outputSequenceObj) ?
49
- ui.divH([
50
- ui.divText(sequence.slice(0, indexOfFirstNotValidChar), {style: {color: 'grey'}}),
51
- ui.tooltip.bind(
52
- ui.divText(sequence.slice(indexOfFirstNotValidChar), {style: {color: 'red'}}),
53
- 'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).synthesizer +
54
- '. See tables with valid codes on the right',
55
- ),
56
- ]) : //@ts-ignore
57
- ui.link(outputSequenceObj[key], () => navigator.clipboard.writeText(outputSequenceObj[key])
58
- .then(() => grok.shell.info(sequenceWasCopied)), tooltipSequence, ''),
43
+ ui.divH([
44
+ ui.divText(sequence.slice(0, indexOfFirstNotValidChar), {style: {color: 'grey'}}),
45
+ ui.tooltip.bind(
46
+ ui.divText(sequence.slice(indexOfFirstNotValidChar), {style: {color: 'red'}}),
47
+ 'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).synthesizer +
48
+ '. See tables with valid codes on the right',
49
+ ),
50
+ ]) : //@ts-ignore
51
+ ui.link(outputSequenceObj[key], () => navigator.clipboard.writeText(outputSequenceObj[key])
52
+ .then(() => grok.shell.info(sequenceWasCopied)), tooltipSequence, ''),
59
53
  });
60
54
  }
61
55
 
@@ -67,27 +61,71 @@ export async function mainView(): Promise<HTMLDivElement> {
67
61
  );
68
62
 
69
63
  if (outputSequenceObj.type != undefinedInputSequence && outputSequenceObj.Error != undefinedInputSequence) {
70
- const canvas = ui.canvas(300, 170);
71
- canvas.addEventListener('click', () => {
72
- const canv = ui.canvas($(window).width(), $(window).height());
73
- const mol = sequenceToMolV3000(
74
- inputSequenceField.value.replace(/\s/g, ''), false, true,
75
- output.synthesizer![0],
76
- );
77
- console.log(mol);
78
- // @ts-ignore
79
- OCL.StructureView.drawMolecule(canv, OCL.Molecule.fromMolfile(mol), {suppressChiralText: true});
80
- ui.dialog('Molecule: ' + inputSequenceField.value)
81
- .add(canv)
82
- .showModal(true);
64
+ const formCanvasWidth = 500;
65
+ const formCanvasHeight = 170;
66
+ const formCanvas = ui.canvas(
67
+ formCanvasWidth * window.devicePixelRatio, formCanvasHeight * window.devicePixelRatio);
68
+ formCanvas.style.width = `${formCanvasWidth}px`;
69
+ formCanvas.style.height = `${formCanvasHeight}px`;
70
+
71
+ formCanvas.addEventListener('click', async () => {
72
+ try {
73
+ const mol = sequenceToMolV3000(
74
+ inputSequenceField.value.replace(/\s/g, ''), false, true,
75
+ output.synthesizer![0],
76
+ );
77
+ console.log(mol);
78
+
79
+ const addDiv = ui.div([], {style: {overflowX: 'scroll'}});
80
+
81
+ // addDiv size required, but now available before dialog show()
82
+ const coordinates = extractAtomDataV3000(mol);
83
+ const cw: number = $(window).width() * 0.80; // addDiv.clientWidth
84
+ const ch: number = $(window).height() * 0.70; // addDiv.clientHeight
85
+ const molWidth: number = Math.max(...coordinates.x) - Math.min(...coordinates.x);
86
+ const molHeight: number = Math.max(...coordinates.y) - Math.min(...coordinates.y);
87
+
88
+ const wR: number = cw / molWidth;
89
+ const hR: number = ch / molHeight;
90
+ const r: number = hR; // Math.max(wR, hR);
91
+ const dlgCanvasWidth = r * molWidth;
92
+ const dlgCanvasHeight = r * molHeight;
93
+
94
+ const dlgCanvas = ui.canvas(dlgCanvasWidth * window.devicePixelRatio, dlgCanvasHeight * window.devicePixelRatio);
95
+ dlgCanvas.style.width = `${dlgCanvasWidth}px`;
96
+ dlgCanvas.style.height = `${dlgCanvasHeight}px`;
97
+
98
+ // // @ts-ignore
99
+ // OCL.StructureView.drawMolecule(dlgCanvas, OCL.Molecule.fromMolfile(mol), {suppressChiralText: true});
100
+ // await grok.chem.canvasMol(0, 0, dlgCanvas.width, dlgCanvas.height, dlgCanvas, mol, null,
101
+ // {setNewCoords: false, normalizeDepiction: false, straightenDepiction: false});
102
+ await grok.functions.call('Chem:canvasMol', {
103
+ x: 0, y: 0, w: dlgCanvas.width, h: dlgCanvas.height, canvas: dlgCanvas,
104
+ molString: mol, scaffoldMolString: '',
105
+ options: {setNewCoords: false, normalizeDepiction: false, straightenDepiction: false}
106
+ });
107
+
108
+ addDiv.appendChild(dlgCanvas);
109
+ ui.dialog('Molecule: ' + inputSequenceField.value)
110
+ .add(addDiv)
111
+ .showModal(true);
112
+ } catch (err) {
113
+ const errStr = errorToConsole(err);
114
+ console.error(errStr);
115
+ }
83
116
  });
84
- $(canvas).on('mouseover', () => $(canvas).css('cursor', 'zoom-in'));
85
- $(canvas).on('mouseout', () => $(canvas).css('cursor', 'default'));
117
+ $(formCanvas).on('mouseover', () => $(formCanvas).css('cursor', 'zoom-in'));
118
+ $(formCanvas).on('mouseout', () => $(formCanvas).css('cursor', 'default'));
86
119
  const mol = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, true,
87
120
  output.synthesizer![0]);
88
- // @ts-ignore
89
- OCL.StructureView.drawMolecule(canvas, OCL.Molecule.fromMolfile(mol), {suppressChiralText: true});
90
- moleculeSvgDiv.append(canvas);
121
+ // // @ts-ignore
122
+ // OCL.StructureView.drawMolecule(formCanvas, OCL.Molecule.fromMolfile(mol), {suppressChiralText: true});
123
+ await grok.functions.call('Chem:canvasMol', {
124
+ x: 0, y: 0, w: formCanvas.width, h: formCanvas.height, canvas: formCanvas,
125
+ molString: mol, scaffoldMolString: '',
126
+ options: {setNewCoords: false, normalizeDepiction: false, straightenDepiction: false}
127
+ });
128
+ moleculeSvgDiv.append(formCanvas);
91
129
  } else
92
130
  moleculeSvgDiv.innerHTML = '';
93
131
  } finally {
@@ -102,6 +140,11 @@ export async function mainView(): Promise<HTMLDivElement> {
102
140
  const moleculeSvgDiv = ui.block([]);
103
141
  const outputTableDiv = ui.div([]);
104
142
  const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => {
143
+ // Send event to DG.debounce()
144
+ onInput.next(sequence);
145
+ });
146
+
147
+ DG.debounce<string>(onInput, 300).subscribe((sequence) => {
105
148
  updateTableAndMolecule(sequence, inputFormatChoiceInput.value!);
106
149
  });
107
150
 
@@ -139,9 +182,9 @@ export async function mainView(): Promise<HTMLDivElement> {
139
182
  );
140
183
 
141
184
  const overhangModificationsGrid = DG.Viewer.grid(
142
- DG.DataFrame.fromColumns([
143
- DG.Column.fromStrings('Name', Object.keys(MODIFICATIONS)),
144
- ])!, {showRowHeader: false, showCellTooltip: false, allowEdit: false},
185
+ DG.DataFrame.fromColumns([
186
+ DG.Column.fromStrings('Name', Object.keys(MODIFICATIONS)),
187
+ ])!, {showRowHeader: false, showCellTooltip: false, allowEdit: false},
145
188
  );
146
189
  updateTableAndMolecule(defaultInput, inputFormatChoiceInput.value!);
147
190
 
@@ -171,7 +214,6 @@ export async function mainView(): Promise<HTMLDivElement> {
171
214
 
172
215
  const downloadMolFileIcon = ui.iconFA('download', async () => {
173
216
  const clearSequence = inputSequenceField.value.replace(/\s/g, '');
174
- const monomersLib = await grok.dapi.files.readAsText(monomersLibAddress);
175
217
  const result = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, false,
176
218
  inputFormatChoiceInput.value!);
177
219
  download(clearSequence + '.mol', encodeURIComponent(result));
@@ -203,9 +245,8 @@ export async function mainView(): Promise<HTMLDivElement> {
203
245
  appMainDescription,
204
246
  ui.div([
205
247
  ui.h1('Input sequence'),
206
- ui.div([
207
- inputSequenceField.root,
208
- ], 'input-base'),
248
+ ui.div([], 'input-base'),
249
+ inputSequenceField.root,
209
250
  ], 'inputSequence'),
210
251
  ui.div([inputFormatChoiceInput], {style: {padding: '5px 0'}}),
211
252
  ui.block([
package/src/package.ts CHANGED
@@ -16,11 +16,11 @@ export let monomerWorks: MonomerWorks | null = null;
16
16
 
17
17
  export function getMonomerWorks() {
18
18
  return monomerWorks;
19
- };
19
+ }
20
20
 
21
21
  export function getMonomerLib() {
22
22
  return monomerLib;
23
- };
23
+ }
24
24
 
25
25
  //name: Sequence Translator
26
26
  //tags: app
@@ -1,18 +1,5 @@
1
- export const MODIFICATIONS: {[index: string]: {molecularWeight: number, left: string, right: string}} = {
2
- '(invabasic)': {
3
- molecularWeight: 118.13,
4
- left: 'O[C@@H]1C[C@@H]O[C@H]1CO',
5
- right: 'O[C@@H]1C[C@@H]O[C@H]1CO',
6
- },
7
- '(GalNAc-2-JNJ)': {
8
- molecularWeight: 1273.3,
9
- left: 'C(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)' +
10
- '(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)' +
11
- '(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)NC(=O)CCCC(=O)NCC(O)CO',
12
- right: 'OCC(O)CNC(=O)CCCC(=O)NC(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)' +
13
- '(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)'+
14
- '(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)',
15
- },
16
- };
1
+ import * as map from './map';
2
+
3
+ export const MODIFICATIONS = map.MODIFICATIONS;
17
4
 
18
5
  export const standardPhosphateLinkSmiles = 'OP(=O)(O)O';
@@ -1,33 +1,35 @@
1
- import {lcmsToGcrs} from './map';
1
+ import {lcmsToGcrs, MODIFICATIONS} from './map';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
  import {DELIMITER} from './map';
4
+ import {sortByStringLengthInDescendingOrder} from '../helpers';
4
5
  //name: gcrsToLcms
5
6
  //input: string nucleotides {semType: GCRS}
6
7
  //output: string result {semType: LCMS}
7
8
  export function gcrsToLcms(sequence: string): string {
8
- const df = DG.DataFrame.fromCsv(lcmsToGcrs);
9
- const arr1 = df.getCol('GCRS').toList();
10
- const arr2 = df.getCol('LCMS').toList();
11
- const obj: {[i: string]: string} = {};
12
- arr1.forEach((element, index) => obj[element] = arr2[index]);
13
- obj[DELIMITER] = DELIMITER;
14
- // for (let i = 0; i < arr1.length; i++) {
15
- // arr1[i] = arr1[i].replace('(', '\\(');
16
- // arr1[i] = arr1[i].replace(')', '\\)');
17
- // }
18
- // const regExp = new RegExp('(' + arr1.join('|') + ')', 'g');
19
- // let r1 = sequence.replace(regExp, function(code) {return obj[code];});
20
- const codes = arr1.concat(DELIMITER).sort(function(a, b) {return b.length - a.length;});
21
- let i = 0;
22
- let r1 = '';
23
- while (i < sequence.length) {
24
- const matchedCode = codes.find((c) => c == sequence.slice(i, i + c.length));
25
- r1 += obj[sequence.slice(i, i + matchedCode.length)];
26
- i += matchedCode.length;
9
+ try {
10
+ const df = DG.DataFrame.fromCsv(lcmsToGcrs);
11
+ const arr1: string[] = df.getCol('GCRS').toList();
12
+ const arr2: string[] = df.getCol('LCMS').toList();
13
+ const obj: { [i: string]: string } = {};
14
+ arr1.forEach((element, index) => obj[element] = arr2[index]);
15
+ obj[DELIMITER] = DELIMITER;
16
+ const codes = arr1
17
+ .concat(DELIMITER)
18
+ .concat(Object.keys(MODIFICATIONS));
19
+ const sortedCodes = sortByStringLengthInDescendingOrder(codes);
20
+ let i = 0;
21
+ let r1 = '';
22
+ while (i < sequence.length) {
23
+ const matchedCode = sortedCodes.find((c) => c == sequence.slice(i, i + c.length))!;
24
+ r1 += obj[sequence.slice(i, i + matchedCode.length)];
25
+ i += matchedCode.length;
26
+ }
27
+ while (r1.indexOf('//') != -1)
28
+ r1 = r1.replace('//', '/');
29
+ return r1;
30
+ } catch {
31
+ return '<error>';
27
32
  }
28
- while (r1.indexOf('//') != -1)
29
- r1 = r1.replace('//', '/');
30
- return r1;
31
33
  }
32
34
 
33
35
  //name: asoGapmersNucleotidesToBioSpring
@@ -35,9 +37,9 @@ export function gcrsToLcms(sequence: string): string {
35
37
  //output: string result {semType: BioSpring / Gapmers}
36
38
  export function asoGapmersNucleotidesToBioSpring(nucleotides: string): string {
37
39
  let count: number = -1;
38
- const objForEdges: {[index: string]: string} = {
40
+ const objForEdges: { [index: string]: string } = {
39
41
  '(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'T': '5*', 'A': '6*', 'C': '7*', 'G': '8*'};
40
- const objForCenter: {[index: string]: string} = {
42
+ const objForCenter: { [index: string]: string } = {
41
43
  '(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'T': 'T*', 'A': 'A*', 'C': '9*', 'G': 'G*'};
42
44
  return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|T|C|G)/g, function(x: string) {
43
45
  count++;
@@ -51,7 +53,7 @@ export function asoGapmersNucleotidesToBioSpring(nucleotides: string): string {
51
53
  //output: string result {semType: GCRS / Gapmers}
52
54
  export function asoGapmersNucleotidesToGcrs(nucleotides: string): string {
53
55
  let count: number = -1;
54
- const objForEdges: {[index: string]: string} = {
56
+ const objForEdges: { [index: string]: string } = {
55
57
  '(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'T': 'moeUnps',
56
58
  'A': 'moeAnps', 'C': 'moe5mCnps', 'G': 'moeGnps'};
57
59
  const objForCenter: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',