@datagrok/sequence-translator 1.4.4 → 1.4.5

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.
@@ -16,7 +16,6 @@ import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-he
16
16
  import '@datagrok-libraries/bio/src/types/input';
17
17
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
18
18
  import {InputColumnBase} from '@datagrok-libraries/bio/src/types/input';
19
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
20
19
 
21
20
  import {
22
21
  PolyToolEnumeratorParams, PolyToolEnumeratorType, PolyToolEnumeratorTypes
@@ -36,8 +35,9 @@ type PolyToolEnumerateInputs = {
36
35
  placeholdersBreadth: PolyToolPlaceholdersBreadthInput;
37
36
  enumeratorType: DG.ChoiceInput<PolyToolEnumeratorType>
38
37
  trivialNameCol: InputColumnBase,
39
- toAtomicLevel: DG.InputBase<boolean>;
40
38
  keepOriginal: DG.InputBase<boolean>;
39
+ toAtomicLevel: DG.InputBase<boolean>;
40
+ toHarmonizedSequence: DG.InputBase<boolean>;
41
41
  };
42
42
 
43
43
  type PolyToolEnumerateHelmSerialized = {
@@ -46,8 +46,9 @@ type PolyToolEnumerateHelmSerialized = {
46
46
  placeholdersBreadth: string;
47
47
  enumeratorType: PolyToolEnumeratorType;
48
48
  trivialNameCol: string;
49
- toAtomicLevel: boolean;
50
49
  keepOriginal: boolean;
50
+ toAtomicLevel: boolean;
51
+ toHarmonizedSequence: boolean;
51
52
  };
52
53
 
53
54
  export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
@@ -160,10 +161,12 @@ async function getPolyToolEnumerateDialog(
160
161
  showRowHeader: false,
161
162
  showCellTooltip: false,
162
163
  }),
163
- toAtomicLevel: ui.input.bool(
164
- 'To atomic level', {value: false}),
165
164
  keepOriginal: ui.input.bool(
166
165
  'Keep original', {value: false}),
166
+ toAtomicLevel: ui.input.bool(
167
+ 'To atomic level', {value: false}),
168
+ toHarmonizedSequence: ui.input.bool(
169
+ 'To harmonized sequence', {value: false}),
167
170
  trivialNameCol: ui.input.column2(
168
171
  'Trivial name', {
169
172
  table: cell?.dataFrame,
@@ -184,6 +187,7 @@ async function getPolyToolEnumerateDialog(
184
187
  }),
185
188
  };
186
189
 
190
+ inputs.toHarmonizedSequence.root.style.display = 'none';
187
191
  inputs.trivialNameCol.addOptions(trivialNameSampleDiv);
188
192
 
189
193
  let placeholdersValidity: string | null = null;
@@ -363,8 +367,9 @@ async function getPolyToolEnumerateDialog(
363
367
  let helmValue: string;
364
368
  let table: DG.DataFrame | undefined = undefined;
365
369
  if (cell && cell.rowIndex >= 0 && cell?.column.semType == DG.SEMTYPE.MACROMOLECULE) {
366
- const sh = SeqHandler.forColumn(cell.column);
367
- helmValue = await sh.getHelm(cell.rowIndex);
370
+ const sh = _package.seqHelper.getSeqHandler(cell.column);
371
+ const helmSemValue = await sh.getHelm(cell.rowIndex);
372
+ helmValue = helmSemValue.value;
368
373
  table = cell.dataFrame;
369
374
  } else {
370
375
  helmValue = PT_HELM_EXAMPLE;
@@ -414,8 +419,8 @@ async function getPolyToolEnumerateDialog(
414
419
  .add(inputs.enumeratorType)
415
420
  .add(inputs.placeholdersBreadth)
416
421
  .add(inputs.trivialNameCol)
417
- .add(inputs.toAtomicLevel)
418
- .add(inputs.keepOriginal)
422
+ .add(ui.divH([inputs.keepOriginal.root, inputs.toAtomicLevel.root, inputs.toHarmonizedSequence.root],
423
+ {style: {width: '100%'}}))
419
424
  .add(warningsTextDiv)
420
425
  // .addButton('Enumerate', () => {
421
426
  // execDialog()
@@ -433,8 +438,9 @@ async function getPolyToolEnumerateDialog(
433
438
  enumeratorType: inputs.enumeratorType.value,
434
439
  placeholdersBreadth: inputs.placeholdersBreadth.stringValue,
435
440
  trivialNameCol: inputs.trivialNameCol.stringValue,
436
- toAtomicLevel: inputs.toAtomicLevel.value,
437
441
  keepOriginal: inputs.keepOriginal.value,
442
+ toAtomicLevel: inputs.toAtomicLevel.value,
443
+ toHarmonizedSequence: inputs.toHarmonizedSequence.value,
438
444
  };
439
445
  },
440
446
  /* applyInput */ (x: PolyToolEnumerateHelmSerialized): void => {
@@ -443,8 +449,9 @@ async function getPolyToolEnumerateDialog(
443
449
  inputs.enumeratorType.value = x.enumeratorType;
444
450
  inputs.placeholdersBreadth.stringValue = x.placeholdersBreadth;
445
451
  inputs.trivialNameCol.stringValue = x.trivialNameCol;
446
- inputs.toAtomicLevel.value = x.toAtomicLevel;
447
452
  inputs.keepOriginal.value = x.keepOriginal;
453
+ inputs.toAtomicLevel.value = x.toAtomicLevel;
454
+ inputs.toHarmonizedSequence.value = x.toHarmonizedSequence;
448
455
  });
449
456
  return dialog;
450
457
  } catch (err: any) {
@@ -4,7 +4,8 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {
6
6
  HelmType, HelmMol,
7
- JSDraw2ModuleType, OrgType
7
+ JSDraw2ModuleType, OrgType,
8
+ IHelmEditorOptions
8
9
  } from '@datagrok-libraries/bio/src/helm/types';
9
10
 
10
11
 
@@ -72,7 +73,7 @@ function getPtEnumeratorBreadth(m: HelmMol, placeholdersBreadth: PolyToolPlaceho
72
73
  export function doPolyToolEnumerateHelm(
73
74
  helm: string, id: string, params: PolyToolEnumeratorParams
74
75
  ): [ /* helm */ string, /* id */ string][] {
75
- const molHandler = new JSDraw2.MolHandler<HelmType>();
76
+ const molHandler = new JSDraw2.MolHandler<HelmType, IHelmEditorOptions>();
76
77
  const plugin = new org.helm.webeditor.Plugin(molHandler);
77
78
  org.helm.webeditor.IO.parseHelm(plugin, helm, new JSDraw2.Point(0, 0), undefined);
78
79
  const m = molHandler.m;
@@ -4,7 +4,6 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {Unsubscribable} from 'rxjs';
6
6
 
7
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
8
7
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
9
8
  import {getUnusedColName} from '@datagrok-libraries/bio/src/monomer-works/utils';
10
9
 
@@ -12,6 +11,7 @@ import {defaultErrorHandler} from '../utils/err-info';
12
11
  import {doPolyToolUnrule} from './pt-unrule';
13
12
  import {getRules, RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
14
13
  import {PT_ERROR_DATAFRAME, PT_UI_DIALOG_UNRULE, PT_UI_RULES_USED} from './const';
14
+ import {_package} from '../package';
15
15
 
16
16
  type PolyToolUnruleSerialized = {
17
17
  rules: string[];
@@ -34,7 +34,7 @@ export async function getPolyToolUnruleDialog(srcCol?: DG.Column<string>): Promi
34
34
  table: srcColVal.dataFrame, value: srcColVal,
35
35
  filter: (col: DG.Column) => {
36
36
  if (col.semType !== DG.SEMTYPE.MACROMOLECULE) return false;
37
- const sh = SeqHandler.forColumn(col);
37
+ const sh = _package.seqHelper.getSeqHandler(col);
38
38
  return sh.notation === NOTATION.HELM;
39
39
  }
40
40
  });
@@ -30,7 +30,7 @@ export function doPolyToolUnrule(helms: string[], rules: Rules): string[] {
30
30
  resHrzSeqList[i] = '';
31
31
  else {
32
32
  const chain = Chain.fromHelm(helms[i]);
33
- resHrzSeqList[i] = chain.getNotation(rules);
33
+ resHrzSeqList[i] = chain.getNotation();
34
34
  }
35
35
  }
36
36
  return resHrzSeqList;
@@ -0,0 +1,59 @@
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 {before, after, category, expect, test, expectArray, testEvent, delay} from '@datagrok-libraries/utils/src/test';
6
+ import {Chain} from '../polytool/pt-conversion';
7
+ import {getRules} from '../polytool/pt-rules';
8
+ import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
9
+
10
+ category('PolyTool: Chain: parseNotation', () => {
11
+ let helmHelper: IHelmHelper;
12
+
13
+ before(async () => {
14
+ helmHelper = await getHelmHelper(); // initialize JSDraw2 and org
15
+ });
16
+
17
+ const tests = {
18
+ 'cyclized': {
19
+ src: {seq: 'R-F-C(1)-T-G-H-F-Y-P-C(1)-meI'},
20
+ tgt: {
21
+ //monomerCount: [11], linkageCount: 1,
22
+ helm: 'PEPTIDE1{R.F.[C(1)].T.G.H.F.Y.P.[C(1)].[meI]}$$$$V2.0',
23
+ },
24
+ },
25
+ 'dimerized1': {
26
+ src: {seq: '(#2)Succ-{A(CHOL)-F-C(2)-T-G-H-Y-P-C(2)-NH2}'},
27
+ tgt: {
28
+ // TODO: Target test data requires clarification
29
+ //monomerCount: [2, 8], linkageCount: 0,
30
+ helm: 'PEPTIDE1{[(#2)Succ]}|PEPTIDE2{[A(CHOL)].F.[C(2)].T.G.H.Y.P.[C(2)].[NH2]}$PEPTIDE1,PEPTIDE2,1:R1-1:R1$$$V2.0',
31
+ },
32
+ },
33
+ 'dimerized2': {
34
+ src: {seq: '($2)Succ-{R-F-C(1)-T-G-H-F-P-C(1)-NH2}($2){A(CHOL)-F-C(1)-T-G-H-F-P-C(1)-NH2}'},
35
+ tgt: {
36
+ // TODO: Target test data requires clarification
37
+ //monomerCount: [2, 8], linkageCount: 0,
38
+ helm: 'PEPTIDE1{[($2)Succ]}|PEPTIDE2{R.F.[C(1)].T.G.H.F.P.[C(1)].[NH2]}|PEPTIDE3{[($2)A(CHOL)].F.[C(1)].T.G.H.F.P.[C(1)].[NH2]}$PEPTIDE1,PEPTIDE2,1:R1-1:R1$$$V2.0',
39
+ },
40
+ },
41
+ };
42
+
43
+ for (const [testName, testData] of Object.entries(tests)) {
44
+ test(`${testName}`, async () => {
45
+ const rules = await getRules(['rules_example.json']);
46
+ const resChain = await Chain.parseNotation(testData.src.seq);
47
+ //expectArray(resChain.monomers.map((mL) => mL.length), testData.tgt.monomerCount);
48
+ //expect(resChain.linkages.length, testData.tgt.linkageCount);
49
+ // expect(resChain.getNotationHelm(), testData.tgt.helm);
50
+ // expect(resChain.getNotation(), testData.src.seq);
51
+
52
+ const resMol = resChain.mol!;
53
+ const hwe = helmHelper.createHelmWebEditor();
54
+ hwe.editor.setMol(resMol!);
55
+ const resHelm = hwe.editor.getHelm();
56
+ expect(resHelm, testData.tgt.helm);
57
+ }, testName == 'reaction2' ? {skipReason: 'reverse reaction'} : undefined);
58
+ }
59
+ });
@@ -0,0 +1,43 @@
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 {category, test, expect, before} from '@datagrok-libraries/utils/src/test';
6
+ import {ISeqHelper, getSeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
7
+ import {ALIGNMENT, ALPHABET, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
8
+ import {_testNeg, _testPos, DetectorTestData, DfReaderFunc, PosCol} from './utils/detect-macromolecule-utils';
9
+
10
+ category('PolyTool: detectors', () => {
11
+ let seqHelper: ISeqHelper;
12
+
13
+ before(async () => {
14
+ seqHelper = await getSeqHelper();
15
+ });
16
+
17
+ const tests: DetectorTestData = {
18
+ 'cyclized1': {
19
+ csv: `n,seq
20
+ 1,R-F-C(1)-T-G-H-F-Y-G-H-F-Y-G-H-F-Y-P-C(1)-meI
21
+ 2,C(1)-T-G-H-F-Y-P-C(1)-meI
22
+ 3,R-F-C(1)-T-G-H-F-Y-P-C(1)
23
+ 4,C(1)-T-G-H-F-H-P-C(1)
24
+ 5,R-F-D(2)-T-G-H-F-Y-P-NH2(2)
25
+ 6,R-F-aG(3)-T-G-H-F-Y-P-azG(3)-meI`,
26
+ pos: {'seq': new PosCol(NOTATION.CUSTOM, ALIGNMENT.SEQ, ALPHABET.UN, 13, true, '-')}
27
+ },
28
+ };
29
+
30
+ for (const [testName, testData] of Object.entries(tests)) {
31
+ test(`${testName}`, async () => {
32
+ const reader: DfReaderFunc = async (): Promise<DG.DataFrame> => {
33
+ return DG.DataFrame.fromCsv(testData.csv);
34
+ };
35
+ for (const negColName of testData.neg ?? [])
36
+ await _testNeg(reader, negColName);
37
+ for (const [posColName, posCol] of Object.entries(testData.pos ?? {})) {
38
+ await _testPos(reader, posColName, seqHelper, posCol.units, posCol.aligned,
39
+ posCol.alphabet, posCol.alphabetSize, posCol.alphabetIsMultichar, posCol.separator);
40
+ }
41
+ });
42
+ }
43
+ });
@@ -45,7 +45,7 @@ category('toAtomicLevel', () => {
45
45
  expect(ggazM != null, true, `Monomer 'GGaz' not found.`);
46
46
 
47
47
  const overrideMonomerLibData: MonomerLibData = {[PolymerTypes.PEPTIDE]: {'GGaz': ggazM}};
48
- const overriddenMonomerLib = systemMonomerLib.override(overrideMonomerLibData);
48
+ const overriddenMonomerLib = systemMonomerLib.override(overrideMonomerLibData, 'test');
49
49
 
50
50
  const seqHelper = await getSeqHelper();
51
51
 
@@ -0,0 +1,64 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+ import * as grok from 'datagrok-api/grok';
3
+
4
+ import {ALIGNMENT, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
5
+ import {delay, expect} from '@datagrok-libraries/utils/src/test';
6
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
7
+
8
+ export type DetectorTestData = { [testName: string]: { csv: string, neg?: string[], pos?: { [colName: string]: PosCol } } };
9
+
10
+ export type DfReaderFunc = () => Promise<DG.DataFrame>;
11
+
12
+ export class PosCol {
13
+ constructor(
14
+ public readonly units: NOTATION,
15
+ public readonly aligned: ALIGNMENT | null,
16
+ public readonly alphabet: string | null,
17
+ public readonly alphabetSize: number,
18
+ public readonly alphabetIsMultichar?: boolean,
19
+ public readonly separator?: string,
20
+ ) { };
21
+ }
22
+
23
+ export async function _testNeg(readDf: DfReaderFunc, colName: string) {
24
+ const df: DG.DataFrame = await readDf();
25
+ const col: DG.Column = df.getCol(colName)!;
26
+ const semType: string = await grok.functions
27
+ .call('Bio:detectMacromolecule', {col: col}) as unknown as string;
28
+ if (semType)
29
+ col.semType = semType;
30
+
31
+ if (col.semType === DG.SEMTYPE.MACROMOLECULE) {
32
+ const msg = `Negative test detected semType='${col.semType}', units='${col.meta.units}'.`;
33
+ throw new Error(msg);
34
+ }
35
+ }
36
+
37
+ export async function _testPos(
38
+ readDf: DfReaderFunc, colName: string, seqHelper: ISeqHelper,
39
+ units: string, aligned: string | null, alphabet: string | null, alphabetSize: number, alphabetIsMultichar?: boolean,
40
+ separator: string | null = null,
41
+ ) {
42
+ const df: DG.DataFrame = await readDf();
43
+ const col: DG.Column = df.col(colName)!;
44
+ const semType: string = await grok.functions
45
+ .call('Bio:detectMacromolecule', {col: col}) as unknown as string;
46
+ if (semType)
47
+ col.semType = semType;
48
+
49
+ expect(col.semType, DG.SEMTYPE.MACROMOLECULE);
50
+ expect(col.meta.units, units);
51
+ expect(col.getTag(bioTAGS.aligned), aligned);
52
+ expect(col.getTag(bioTAGS.alphabet), alphabet);
53
+ if (separator)
54
+ expect(col.getTag(bioTAGS.separator), separator);
55
+
56
+ const sh = seqHelper.getSeqHandler(col);
57
+ expect(sh.getAlphabetSize(), alphabetSize);
58
+ expect(sh.getAlphabetIsMultichar(), alphabetIsMultichar);
59
+ if (!sh.isHelm()) {
60
+ expect(sh.aligned, aligned);
61
+ expect(sh.alphabet, alphabet);
62
+ }
63
+ }
64
+
@@ -2,8 +2,8 @@ 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
4
 
5
- import {DEFAULT_FORMATS} from '../apps/common/model/const';
6
- import {ITranslationHelper} from '../types';
5
+ import {DEFAULT_FORMATS} from '../../apps/common/model/const';
6
+ import {ITranslationHelper} from '../../types';
7
7
 
8
8
  export class OligoToolkitTestPackage extends DG.Package {
9
9
  async getTranslationHelper(): Promise<ITranslationHelper> {
@@ -2,9 +2,6 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
 
5
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
6
- import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
-
8
5
  import {defaultErrorHandler} from './err-info';
9
6
  import {polyToolEnumerateHelmUI} from '../polytool/pt-enumeration-helm-dialog';
10
7
  import {polyToolEnumerateChemUI} from '../polytool/pt-dialog';
@@ -0,0 +1,90 @@
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
+ /* eslint-disable max-len */
8
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
9
+ import {INotationProvider, ISeqSplitted, SeqSplittedBase, SplitterFunc} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
10
+ import {getSplitterWithSeparator} from '@datagrok-libraries/bio/src/utils/macromolecule';
11
+ import {GAP_SYMBOL, GapOriginals, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
12
+ import {CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
13
+ import {MonomerPlacer} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
14
+ import {monomerToShort, StringListSeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
15
+ import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
16
+
17
+ import {Chain} from '../polytool/pt-conversion';
18
+
19
+ import {_package} from '../package';
20
+
21
+ /* eslint-enable max-len */
22
+
23
+ export class CyclizedNotationProvider implements INotationProvider {
24
+ private readonly separatorSplitter: SplitterFunc;
25
+ public readonly splitter: SplitterFunc;
26
+
27
+ constructor(
28
+ public readonly separator: string,
29
+ protected readonly seqHelper: ISeqHelper
30
+ ) {
31
+ this.separatorSplitter = getSplitterWithSeparator(this.separator);
32
+ this.splitter = this._splitter.bind(this);
33
+ }
34
+
35
+ private _splitter(seq: string): ISeqSplitted {
36
+ const baseSS: ISeqSplitted = this.separatorSplitter(seq);
37
+ return new CyclizedSeqSplitted(
38
+ wu.count(0).take(baseSS.length).map((p) => baseSS.getOriginal(p)).toArray(),
39
+ GapOriginals[NOTATION.SEPARATOR]);
40
+ }
41
+
42
+ public async getHelm(seq: string, options?: any): Promise<DG.SemanticValue<string>> {
43
+ const seqChain = await Chain.parseNotation(seq);
44
+ const seqPseudoHelm = seqChain.getNotationHelm();
45
+
46
+ const resPseudoHelmSV = DG.SemanticValue.fromValueType(seqPseudoHelm,
47
+ DG.SEMTYPE.MACROMOLECULE, NOTATION.HELM);
48
+ resPseudoHelmSV.tags['pt-role'] = 'template';
49
+ return resPseudoHelmSV;
50
+ }
51
+
52
+ public createCellRendererBack(gridCol: DG.GridColumn | null, tableCol: DG.Column<string>): CellRendererBackBase<string> {
53
+ let maxLengthOfMonomer: number = 4; // (_package.bioProperties ? _package.bioProperties.maxMonomerLength : 4) ?? 50;
54
+ const back = new MonomerPlacer(gridCol, tableCol, _package.logger, maxLengthOfMonomer,
55
+ () => {
56
+ const sh = this.seqHelper.getSeqHandler(tableCol);
57
+ return {
58
+ seqHandler: sh,
59
+ monomerCharWidth: 7,
60
+ separatorWidth: 11,
61
+ monomerToShort: monomerToShort,
62
+ };
63
+ });
64
+ back.init().then(() => {});
65
+ return back;
66
+ }
67
+ }
68
+
69
+ /** Gets canonical monomers for original ones with cyclization marks */
70
+ export class CyclizedSeqSplitted extends StringListSeqSplitted {
71
+ private readonly seqCList: (string | null)[];
72
+
73
+ override getCanonical(posIdx: number): string {
74
+ if (this.isGap(posIdx)) return GAP_SYMBOL;
75
+
76
+ let cmRes: string | null = this.seqCList[posIdx];
77
+ if (cmRes === null) {
78
+ const om = this.getOriginal(posIdx);
79
+ cmRes = om;
80
+ if (om[om.length - 1] === ')')
81
+ cmRes = this.seqCList[posIdx] = om.replace(/\(\d+\)$/, '');
82
+ }
83
+ return cmRes;
84
+ }
85
+
86
+ constructor(seqOList: SeqSplittedBase, gapOriginalMonomer: string) {
87
+ super(seqOList, gapOriginalMonomer);
88
+ this.seqCList = new Array<string | null>(this.length).fill(null);
89
+ }
90
+ }
@@ -0,0 +1,10 @@
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 {CyclizedNotationProvider} from './cyclized';
6
+
7
+
8
+ export class DimerizedNotationProvider extends CyclizedNotationProvider {
9
+
10
+ }