@datagrok/bio 2.15.13 → 2.16.2

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/detectors.js +16 -11
  3. package/dist/455.js.map +1 -1
  4. package/dist/980.js +1 -1
  5. package/dist/980.js.map +1 -1
  6. package/dist/package-test.js +6 -6
  7. package/dist/package-test.js.map +1 -1
  8. package/dist/package.js +3 -3
  9. package/dist/package.js.map +1 -1
  10. package/package.json +14 -14
  11. package/src/analysis/sequence-activity-cliffs.ts +9 -8
  12. package/src/analysis/sequence-diversity-viewer.ts +6 -4
  13. package/src/analysis/sequence-similarity-viewer.ts +9 -6
  14. package/src/analysis/sequence-space.ts +3 -2
  15. package/src/calculations/monomerLevelMols.ts +4 -5
  16. package/src/demo/bio01-similarity-diversity.ts +4 -1
  17. package/src/package-test.ts +1 -1
  18. package/src/package-types.ts +34 -2
  19. package/src/package.ts +60 -76
  20. package/src/substructure-search/substructure-search.ts +15 -9
  21. package/src/tests/WebLogo-layout-tests.ts +1 -1
  22. package/src/tests/WebLogo-positions-test.ts +11 -5
  23. package/src/tests/WebLogo-project-tests.ts +1 -1
  24. package/src/tests/activity-cliffs-utils.ts +11 -14
  25. package/src/tests/bio-tests.ts +85 -79
  26. package/src/tests/checkInputColumn-tests.ts +15 -10
  27. package/src/tests/converters-test.ts +12 -5
  28. package/src/tests/detectors-benchmark-tests.ts +5 -2
  29. package/src/tests/detectors-tests.ts +51 -44
  30. package/src/tests/detectors-weak-and-likely-tests.ts +12 -5
  31. package/src/tests/fasta-export-tests.ts +13 -5
  32. package/src/tests/helm-tests.ts +85 -0
  33. package/src/tests/mm-distance-tests.ts +14 -7
  34. package/src/tests/monomer-libraries-tests.ts +1 -1
  35. package/src/tests/msa-tests.ts +33 -24
  36. package/src/tests/renderers-monomer-placer-tests.ts +2 -5
  37. package/src/tests/renderers-test.ts +15 -9
  38. package/src/tests/scoring.ts +9 -6
  39. package/src/tests/seq-handler-get-helm-tests.ts +7 -5
  40. package/src/tests/seq-handler-get-region-tests.ts +9 -3
  41. package/src/tests/seq-handler-splitted-tests.ts +11 -5
  42. package/src/tests/seq-handler-tests.ts +17 -10
  43. package/src/tests/sequence-space-utils.ts +9 -4
  44. package/src/tests/splitters-test.ts +5 -4
  45. package/src/tests/substructure-filters-tests.ts +22 -23
  46. package/src/tests/to-atomic-level-tests.ts +5 -3
  47. package/src/tests/to-atomic-level-ui-tests.ts +4 -1
  48. package/src/tests/utils/detectors-utils.ts +4 -4
  49. package/src/utils/calculate-scores.ts +11 -9
  50. package/src/utils/cell-renderer-custom.ts +27 -17
  51. package/src/utils/cell-renderer.ts +14 -8
  52. package/src/utils/check-input-column.ts +13 -9
  53. package/src/utils/context-menu.ts +4 -4
  54. package/src/utils/convert.ts +21 -14
  55. package/src/utils/get-region-func-editor.ts +8 -5
  56. package/src/utils/get-region.ts +4 -5
  57. package/src/utils/helm-to-molfile/converter/helm.ts +4 -4
  58. package/src/utils/helm-to-molfile/utils.ts +5 -6
  59. package/src/utils/macromolecule-column-widget.ts +6 -7
  60. package/src/utils/monomer-cell-renderer-base.ts +8 -1
  61. package/src/utils/monomer-lib/lib-manager.ts +3 -2
  62. package/src/utils/monomer-lib/monomer-colors.ts +10 -10
  63. package/src/utils/monomer-lib/monomer-lib-base.ts +6 -1
  64. package/src/utils/monomer-lib/monomer-lib.ts +15 -9
  65. package/src/utils/multiple-sequence-alignment-ui.ts +30 -30
  66. package/src/utils/save-as-fasta.ts +19 -12
  67. package/src/utils/seq-helper/seq-handler.ts +836 -0
  68. package/src/utils/seq-helper/seq-helper.ts +43 -19
  69. package/src/utils/sequence-to-mol.ts +7 -8
  70. package/src/utils/split-to-monomers.ts +7 -2
  71. package/src/utils/types.ts +8 -7
  72. package/src/utils/ui-utils.ts +2 -2
  73. package/src/viewers/web-logo-viewer.ts +18 -16
  74. package/src/widgets/bio-substructure-filter-helm.ts +5 -2
  75. package/src/widgets/bio-substructure-filter.ts +14 -24
  76. package/src/widgets/composition-analysis-widget.ts +6 -6
  77. package/src/widgets/representations.ts +7 -4
  78. package/src/tests/detectors-custom-notation-tests.ts +0 -37
  79. package/src/utils/cyclized.ts +0 -89
  80. package/src/utils/dimerized.ts +0 -10
@@ -15,9 +15,10 @@ import {getMolHighlight} from '@datagrok-libraries/bio/src/monomer-works/seq-to-
15
15
  import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/index';
16
16
 
17
17
  import {HelmToMolfileConverter} from '../helm-to-molfile/converter';
18
- import {MonomerLibManager} from '../monomer-lib/lib-manager';
19
-
20
- import {_package, getMonomerLibHelper} from '../../package';
18
+ import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
19
+ import {SeqHandler} from './seq-handler';
20
+ import {Column} from 'datagrok-api/dg';
21
+ import {NOTATION, TAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
21
22
 
22
23
  type SeqHelperWindowType = Window & { $seqHelperPromise?: Promise<SeqHelper> };
23
24
  declare const window: SeqHelperWindowType;
@@ -25,12 +26,22 @@ declare const window: SeqHelperWindowType;
25
26
  export class SeqHelper implements ISeqHelper {
26
27
  constructor(
27
28
  private readonly libHelper: IMonomerLibHelper,
28
- private readonly helmHelper: IHelmHelper,
29
29
  private readonly rdKitModule: RDModule
30
30
  ) {}
31
31
 
32
- getHelmToMolfileConverter(monomerLib: IMonomerLibBase): HelmToMolfileConverter {
33
- return new HelmToMolfileConverter(this.helmHelper, this.rdKitModule, monomerLib);
32
+ getSeqHandler(seqCol: DG.Column<string>): ISeqHandler {
33
+ return SeqHandler.forColumn(seqCol, this);
34
+ }
35
+
36
+ getSeqMonomers(seqCol: Column<string>): string[] {
37
+ const sh = this.getSeqHandler(seqCol);
38
+ return Object.keys(sh.stats.freq);
39
+ }
40
+
41
+ // TODO: Move to the Helm package
42
+ async getHelmToMolfileConverter(monomerLib: IMonomerLibBase): Promise<HelmToMolfileConverter> {
43
+ const helmHelper: IHelmHelper = await getHelmHelper();
44
+ return new HelmToMolfileConverter(helmHelper, this.rdKitModule, monomerLib);
34
45
  }
35
46
 
36
47
  async helmToAtomicLevel(
@@ -41,7 +52,7 @@ export class SeqHelper implements ISeqHelper {
41
52
  const df: DG.DataFrame = helmCol.dataFrame;
42
53
  const molColName: string = getMolColName(df, helmCol.name);
43
54
 
44
- const converter = this.getHelmToMolfileConverter(monomerLib);
55
+ const converter = await this.getHelmToMolfileConverter(monomerLib);
45
56
 
46
57
  //#region From HelmToMolfileConverter.convertToRdKitBeautifiedMolfileColumn
47
58
 
@@ -86,17 +97,30 @@ export class SeqHelper implements ISeqHelper {
86
97
  return {molCol: molCol, warnings: []};
87
98
  }
88
99
 
89
- static getInstance(): Promise<SeqHelper> {
90
- let res = window.$seqHelperPromise;
91
- if (res == undefined) {
92
- res = window.$seqHelperPromise = (async () => {
93
- if (!_package.initialized)
94
- throw new Error('Bio package is not initialized, call Bio:getSeqHelper');
95
- const instance = new SeqHelper(
96
- await MonomerLibManager.getInstance(), await getHelmHelper(), _package.rdKitModule);
97
- return instance;
98
- })();
99
- }
100
- return res;
100
+ public setUnitsToFastaColumn(uh: SeqHandler) {
101
+ if (uh.column.semType !== DG.SEMTYPE.MACROMOLECULE || uh.column.meta.units !== NOTATION.FASTA)
102
+ throw new Error(`The column of notation '${NOTATION.FASTA}' must be '${DG.SEMTYPE.MACROMOLECULE}'.`);
103
+
104
+ uh.column.meta.units = NOTATION.FASTA;
105
+ SeqHandler.setTags(uh);
106
+ }
107
+
108
+ public setUnitsToSeparatorColumn(uh: SeqHandler, separator?: string) {
109
+ if (uh.column.semType !== DG.SEMTYPE.MACROMOLECULE || uh.column.meta.units !== NOTATION.SEPARATOR)
110
+ throw new Error(`The column of notation '${NOTATION.SEPARATOR}' must be '${DG.SEMTYPE.MACROMOLECULE}'.`);
111
+ if (!separator)
112
+ throw new Error(`The column of notation '${NOTATION.SEPARATOR}' must have the separator tag.`);
113
+
114
+ uh.column.meta.units = NOTATION.SEPARATOR;
115
+ uh.column.setTag(TAGS.separator, separator);
116
+ SeqHandler.setTags(uh);
117
+ }
118
+
119
+ public setUnitsToHelmColumn(uh: SeqHandler) {
120
+ if (uh.column.semType !== DG.SEMTYPE.MACROMOLECULE)
121
+ throw new Error(`The column of notation '${NOTATION.HELM}' must be '${DG.SEMTYPE.MACROMOLECULE}'`);
122
+
123
+ uh.column.meta.units = NOTATION.HELM;
124
+ SeqHandler.setTags(uh);
101
125
  }
102
126
  }
@@ -4,24 +4,23 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {_toAtomicLevel} from '@datagrok-libraries/bio/src/monomer-works/to-atomic-level';
6
6
  import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
7
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
8
7
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
9
- import {getSeqHelper, ToAtomicLevelRes} from '@datagrok-libraries/bio/src/utils/seq-helper';
8
+ import {getSeqHelper, ISeqHelper, ToAtomicLevelRes} from '@datagrok-libraries/bio/src/utils/seq-helper';
10
9
  import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
11
10
  import {ChemTags, ChemTemps} from '@datagrok-libraries/chem-meta/src/consts';
12
11
  import {buildMonomerHoverLink} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
13
12
 
14
- import {checkInputColumnUI} from './check-input-column';
13
+ import {checkInputColumn, checkInputColumnUI} from './check-input-column';
15
14
  import {getMolColName} from '@datagrok-libraries/bio/src/monomer-works/utils';
16
15
 
17
16
  export async function sequenceToMolfile(
18
17
  df: DG.DataFrame, macroMolecule: DG.Column, nonlinear: boolean, highlight: boolean,
19
- monomerLib: IMonomerLib, rdKitModule: RDModule
18
+ monomerLib: IMonomerLib, seqHelper: ISeqHelper, rdKitModule: RDModule
20
19
  ): Promise<ToAtomicLevelRes> {
21
20
  let res: ToAtomicLevelRes;
22
21
  if (nonlinear) {
23
22
  const seqHelper = await getSeqHelper();
24
- const seqSh = SeqHandler.forColumn(macroMolecule);
23
+ const seqSh = seqHelper.getSeqHandler(macroMolecule);
25
24
 
26
25
  let helmCol: DG.Column<string>;
27
26
  let seqColName!: string;
@@ -43,10 +42,10 @@ export async function sequenceToMolfile(
43
42
  }
44
43
  }
45
44
  } else { // linear
46
- if (!checkInputColumnUI(macroMolecule, 'To Atomic Level'))
45
+ if (!checkInputColumn(macroMolecule, 'To Atomic Level', seqHelper)[0])
47
46
  return {molCol: null, warnings: ['Column is not suitable']};
48
47
 
49
- res = await _toAtomicLevel(df, macroMolecule, monomerLib, rdKitModule);
48
+ res = await _toAtomicLevel(df, macroMolecule, monomerLib, seqHelper, rdKitModule);
50
49
  }
51
50
 
52
51
  if (res.molCol) {
@@ -54,7 +53,7 @@ export async function sequenceToMolfile(
54
53
  res.molCol.name = molColName;
55
54
  df.columns.add(res.molCol, true);
56
55
 
57
- buildMonomerHoverLink(macroMolecule, res.molCol, monomerLib, rdKitModule);
56
+ buildMonomerHoverLink(macroMolecule, res.molCol, monomerLib, seqHelper, rdKitModule);
58
57
  res.molCol.setTag(ChemTags.SEQUENCE_SRC_HL_MONOMERS, String(highlight));
59
58
  await grok.data.detectSemanticTypes(df);
60
59
  }
@@ -8,15 +8,20 @@ import {splitAlignedSequences} from '@datagrok-libraries/bio/src/utils/splitter'
8
8
  import * as C from './constants';
9
9
  import {TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
10
10
  import {SEM_TYPES} from './constants';
11
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
12
+ import {_package} from '../package';
11
13
 
12
14
 
13
- export async function splitToMonomersUI(table: DG.DataFrame, seqCol: DG.Column<string>): Promise<DG.DataFrame> {
15
+ export async function splitToMonomersUI(
16
+ table: DG.DataFrame, seqCol: DG.Column<string>
17
+ ): Promise<DG.DataFrame> {
14
18
  // Delay is required for initial function dialog to close before starting invalidating of molfiles.
15
19
  // Otherwise, dialog is freezing
16
20
  await delay(10);
17
21
  if (!checkInputColumnUI(seqCol, 'Sequence space')) return table;
18
22
 
19
- const tempDf = splitAlignedSequences(seqCol);
23
+ const seqHelper = _package.seqHelper;
24
+ const tempDf = splitAlignedSequences(seqCol, seqHelper);
20
25
  tempDf.name = 'splitToMonomers';
21
26
  const originalDf = seqCol.dataFrame;
22
27
  for (const tempCol of tempDf.columns) {
@@ -1,19 +1,20 @@
1
1
  import * as DG from 'datagrok-api/dg';
2
2
  import {pepseaMethods} from './pepsea';
3
- export type DataFrameDict = {[key: string]: DG.DataFrame};
3
+
4
+ export type DataFrameDict = { [key: string]: DG.DataFrame };
4
5
 
5
6
  export namespace BarChart {
6
- export type BarPart = {colName : string, aaName : string};
7
- export type BarStatsObject = {name: string, count: number, selectedCount: number};
7
+ export type BarPart = { colName: string, aaName: string };
8
+ export type BarStatsObject = { name: string, count: number, selectedCount: number };
8
9
  }
9
10
 
10
11
  export type UTypedArray = Uint8Array | Uint16Array | Uint32Array;
11
12
  //AAR: (Position: (index: indexList))
12
13
  export type SubstitutionsInfo = Map<string, Map<string, Map<number, number[] | UTypedArray>>>;
13
- export type SelectionObject = {[postiton: string]: string[]};
14
+ export type SelectionObject = { [position: string]: string[] };
14
15
 
15
- export type multipleSequenceAlginmentUIOptions = {
16
+ export type MultipleSequenceAlignmentUIOptions = {
16
17
  col?: DG.Column<string> | null, clustersCol?: DG.Column | null,
17
- pepsea?: {method?: typeof pepseaMethods[number], gapOpen?: number, gapExtend?: number},
18
- kalign?: {gapOpen?: number, gapExtend?: number, terminalGap?: number}
18
+ pepsea?: { method?: typeof pepseaMethods[number], gapOpen?: number, gapExtend?: number },
19
+ kalign?: { gapOpen?: number, gapExtend?: number, terminalGap?: number }
19
20
  };
@@ -1,11 +1,11 @@
1
1
  import * as grok from 'datagrok-api/grok';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
 
4
- export function getMacromoleculeColumns(): DG.Column<any>[] | any {
4
+ export function getMacromoleculeColumns(): DG.Column<string>[] {
5
5
  const columns = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
6
6
  if (columns === null) {
7
7
  grok.shell.error('Current table does not contain macromolecules');
8
- return;
8
+ return [];
9
9
  }
10
10
  return columns;
11
11
  }
@@ -6,7 +6,8 @@ import $ from 'cash-dom';
6
6
  import wu from 'wu';
7
7
  import {fromEvent, Observable, Subject, Unsubscribable} from 'rxjs';
8
8
 
9
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
9
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
10
+ import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
10
11
  import {
11
12
  monomerToShort, pickUpSeqCol, TAGS as bioTAGS, positionSeparator, ALPHABET
12
13
  } from '@datagrok-libraries/bio/src/utils/macromolecule';
@@ -308,7 +309,8 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
308
309
 
309
310
  private viewed: boolean = false;
310
311
 
311
- private seqHandler: SeqHandler | null;
312
+ private seqHelper: ISeqHelper;
313
+ private seqHandler: ISeqHandler | null;
312
314
  private initialized: boolean = false;
313
315
 
314
316
  private monomerLib: IMonomerLibBase | null = null;
@@ -387,6 +389,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
387
389
  constructor() {
388
390
  super();
389
391
 
392
+ this.seqHelper = _package.seqHelper;
390
393
  this.textBaseline = 'top';
391
394
  this.seqHandler = null;
392
395
 
@@ -606,7 +609,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
606
609
  }
607
610
  if (this.seqCol) {
608
611
  try {
609
- this.seqHandler = SeqHandler.forColumn(this.seqCol);
612
+ this.seqHandler = this.seqHelper.getSeqHandler(this.seqCol);
610
613
 
611
614
  this.render(WlRenderLevel.Freqs, 'updateSeqCol()');
612
615
  this.error = null;
@@ -1006,7 +1009,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
1006
1009
  // endregion updatePositions
1007
1010
 
1008
1011
  const length: number = this.startPosition <= this.endPosition ? this.endPosition - this.startPosition + 1 : 0;
1009
- this.seqHandler = SeqHandler.forColumn(this.seqCol);
1012
+ this.seqHandler = this.seqHelper.getSeqHandler(this.seqCol);
1010
1013
  const posCount: number = this.startPosition <= this.endPosition ? this.endPosition - this.startPosition + 1 : 0;
1011
1014
  this.positions = new Array(posCount);
1012
1015
  for (let jPos = 0; jPos < length; jPos++) {
@@ -1073,7 +1076,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
1073
1076
  const absoluteMaxHeight: number = this.canvas.height - positionLabelsHeight * dpr;
1074
1077
  let alphabetSizeLog: number;
1075
1078
  if (this.valueAggrType === DG.AGG.TOTAL_COUNT) {
1076
- const alphabetSize: number = this.getAlphabetSize();
1079
+ const alphabetSize: number = this.seqHandler!.getAlphabetSize();
1077
1080
  if ((this.positionHeight == PositionHeight.Entropy) && (alphabetSize == null))
1078
1081
  grok.shell.error('WebLogo: alphabet is undefined.');
1079
1082
  alphabetSizeLog = Math.log2(alphabetSize);
@@ -1139,8 +1142,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
1139
1142
  // Hacks to scale uppercase characters to target rectangle
1140
1143
  const uppercaseLetterAscent = 0.25;
1141
1144
  const uppercaseLetterHeight = 12.2;
1142
- const sh = SeqHandler.forColumn(this.seqCol);
1143
- const biotype = sh.defaultBiotype;
1145
+ const biotype = this.seqHandler!.defaultBiotype;
1144
1146
  for (let jPos = firstPos; jPos <= lastPos; jPos++)
1145
1147
  this.positions[jPos].render(g, fontStyle, uppercaseLetterAscent, uppercaseLetterHeight, biotype, this.monomerLib);
1146
1148
  } finally {
@@ -1165,9 +1167,9 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
1165
1167
  private _lastWidth: number;
1166
1168
  private _lastHeight: number;
1167
1169
 
1168
- public getAlphabetSize(): number {
1169
- return this.seqHandler?.getAlphabetSize() ?? 0;
1170
- }
1170
+ // public getAlphabetSize(): number {
1171
+ // return this.seqHandler?.getAlphabetSize() ?? 0;
1172
+ // }
1171
1173
 
1172
1174
  // -- Handle events --
1173
1175
 
@@ -1215,7 +1217,8 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
1215
1217
  }
1216
1218
  }
1217
1219
 
1218
- private canvasOnMouseMove(e: MouseEvent) {
1220
+ private canvasOnMouseMove(e: MouseEvent): void {
1221
+ if (!this.monomerLib || !this.seqHandler) return;
1219
1222
  const dpr = window.devicePixelRatio;
1220
1223
  try {
1221
1224
  const args = e as MouseEvent;
@@ -1224,13 +1227,12 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
1224
1227
  const [pi, monomer] = this.getMonomer(cursorP, dpr);
1225
1228
  const positionLabelHeight = this.showPositionLabels ? POSITION_LABELS_HEIGHT * dpr : 0;
1226
1229
 
1227
- if (pi !== null && monomer === null && 0 <= cursorP.y && cursorP.y <= positionLabelHeight && this.monomerLib) {
1230
+ if (pi !== null && monomer === null && 0 <= cursorP.y && cursorP.y <= positionLabelHeight) {
1228
1231
  // Position tooltip
1229
1232
 
1230
1233
  const tooltipRows = [ui.divText(`Position ${pi.label}`)];
1231
1234
  if (this.valueAggrType === DG.AGG.TOTAL_COUNT) {
1232
- const sh = SeqHandler.forColumn(this.seqCol!);
1233
- const biotype = sh.defaultBiotype;
1235
+ const biotype = this.seqHandler!.defaultBiotype;
1234
1236
  tooltipRows.push(pi.buildCompositionTable(biotype, this.monomerLib));
1235
1237
  }
1236
1238
  const tooltipEl = ui.divV(tooltipRows);
@@ -1356,7 +1358,7 @@ function renderPositionLabels(g: CanvasRenderingContext2D,
1356
1358
  }
1357
1359
 
1358
1360
  export function checkSeqForMonomerAtPos(
1359
- df: DG.DataFrame, sh: SeqHandler, filter: DG.BitSet, rowI: number, monomer: string, at: PositionInfo,
1361
+ df: DG.DataFrame, sh: ISeqHandler, filter: DG.BitSet, rowI: number, monomer: string, at: PositionInfo,
1360
1362
  ): boolean {
1361
1363
  const seqMList: ISeqSplitted = sh.getSplitted(rowI);
1362
1364
  const seqCM: string | null = at.pos < seqMList.length ? seqMList.getCanonical(at.pos) : null;
@@ -1364,7 +1366,7 @@ export function checkSeqForMonomerAtPos(
1364
1366
  }
1365
1367
 
1366
1368
  export function countForMonomerAtPosition(
1367
- df: DG.DataFrame, sh: SeqHandler, filter: DG.BitSet, monomer: string, at: PositionInfo
1369
+ df: DG.DataFrame, sh: ISeqHandler, filter: DG.BitSet, monomer: string, at: PositionInfo
1368
1370
  ): number {
1369
1371
  let count = 0;
1370
1372
  let rowI = -1;
@@ -10,6 +10,7 @@ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
10
10
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
11
11
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
12
12
  import {delay} from '@datagrok-libraries/utils/src/test';
13
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
13
14
 
14
15
  import {updateDivInnerHTML} from '../utils/ui-utils';
15
16
  import {helmSubstructureSearch} from '../substructure-search/substructure-search';
@@ -32,7 +33,9 @@ export class HelmBioFilter extends BioFilterBase<BioFilterProps> /* implements I
32
33
 
33
34
  get type(): string { return 'HelmBioFilter'; }
34
35
 
35
- constructor() {
36
+ constructor(
37
+ private readonly seqHelper: ISeqHelper,
38
+ ) {
36
39
  super();
37
40
  this.logger = _package.logger;
38
41
  }
@@ -138,7 +141,7 @@ export class HelmBioFilter extends BioFilterBase<BioFilterProps> /* implements I
138
141
  _package.logger.debug(`${logPrefix}, start`);
139
142
  try {
140
143
  await delay(10);
141
- const res = await helmSubstructureSearch(this.props.substructure, column);
144
+ const res = await helmSubstructureSearch(this.props.substructure, column, this.seqHelper);
142
145
  return res;
143
146
  } finally {
144
147
  _package.logger.debug(`${logPrefix}, end`);
@@ -16,18 +16,16 @@ import {TAGS as bioTAGS, NOTATION} from '@datagrok-libraries/bio/src/utils/macro
16
16
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
17
17
  import {delay, testEvent} from '@datagrok-libraries/utils/src/test';
18
18
  import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
19
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
20
19
  import {IRenderer} from '@datagrok-libraries/bio/src/types/renderer';
21
20
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
22
21
  import {PromiseSyncer} from '@datagrok-libraries/bio/src/utils/syncer';
22
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
23
23
 
24
24
  import {helmSubstructureSearch, linearSubstructureSearch} from '../substructure-search/substructure-search';
25
25
  import {updateDivInnerHTML} from '../utils/ui-utils';
26
26
  import {BioFilterBase, BioFilterProps, IBioFilter, IFilterProps} from './bio-substructure-filter-types';
27
27
  import {HelmBioFilter} from './bio-substructure-filter-helm';
28
28
 
29
- import {_package} from '../package';
30
-
31
29
  const FILTER_SYNC_EVENT: string = 'bio-substructure-filter';
32
30
 
33
31
  class FilterState {
@@ -56,7 +54,6 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
56
54
  readonly loader: HTMLDivElement;
57
55
  notation: string | undefined = undefined;
58
56
 
59
- readonly logger: ILogger;
60
57
  readonly filterSyncer: PromiseSyncer;
61
58
 
62
59
  get calculating(): boolean { return this.loader.style.display == 'initial'; }
@@ -88,22 +85,15 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
88
85
  return res;
89
86
  }
90
87
 
91
- constructor() {
88
+ constructor(
89
+ private readonly seqHelper: ISeqHelper,
90
+ private logger: ILogger
91
+ ) {
92
92
  super();
93
93
  this.root = ui.divV([]);
94
94
  this.loader = ui.loader();
95
95
  this.calculating = false;
96
- this.filterSyncer = new PromiseSyncer(this.logger = _package.logger);
97
-
98
- return new Proxy(this, {
99
- set(target: any, key, value) {
100
- if (key === 'column') {
101
- const k = 42;
102
- }
103
- target[key] = value;
104
- return true;
105
- }
106
- });
96
+ this.filterSyncer = new PromiseSyncer(this.logger);
107
97
  }
108
98
 
109
99
  private static filterCounter: number = -1;
@@ -125,13 +115,13 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
125
115
  else
126
116
  this.column = dataFrame.columns.bySemType(DG.SEMTYPE.MACROMOLECULE);
127
117
  }
128
- const sh = SeqHandler.forColumn(this.column!);
118
+ const sh = this.seqHelper.getSeqHandler(this.column!);
129
119
  this.columnName ??= this.column?.name;
130
120
  this.notation ??= this.column?.meta.units!;
131
121
 
132
122
  this.bioFilter = this.notation === NOTATION.FASTA ?
133
123
  new FastaBioFilter() : this.notation === NOTATION.SEPARATOR ?
134
- new SeparatorBioFilter(this.column!.getTag(bioTAGS.separator)) : new HelmBioFilter();
124
+ new SeparatorBioFilter(this.column!.getTag(bioTAGS.separator)) : new HelmBioFilter(this.seqHelper);
135
125
  this.root.appendChild(this.bioFilter!.filterPanel);
136
126
  this.root.appendChild(this.loader);
137
127
  await this.bioFilter.attach(); // may await waitForElementInDom
@@ -201,7 +191,7 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
201
191
 
202
192
  private fireFilterSync(): void {
203
193
  const logPrefix = `${this.filterToLog()}.fireFilterSync()`;
204
- _package.logger.debug(`${logPrefix}, ` +
194
+ this.logger.debug(`${logPrefix}, ` +
205
195
  `bioFilter = ${!!this.bioFilter ? this.bioFilter.constructor.name : 'null'}` +
206
196
  (!!this.bioFilter ? `, props = ${JSON.stringify(this.bioFilter!.saveProps())}` : ''));
207
197
 
@@ -219,7 +209,7 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
219
209
  bioFilterOnChangedDebounced(): void {
220
210
  if (!this.dataFrame) return; // Debounced event can be handled postponed
221
211
  const logPrefix = `${this.filterToLog()}.bioFilterOnChangedDebounced()`;
222
- _package.logger.debug(`${logPrefix}, start, ` +
212
+ this.logger.debug(`${logPrefix}, start, ` +
223
213
  `isFiltering = ${this.isFiltering}, ` +
224
214
  `props = ${JSON.stringify(this.bioFilter!.saveProps())}`);
225
215
 
@@ -236,22 +226,22 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
236
226
  this.filterSyncer.sync(logPrefix, async () => {
237
227
  this.calculating = true;
238
228
  try {
239
- _package.logger.debug(`${logPrefix}, before substructureSearch`);
229
+ this.logger.debug(`${logPrefix}, before substructureSearch`);
240
230
  this.bitset = await this.bioFilter?.substructureSearch(this.column!)!;
241
- _package.logger.debug(`${logPrefix}, after substructureSearch`);
231
+ this.logger.debug(`${logPrefix}, after substructureSearch`);
242
232
  this.calculating = false;
243
233
  this.fireFilterSync();
244
234
  this.dataFrame?.rows.requestFilter();
245
235
  } finally {
246
236
  this.calculating = false;
247
- _package.logger.debug(`${logPrefix}, end`);
237
+ this.logger.debug(`${logPrefix}, end`);
248
238
  }
249
239
  });
250
240
  }
251
241
 
252
242
  grokEventsOnResetFilterRequest(): void {
253
243
  const logPrefix = `${this.filterToLog()}.grokEventsOnResetFilterRequest()`;
254
- _package.logger.debug(`${logPrefix}`);
244
+ this.logger.debug(`${logPrefix}`);
255
245
  this.bioFilter?.resetFilter();
256
246
  }
257
247
 
@@ -4,25 +4,25 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import wu from 'wu';
6
6
 
7
- import {TAGS as bioTAGS, ALPHABET, getPaletteByType} from '@datagrok-libraries/bio/src/utils/macromolecule';
8
- import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
9
- import {UnknownSeqPalettes} from '@datagrok-libraries/bio/src/unknown';
10
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
7
+ import {TAGS as bioTAGS, ALPHABET} from '@datagrok-libraries/bio/src/utils/macromolecule';
11
8
  import {GAP_SYMBOL} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
12
9
  import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types';
13
10
  import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
14
11
  import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
15
12
 
16
13
  import '../../css/composition-analysis.css';
14
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
17
15
 
18
- export function getCompositionAnalysisWidget(val: DG.SemanticValue, monomerLib: IMonomerLibBase): DG.Widget {
16
+ export function getCompositionAnalysisWidget(
17
+ val: DG.SemanticValue, monomerLib: IMonomerLibBase, seqHelper: ISeqHelper
18
+ ): DG.Widget {
19
19
  const host = ui.div();
20
20
  host.classList.add('macromolecule-cell-comp-analysis-host');
21
21
  const alphabet = val.cell.column.tags[bioTAGS.alphabet];
22
22
  const biotype = alphabet === ALPHABET.DNA || alphabet === ALPHABET.RNA ? HelmTypes.NUCLEOTIDE : HelmTypes.AA;
23
23
 
24
24
  const counts: { [m: string]: number } = {};
25
- const sh = SeqHandler.forColumn(val.cell.column as DG.Column<string>);
25
+ const sh = seqHelper.getSeqHandler(val.cell.column as DG.Column<string>);
26
26
  const rowIdx = val.cell.rowIndex;
27
27
  const seqSS = sh.getSplitted(rowIdx);
28
28
  wu.count(0).take(seqSS.length).filter((posIdx) => !seqSS.isGap(posIdx)).forEach((posIdx) => {
@@ -2,13 +2,13 @@ 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 {getMolfilesFromSingleSeq} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
6
5
  import {TAGS as mmcrTAGS} from '@datagrok-libraries/bio/src/utils/cell-renderer';
7
6
 
8
7
  import {MmcrTemps, rendererSettingsChangedState} from '@datagrok-libraries/bio/src/utils/cell-renderer-consts';
8
+ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
9
+ import {getMolfilesFromSingleSeq} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
9
10
 
10
11
  import {_package} from '../package';
11
- import {max} from 'rxjs/operators';
12
12
 
13
13
 
14
14
  /**
@@ -105,16 +105,19 @@ export function getMacromoleculeColumnPropertyPanel(col: DG.Column): DG.Widget {
105
105
  * @export
106
106
  * @param {DG.Cell} macroMolecule macromolecule cell.
107
107
  * @param {any[]} monomersLibObject
108
+ * @param {ISeqHelper} seqHelper
108
109
  * @return {Promise<DG.Widget>} Widget.
109
110
  */
110
- export async function representationsWidget(macroMolecule: DG.Cell, monomersLibObject: any[]): Promise<DG.Widget> {
111
+ export async function representationsWidget(
112
+ macroMolecule: DG.Cell, monomersLibObject: any[], seqHelper: ISeqHelper
113
+ ): Promise<DG.Widget> {
111
114
  const pi = DG.TaskBarProgressIndicator.create('Creating 3D view');
112
115
 
113
116
  let widgetHost;
114
117
  let molBlock3D = '';
115
118
  try {
116
119
  try {
117
- const _atomicCodes = getMolfilesFromSingleSeq(macroMolecule, monomersLibObject);
120
+ const _atomicCodes = getMolfilesFromSingleSeq(macroMolecule, monomersLibObject, seqHelper);
118
121
  const result = '';//await getMacroMol(atomicCodes!);
119
122
  const molBlock2D = result[0];
120
123
  molBlock3D = (await grok.functions.call('Bio:Embed', {molBlock2D})) as unknown as string;
@@ -1,37 +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 {category, test} from '@datagrok-libraries/utils/src/test';
6
- import {ALIGNMENT, ALPHABET, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
-
8
- import {_testNeg, _testPos, DetectorTestData, DfReaderFunc, PosCol} from './utils/detectors-utils';
9
-
10
- category('detectors: custom', () => {
11
- const tests: DetectorTestData = {
12
- 'cyclized1': {
13
- csv: `n,seq
14
- 1,R-F-C(1)-T-G-H-F-Y-G-H-F-Y-G-H-F-Y-P-C(1)-meI
15
- 2,C(1)-T-G-H-F-Y-P-C(1)-meI
16
- 3,R-F-C(1)-T-G-H-F-Y-P-C(1)
17
- 4,C(1)-T-G-H-F-H-P-C(1)
18
- 5,R-F-D(2)-T-G-H-F-Y-P-NH2(2)
19
- 6,R-F-aG(3)-T-G-H-F-Y-P-azG(3)-meI`,
20
- pos: {'seq': new PosCol(NOTATION.CUSTOM, ALIGNMENT.SEQ, ALPHABET.UN, 13, true, '-')}
21
- },
22
- };
23
-
24
- for (const [testName, testData] of Object.entries(tests)) {
25
- test(`${testName}`, async () => {
26
- const reader: DfReaderFunc = async (): Promise<DG.DataFrame> => {
27
- return DG.DataFrame.fromCsv(testData.csv);
28
- };
29
- for (const negColName of testData.neg ?? [])
30
- await _testNeg(reader, negColName);
31
- for (const [posColName, posCol] of Object.entries(testData.pos ?? {})) {
32
- await _testPos(reader, posColName, posCol.units, posCol.aligned,
33
- posCol.alphabet, posCol.alphabetSize, posCol.alphabetIsMultichar, posCol.separator);
34
- }
35
- });
36
- }
37
- });