@datagrok/helm 2.5.5 → 2.5.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.5.5",
4
+ "version": "2.5.6",
5
5
  "author": {
6
6
  "name": "Aleksandr Tanas",
7
7
  "email": "atanas@datagrok.ai"
@@ -16,7 +16,7 @@
16
16
  "css/helm.css"
17
17
  ],
18
18
  "dependencies": {
19
- "@datagrok-libraries/bio": "^5.45.0",
19
+ "@datagrok-libraries/bio": "^5.45.4",
20
20
  "@datagrok-libraries/chem-meta": "^1.2.7",
21
21
  "@datagrok-libraries/utils": "^4.3.6",
22
22
  "cash-dom": "^8.1.1",
@@ -29,7 +29,7 @@
29
29
  "devDependencies": {
30
30
  "@datagrok-libraries/helm-web-editor": "^1.1.12",
31
31
  "@datagrok-libraries/js-draw-lite": "^0.0.9",
32
- "@datagrok/bio": "^2.16.0",
32
+ "@datagrok/bio": "^2.16.6",
33
33
  "@datagrok/chem": "^1.12.3",
34
34
  "@types/node": "17.0.45",
35
35
  "@types/webpack-env": "^1.18.5",
@@ -79,4 +79,4 @@
79
79
  "directory": "packages/Helm"
80
80
  },
81
81
  "category": "Bioinformatics"
82
- }
82
+ }
@@ -0,0 +1,13 @@
1
+ import * as grokNamespace from 'datagrok-api/grok';
2
+ import * as uiNamespace from 'datagrok-api/ui';
3
+ import * as DGNamespace from 'datagrok-api/dg';
4
+ import * as rxjsNamespace from 'rxjs';
5
+ import $Namespace from 'cash-dom';
6
+
7
+ declare global {
8
+ const grok: typeof grokNamespace;
9
+ const ui: typeof uiNamespace;
10
+ const DG: typeof DGNamespace;
11
+ const rjxs: typeof rxjsNamespace;
12
+ const $: typeof $Namespace;
13
+ }
@@ -14,7 +14,6 @@ import './tests/helm-service-tests';
14
14
  import './tests/renderers-tests';
15
15
  import './tests/get-molfiles-tests';
16
16
  import './tests/properties-widget-tests';
17
- import './tests/get-all-parts-tests';
18
17
  import './tests/get-monomer-tests';
19
18
  import './tests/parse-helm-tests';
20
19
  import './tests/helm-web-editor-tests';
@@ -59,6 +59,7 @@ export async function initHelmLoadAndPatchDojo(): Promise<void> {
59
59
  try {
60
60
  const requireBackup = window.require;
61
61
 
62
+ // Dojo modules required by JDraw2 and HELMWebEditor
62
63
  // 'dojo.window','dojo.io.script','dojo.io.iframe','dojo.dom',
63
64
  // 'dojox.gfx','dojox.gfx.svg','dojox.gfx.shape','dojox.charting'
64
65
  const dojoTargetList: { name: string, checker: () => boolean }[] = [
@@ -6,6 +6,9 @@ import * as DG from 'datagrok-api/dg';
6
6
  import {after, before, category, delay, expect, expectArray, test, testEvent} from '@datagrok-libraries/utils/src/test';
7
7
  import {HelmNotSupportedError, HelmNotSupportedErrorType, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
8
8
  import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
9
+ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
10
+ import {getUserLibSettings, setUserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
11
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
9
12
  /* eslint-enable max-len */
10
13
 
11
14
  import {_package} from '../package-test';
@@ -15,9 +18,21 @@ type TestTgtType = { helm: string | null, map: [number, number][], errType?: str
15
18
 
16
19
  category('HelmHelper: removeGaps', () => {
17
20
  let helmHelper: IHelmHelper;
21
+ let libHelper: IMonomerLibHelper;
22
+ let userLibSettings: UserLibSettings;
18
23
 
19
24
  before(async () => {
20
25
  helmHelper = await getHelmHelper();
26
+ libHelper = await getMonomerLibHelper();
27
+
28
+ userLibSettings = await getUserLibSettings();
29
+ // Cysteine has different R-groups in other libraries
30
+ await libHelper.loadMonomerLibForTests();
31
+ });
32
+
33
+ after(async () => {
34
+ await setUserLibSettings(userLibSettings);
35
+ await libHelper.loadMonomerLib(true);
21
36
  });
22
37
 
23
38
  const tests: { [testName: string]: { src: TestSrcType, tgt: TestTgtType } } = {
@@ -10,6 +10,7 @@ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
10
10
  import {
11
11
  getUserLibSettings, setUserLibSettings
12
12
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
13
+ import {IHelmHelper, getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
13
14
 
14
15
  import {JSDraw2Module} from '../types';
15
16
  import {initHelmMainPackage} from './utils';
@@ -37,10 +38,28 @@ category('parseHelm', () => {
37
38
  },
38
39
  'RNA': {
39
40
  src: 'RNA1{[dhp]([m1A])p.r(T)p.r(T)p.r(G)p}$$$$V2.0',
40
- tgt: {atomCount: 12, bondCount: 11, helm: 'RNA1{[dhp]([m1A])p.r(T)p.r(T)p.r(G)p}$$$$V2.0',}
41
- }
41
+ tgt: {
42
+ atomCount: 12, bondCount: 11,
43
+ helm: 'RNA1{[dhp]([m1A])p.r(T)p.r(T)p.r(G)p}$$$$V2.0',
44
+ }
45
+ },
46
+ 'PT-with-gap': {
47
+ src: 'PEPTIDE1{[meY].*.C.R.N.P.C.T}$$$$V2.0',
48
+ tgt: {
49
+ atomCount: 8, bondCount: 7,
50
+ helm: 'PEPTIDE1{[meY].*.C.R.N.P.C.T}$$$$V2.0',
51
+ }
52
+ },
53
+ 'PT-with-gap-at-connection': {
54
+ src: 'PEPTIDE1{[meY].*.C.R.N.P.C.T}$PEPTIDE1,PEPTIDE1,2:R3-7:R3$$$V2.0',
55
+ tgt: {
56
+ atomCount: 8, bondCount: 8,
57
+ helm: 'PEPTIDE1{[meY].*.C.R.N.P.C.T}$PEPTIDE1,PEPTIDE1,2:R3-7:R3$$$V2.0',
58
+ }
59
+ },
42
60
  };
43
61
 
62
+ let helmHelper: IHelmHelper;
44
63
  let libHelper: IMonomerLibHelper;
45
64
  /** Backup actual user's monomer libraries settings */
46
65
  let userLibSettings: UserLibSettings;
@@ -48,8 +67,9 @@ category('parseHelm', () => {
48
67
  before(async () => {
49
68
  await initHelmMainPackage();
50
69
 
51
- libHelper = await getMonomerLibHelper();
70
+ helmHelper = await getHelmHelper();
52
71
 
72
+ libHelper = await getMonomerLibHelper();
53
73
  userLibSettings = await getUserLibSettings();
54
74
 
55
75
  // parseHelm is dependent on monomers RGroups available, test requires default monomer library
@@ -67,6 +87,12 @@ category('parseHelm', () => {
67
87
  });
68
88
  }
69
89
 
90
+ for (const [testName, {src, tgt}] of Object.entries(testData)) {
91
+ test(`HelmHelper-${testName}`, async () => {
92
+ _testParseHelmWithHelmHelper(src, tgt, helmHelper);
93
+ });
94
+ }
95
+
70
96
  for (const [testName, {src, tgt}] of Object.entries(testData)) {
71
97
  test(`woDOM-${testName}`, async () => {
72
98
  _testParseHelmWithoutDOM(src, tgt);
@@ -89,6 +115,20 @@ function _testParseHelmWithEditor(src: string, tgt: TestTgtType): void {
89
115
  expect(m.bonds.length, tgt.bondCount);
90
116
  }
91
117
 
118
+ function _testParseHelmWithHelmHelper(src: string, tgt: TestTgtType, helmHelper: IHelmHelper): void {
119
+ const io = org.helm.webeditor.IO;
120
+
121
+ const origin = new JSDraw2.Point(0, 0);
122
+ const resMol = helmHelper.parse(src, origin);
123
+
124
+ const resHelm = io.getHelm(resMol);
125
+ expect(resMol.atoms.length, tgt.atomCount);
126
+ expect(resMol.bonds.length, tgt.bondCount);
127
+ expect(resHelm, tgt.helm);
128
+ expect(resMol.atoms.every((a) => !a.elem.startsWith('[') && !a.elem.endsWith(']')), true,
129
+ 'Atoms should not contain square braces.');
130
+ }
131
+
92
132
  function _testParseHelmWithoutDOM(src: string, tgt: TestTgtType): void {
93
133
  const io = org.helm.webeditor.IO;
94
134
 
@@ -103,5 +143,6 @@ function _testParseHelmWithoutDOM(src: string, tgt: TestTgtType): void {
103
143
  expect(m.atoms.length, tgt.atomCount);
104
144
  expect(m.bonds.length, tgt.bondCount);
105
145
  expect(resHelm, tgt.helm);
106
- expect(m.atoms.every((a) => !a.elem.startsWith('[') && !a.elem.endsWith(']')), true, 'Atoms should not contain square braces.');
146
+ expect(m.atoms.every((a) => !a.elem.startsWith('[') && !a.elem.endsWith(']')), true,
147
+ 'Atoms should not contain square braces.');
107
148
  }
@@ -9,8 +9,6 @@ import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/m
9
9
  import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
10
10
  import {GAP_SYMBOL, GapOriginals, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
11
11
 
12
- import {HelmMonomerPlacer} from '../helm-monomer-placer';
13
-
14
12
  export function getHoveredMonomerFromEditorMol(
15
13
  argsX: number, argsY: number, mol: HelmMol, cellHeight?: number
16
14
  ): HelmAtom | null {
@@ -49,41 +47,6 @@ export function getHoveredMonomerFromEditorMol(
49
47
  return resAtom;
50
48
  }
51
49
 
52
- export function getHoveredMonomerFallback(
53
- argsX: number, _argsY: number, gridCell: DG.GridCell, helmPlacer: HelmMonomerPlacer
54
- ): ISeqMonomer | null {
55
- let hoveredSeqMonomer: ISeqMonomer | null = null;
56
- const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
57
- const maxIndex = Object.values(lengths).length - 1;
58
- let left = 0;
59
- let right = maxIndex;
60
- let found = false;
61
- let iterCount: number = 0;
62
-
63
- let mid = 0;
64
- if (argsX > sumLengths[0]) {
65
- while (!found && iterCount < sumLengths.length) {
66
- mid = Math.floor((right + left) / 2);
67
- if (argsX >= sumLengths[mid] && argsX <= sumLengths[mid + 1]) {
68
- left = mid;
69
- found = true;
70
- } else if (argsX < sumLengths[mid])
71
- right = mid - 1;
72
- else if (argsX > sumLengths[mid + 1])
73
- left = mid + 1;
74
-
75
- if (left == right)
76
- found = true;
77
-
78
- iterCount++;
79
- }
80
- }
81
- left = (argsX >= sumLengths[left]) ? left : left - 1; // correct left to between sumLengths
82
- if (left >= 0)
83
- hoveredSeqMonomer = getSeqMonomerFromHelm(left, allParts[left], allParts[0]);
84
- return hoveredSeqMonomer;
85
- }
86
-
87
50
  export function getSeqMonomerFromHelmAtom(atom: HelmAtom): ISeqMonomer {
88
51
  const canonicalSymbol = atom.elem === GapOriginals[NOTATION.HELM] ? GAP_SYMBOL : atom.elem;
89
52
  return {position: parseInt(atom.bio!.continuousId as string) - 1, symbol: canonicalSymbol, biotype: atom.bio!.type};
@@ -94,48 +94,62 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
94
94
  protected override renderCellImageData(
95
95
  gridCtx: CanvasRenderingContext2D, gridCellBounds: DG.Rect, gridCell: DG.GridCell, cellImageData: ImageData,
96
96
  ): boolean {
97
+ // super.renderCellImageData(gridCtx, gridCellBounds, gridCell, cellImageData);
98
+ // return true;
99
+
100
+ const gcb = gridCellBounds;
97
101
  const dpr = window.devicePixelRatio;
98
102
  if (gridCell.tableRowIndex === null) return false;
99
103
  const aux = this._auxList[gridCell.tableRowIndex];
100
104
  if (!aux) return true;
101
105
 
106
+ const [cellWidth, cellHeight] = [gcb.width * dpr - 2, gcb.height * dpr - 2];
107
+ const cellDScale = Math.min(0.95 * cellWidth / aux.dBox.width, 0.95 * cellHeight / aux.dBox.height);
108
+ const [cellDWidth, cellDHeight] = [cellDScale * aux.dBox.width, cellDScale * aux.dBox.height];
109
+ const cellDBox = new DG.Rect((cellWidth - cellDWidth) / 2, (cellHeight - cellDHeight) / 2, cellDWidth, cellDHeight);
110
+
111
+
102
112
  // Draw cell image data to scale it with drawImage() while transform()
103
113
  const cellCanvas = ui.canvas(cellImageData.width, cellImageData.height);
104
114
  const cellCtx = cellCanvas.getContext('2d')!;
105
115
  cellCtx.putImageData(cellImageData, 0, 0);
106
116
 
107
- // Get bbox canvas
108
- const bBoxImageData = cellCtx.getImageData(aux.bBox.x, aux.bBox.y, aux.bBox.width, aux.bBox.height);
109
- const bBoxCanvas = ui.canvas(aux.bBox.width, aux.bBox.height);
110
- const bBoxCtx = bBoxCanvas.getContext('2d')!;
111
- bBoxCtx.putImageData(bBoxImageData, 0, 0);
112
-
117
+ // // Get bbox canvas
118
+ // const bBoxImageData = cellCtx.getImageData(aux.bBox.x, aux.bBox.y, aux.bBox.width, aux.bBox.height);
119
+ // const bBoxCanvas = ui.canvas(aux.bBox.width, aux.bBox.height);
120
+ // const bBoxCtx = bBoxCanvas.getContext('2d')!;
121
+ // bBoxCtx.putImageData(bBoxImageData, 0, 0);
122
+ //
113
123
  const fitCanvasWidth = gridCellBounds.width * dpr - 2;
114
124
  const fitCanvasHeight = gridCellBounds.height * dpr - 2;
115
-
116
- const bBoxRatio = Math.max(aux.bBox.width / aux.cBox.width, aux.bBox.height / aux.cBox.height);
117
- const bBoxFullWidth = aux.bBox.width / bBoxRatio;
118
- const bBoxFullHeight = aux.bBox.height / bBoxRatio;
119
-
120
- const fitScale = Math.min(fitCanvasWidth / bBoxFullWidth, fitCanvasHeight / bBoxFullHeight);
121
-
122
- // Relative shift of bbox center to cbox center
123
- const bBoxShiftHR = (aux.bBox.left + aux.bBox.width / 2 - aux.cBox.width / 2) / aux.cBox.width;
124
- const bBoxShiftVR = (aux.bBox.top + aux.bBox.height / 2 - aux.cBox.height / 2) / aux.cBox.height;
125
-
126
- const bBoxFitLeft = fitCanvasWidth / 2 - bBoxCanvas.width * fitScale * (1 - 2 * bBoxShiftHR) / 2;
127
- const bBoxFitTop = fitCanvasHeight / 2 - bBoxCanvas.height * fitScale * (1 - 2 * bBoxShiftVR) / 2;
128
-
125
+ //
126
+ // const bBoxRatio = Math.max(aux.bBox.width / aux.cBox.width, aux.bBox.height / aux.cBox.height);
127
+ // const bBoxFullWidth = aux.bBox.width / bBoxRatio;
128
+ // const bBoxFullHeight = aux.bBox.height / bBoxRatio;
129
+ //
130
+ // const fitScale = Math.min(fitCanvasWidth / bBoxFullWidth, fitCanvasHeight / bBoxFullHeight);
131
+ //
132
+ // // Relative shift of bbox center to cbox center
133
+ // const bBoxShiftHR = (aux.bBox.left + aux.bBox.width / 2 - aux.cBox.width / 2) / aux.cBox.width;
134
+ // const bBoxShiftVR = (aux.bBox.top + aux.bBox.height / 2 - aux.cBox.height / 2) / aux.cBox.height;
135
+ //
136
+ // const bBoxFitLeft = fitCanvasWidth / 2 - bBoxCanvas.width * fitScale * (1 - 2 * bBoxShiftHR) / 2;
137
+ // const bBoxFitTop = fitCanvasHeight / 2 - bBoxCanvas.height * fitScale * (1 - 2 * bBoxShiftVR) / 2;
138
+ //
129
139
  const fitCanvas = ui.canvas(fitCanvasWidth, fitCanvasHeight);
130
140
  const fitCtx = fitCanvas.getContext('2d')!;
131
141
  // fitCtx.fillStyle = '#FFFFA0';
132
142
  // fitCtx.fillRect(0, 0, fitCanvasWidth, fitCanvasHeight);
133
- fitCtx.transform(fitScale, 0, 0, fitScale, bBoxFitLeft, bBoxFitTop);
134
- fitCtx.drawImage(bBoxCanvas, 0, 0); // draw with scale transform
143
+ // fitCtx.transform(fitScale, 0, 0, fitScale, bBoxFitLeft, bBoxFitTop);
144
+ // fitCtx.drawImage(bBoxCanvas, 0, 0); // draw with scale transform
145
+ fitCtx.drawImage(cellCanvas,
146
+ aux.dBox.x, aux.dBox.y, aux.dBox.width, aux.dBox.height,
147
+ cellDBox.x, cellDBox.y, cellDBox.width, cellDBox.height);
135
148
 
136
149
  const fitCanvasData = fitCtx.getImageData(0, 0, fitCanvasWidth, fitCanvasHeight);
137
150
  this.renderOnGrid(gridCtx, gridCellBounds, gridCell, fitCanvasData);
138
- return true; // request rendering
151
+
152
+ return aux.cBox.width != cellWidth || aux.cBox.height != cellHeight; // request rendering
139
153
  }
140
154
 
141
155
  onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
@@ -147,15 +161,18 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
147
161
  const dpr = window.devicePixelRatio;
148
162
 
149
163
  /** {@link gridCell}.bounds */ const gcb = gridCell.bounds;
150
- const argsX = (e.offsetX - gcb.x) * dpr;
151
- const argsY = (e.offsetY - gcb.y) * dpr;
164
+ const cX = (e.offsetX - gcb.x) * dpr;
165
+ const cY = (e.offsetY - gcb.y) * dpr;
166
+
167
+ const bX = aux.bBox.x + (cX - aux.dBox.x) * aux.bBox.width / aux.dBox.width;
168
+ const bY = aux.bBox.y + (cY - aux.dBox.y) * aux.bBox.height / aux.dBox.height;
152
169
 
153
- const editorMol: Mol<HelmType> | null = aux.mol;
170
+ const editorMol: Mol<HelmType> | null = aux.mol; // in bBox world
154
171
  if (!editorMol) {
155
172
  this.logger.warning(`${logPrefix}, editorMol of the cell not found.`);
156
173
  return; // The gridCell is not rendered yet
157
174
  }
158
- const hoveredAtom = getHoveredMonomerFromEditorMol(argsX, argsY, editorMol, gridCell.bounds.height);
175
+ const hoveredAtom = getHoveredMonomerFromEditorMol(bX, bY, editorMol, gridCell.bounds.height);
159
176
 
160
177
  let seqMonomer: ISeqMonomer | null = null;
161
178
  if (hoveredAtom) {
@@ -1,4 +1,3 @@
1
- import * as grok from 'datagrok-api/grok';
2
1
  import * as ui from 'datagrok-api/ui';
3
2
  import * as DG from 'datagrok-api/dg';
4
3
 
@@ -89,15 +88,19 @@ export class HelmService extends HelmServiceBase {
89
88
  if (!helmStr)
90
89
  editor.reset();
91
90
 
92
- const bBox = (editor.div.children[0] as SVGSVGElement).getBBox();
91
+ const svgEl = editor.div.children[0] as SVGSVGElement;
92
+ const bBox = svgEl.getBBox();
93
+ const [cellWidth, cellHeight] = [task.props.width, task.props.height];
94
+ const bScale = Math.min(cellWidth * 0.95 / bBox.width, cellHeight * 0.95 / bBox.height);
95
+ const [drawWidth, drawHeight] = [bBox.width * bScale, bBox.height * bScale];
93
96
  const aux: HelmAux = {
94
97
  mol: editor.m.clone(false),
95
98
  bBox: new DG.Rect(bBox.x, bBox.y, bBox.width + 2, bBox.height + 2) /* adjust for clipping right/bottom */,
99
+ dBox: new DG.Rect((cellWidth - drawWidth) / 2, (cellHeight - drawHeight) / 2, drawWidth, drawHeight),
96
100
  cBox: new DG.Rect(0, 0, task.props.width, task.props.height),
97
101
  };
98
102
  const lET = window.performance.now();
99
103
 
100
- const svgEl = $(this.hostDiv).find('svg').get(0) as unknown as SVGSVGElement;
101
104
  const dpr = window.devicePixelRatio;
102
105
 
103
106
  const rST = window.performance.now();
@@ -135,7 +138,9 @@ export class HelmService extends HelmServiceBase {
135
138
  if (!this.image || !g) return false;
136
139
  // g.fillStyle = '#C0C0FF';
137
140
  // g.fillRect(0, 0, canvas.width, canvas.height);
138
- g.drawImage(this.image, 0, 0);
141
+ g.drawImage(this.image,
142
+ aux.bBox.x, aux.bBox.y, aux.bBox.width, aux.bBox.height,
143
+ aux.dBox.x, aux.dBox.y, aux.dBox.width, aux.dBox.height);
139
144
  task.onAfterRender(canvas, aux);
140
145
  } finally {
141
146
  canvas.remove();
@@ -1,98 +0,0 @@
1
- import * as grok from 'datagrok-api/grok';
2
- import * as ui from 'datagrok-api/ui';
3
- import * as DG from 'datagrok-api/dg';
4
-
5
- import wu from 'wu';
6
-
7
- import {HelmType, Mol, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
8
-
9
- import {CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
10
-
11
- import {getParts, parseHelm} from './utils';
12
-
13
- import {_package} from './package';
14
-
15
- export class HelmMonomerPlacer extends CellRendererBackBase<string> {
16
- private _allPartsList: (string[] | null)[];
17
- private _lengthsList: (number[] | null)[];
18
- private _editorMolList: (Mol<HelmType> | null)[];
19
-
20
- public monomerCharWidth: number = 7;
21
- public leftPadding: number = 5;
22
- public monomerTextSizeMap: { [p: string]: TextMetrics } = {};
23
-
24
- public constructor(
25
- gridCol: DG.GridColumn | null,
26
- tableCol: DG.Column<string>
27
- ) {
28
- super(gridCol, tableCol, _package.logger);
29
- }
30
-
31
- render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
32
- gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
33
- ) {
34
- throw new Error('Not implemented');
35
- }
36
-
37
- protected override reset(): void {
38
- this._allPartsList = new Array<string[] | null>(this.tableCol.length).fill(null);
39
- this._lengthsList = new Array<number[] | null>(this.tableCol.length).fill(null);
40
- this._editorMolList = new Array<Mol<HelmType> | null>(this.tableCol.length).fill(null);
41
- }
42
-
43
- /** Skips cell for the fallback rendering */
44
- public skipCell(rowIdx: number): void {
45
- this._allPartsList[rowIdx] = [];
46
- this._lengthsList[rowIdx] = [];
47
- }
48
-
49
- /** @param rowIdx Row index of the table {@link DG.DataFrame}, HelmMonomerPlacer is {@link DG.Column} based */
50
- public getCellAllPartsLengths(rowIdx: number): [string[], number[], number[]] {
51
- const [allParts, lengths] = this.getCellMonomerLengthsForSeq(rowIdx);
52
-
53
- const sumLengths: number[] = new Array<number>(lengths.length + 1);
54
- sumLengths[0] = this.leftPadding; // padding
55
- for (let pos: number = 1; pos < sumLengths.length; pos++)
56
- sumLengths[pos] = sumLengths[pos - 1] + lengths[pos - 1];
57
- return [allParts, lengths, sumLengths];
58
- }
59
-
60
- private getCellMonomerLengthsForSeq(rowIdx: number): [string[], number[]] {
61
- let allParts: string[] | null = this._allPartsList![rowIdx];
62
- if (allParts === null) {
63
- const seq = this.tableCol.get(rowIdx);
64
- allParts = this._allPartsList![rowIdx] = getAllParts(seq);
65
- }
66
-
67
- let lengths: number[] | null = this._lengthsList![rowIdx];
68
- if (lengths === null) {
69
- lengths = this._lengthsList![rowIdx] = new Array<number>(allParts.length);
70
- for (const [part, partI] of wu.enumerate(allParts)) {
71
- const partWidth: number = part.length * this.monomerCharWidth;
72
- lengths[partI] = partWidth;
73
- }
74
- }
75
-
76
- return [allParts, lengths];
77
- }
78
-
79
- // -- Handle events --
80
-
81
- private monomerLibOnChanged(_value: any): void {
82
- this.dirty = true;
83
- this.invalidateGrid();
84
- }
85
-
86
- public setEditorMol(tableRowIndex: number, editorMol: Mol<HelmType>) {
87
- this._editorMolList![tableRowIndex] = editorMol.clone(false);
88
- }
89
-
90
- public getEditorMol(tableRowIndex: number): Mol<HelmType> | null {
91
- return this._editorMolList![tableRowIndex];
92
- }
93
- }
94
-
95
- export function getAllParts(seq: string | null): string[] {
96
- const monomerList: string[] = !!seq ? parseHelm(seq) : [];
97
- return !!seq ? getParts(monomerList, seq) : [];
98
- }
@@ -1,39 +0,0 @@
1
- import * as grok from 'datagrok-api/grok';
2
- import * as ui from 'datagrok-api/ui';
3
- import * as DG from 'datagrok-api/dg';
4
-
5
- import {after, before, category, delay, expect, test, expectArray} from '@datagrok-libraries/utils/src/test';
6
-
7
- import {getAllParts} from '../helm-monomer-placer';
8
- import {initHelmMainPackage} from './utils';
9
-
10
- category('getAllParts', () => {
11
- /** All parts of Helm string are required for fallback rendering. */
12
-
13
- const tests: { [testName: string]: { tgt: string[]; seq: string } } = {
14
- 'peptideSimpleSingleChar': {
15
- seq: 'PEPTIDE1{L.V.A}$$$$',
16
- tgt: ['PEPTIDE1{', 'L', '.', 'V', '.', 'A', '}$$$$'],
17
- },
18
- 'peptideSimpleMultiChar': {
19
- seq: 'PEPTIDE1{[Ac].V.A}$$$$',
20
- /* doubt joining square brackets to separator or notation is correct */
21
- tgt: ['PEPTIDE1{[', 'Ac', '].', 'V', '.', 'A', '}$$$$'],
22
- }
23
- };
24
-
25
- before(async () => {
26
- await initHelmMainPackage();
27
- });
28
-
29
- for (const [testName, testData] of Object.entries(tests)) {
30
- test(`${testName}`, async () => {
31
- await _testAllParts(testData.seq, testData.tgt);
32
- });
33
- }
34
- });
35
-
36
- async function _testAllParts(seq: string | null, tgt: string[]): Promise<void> {
37
- const res: string[] = getAllParts(seq);
38
- expectArray(res, tgt);
39
- }