@datagrok/bio 2.7.2 → 2.8.1

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
@@ -5,7 +5,7 @@
5
5
  "name": "Leonid Stolbov",
6
6
  "email": "lstolbov@datagrok.ai"
7
7
  },
8
- "version": "2.7.2",
8
+ "version": "2.8.1",
9
9
  "description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
10
10
  "repository": {
11
11
  "type": "git",
@@ -24,14 +24,20 @@
24
24
  "propertyType": "bool",
25
25
  "defaultValue": "true",
26
26
  "nullable": false
27
+ },
28
+ {
29
+ "name": "DefaultSeparator",
30
+ "propertyType": "string",
31
+ "defaultValue": ".",
32
+ "nullable": false
27
33
  }
28
34
  ],
29
35
  "dependencies": {
30
36
  "@biowasm/aioli": "^3.1.0",
31
- "@datagrok-libraries/bio": "^5.33.2",
37
+ "@datagrok-libraries/bio": "^5.34.0",
32
38
  "@datagrok-libraries/chem-meta": "^1.0.1",
33
39
  "@datagrok-libraries/ml": "^6.3.39",
34
- "@datagrok-libraries/tutorials": "^1.3.2",
40
+ "@datagrok-libraries/tutorials": "^1.3.6",
35
41
  "@datagrok-libraries/utils": "^4.0.17",
36
42
  "cash-dom": "^8.0.0",
37
43
  "css-loader": "^6.7.3",
@@ -9,6 +9,7 @@ import {ObjectPropertyBag} from 'datagrok-api/dg';
9
9
  export const enum BioPackagePropertiesNames {
10
10
  MaxMonomerLength = 'MaxMonomerLength',
11
11
  TooltipWebLogo = 'TooltipWebLogo',
12
+ DefaultSeparator = 'DefaultSeparator',
12
13
  }
13
14
 
14
15
 
@@ -18,24 +19,34 @@ export class BioPackageProperties extends Map<string, any> {
18
19
  public get onPropertyChanged(): Observable<string> { return this._onPropertyChanged; }
19
20
 
20
21
  /** Monomer name maximum length displayed in short mode. */
21
- public get maxMonomerLength(): number {
22
- return super.get(BioPackagePropertiesNames.MaxMonomerLength) as unknown as number;
22
+ public get MaxMonomerLength(): number {
23
+ return super.get(BioPackagePropertiesNames.MaxMonomerLength) as number;
23
24
  }
24
25
 
25
- public set maxMonomerLength(value: number) {
26
- super.set(BioPackagePropertiesNames.MaxMonomerLength, value as unknown as object);
26
+ public set MaxMonomerLength(value: number) {
27
+ super.set(BioPackagePropertiesNames.MaxMonomerLength, value);
27
28
  this._onPropertyChanged.next(BioPackagePropertiesNames.MaxMonomerLength);
28
29
  }
29
30
 
30
- public get tooltipWebLogo(): boolean {
31
- return super.get(BioPackagePropertiesNames.TooltipWebLogo) as unknown as boolean;
31
+ public get TooltipWebLogo(): boolean {
32
+ return super.get(BioPackagePropertiesNames.TooltipWebLogo) as boolean;
32
33
  }
33
34
 
34
- public set tooltipWebLogo(value: boolean) {
35
- super.set(BioPackagePropertiesNames.TooltipWebLogo, value as unknown as boolean);
35
+ public set TooltipWebLogo(value: boolean) {
36
+ super.set(BioPackagePropertiesNames.TooltipWebLogo, value);
36
37
  this._onPropertyChanged.next(BioPackagePropertiesNames.TooltipWebLogo);
37
38
  }
38
39
 
40
+ public get DefaultSeparator(): string {
41
+ return super.get(BioPackagePropertiesNames.DefaultSeparator) as string;
42
+ }
43
+
44
+ public set DefaultSeparator(value: string) {
45
+ if (value.length !== 1) throw new Error('The separator must be of length one.');
46
+ super.set(BioPackagePropertiesNames.DefaultSeparator, value);
47
+ this._onPropertyChanged.next(BioPackagePropertiesNames.DefaultSeparator);
48
+ }
49
+
39
50
  constructor(source: any) {
40
51
  super(Object.entries(source));
41
52
  }
package/src/package.ts CHANGED
@@ -64,6 +64,7 @@ import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
64
64
  import {PackageSettingsEditorWidget} from './widgets/package-settings-editor-widget';
65
65
  import {getCompositionAnalysisWidget} from './widgets/composition-analysis-widget';
66
66
  import {MacromoleculeColumnWidget} from './utils/macromolecule-column-widget';
67
+ import {addCopyMenuUI} from './utils/context-menu';
67
68
 
68
69
  export const _package = new BioPackage();
69
70
 
@@ -264,7 +265,7 @@ export function SeqActivityCliffsEditor(call: DG.FuncCall) {
264
265
 
265
266
  //top-menu: Bio | Analyze | Activity Cliffs...
266
267
  //name: Sequence Activity Cliffs
267
- //description: detect activity cliffs
268
+ //description: Detects pairs of molecules with similar structure and significant difference in any given property
268
269
  //input: dataframe table [Input data table]
269
270
  //input: column molecules {semType: Macromolecule}
270
271
  //input: column activities
@@ -358,6 +359,7 @@ export function SequenceSpaceEditor(call: DG.FuncCall) {
358
359
 
359
360
  //top-menu: Bio | Analyze | Sequence Space...
360
361
  //name: Sequence Space
362
+ //description: Creates 2D sequence space with projected sequences by pairwise distance
361
363
  //input: dataframe table
362
364
  //input: column molecules { semType: Macromolecule }
363
365
  //input: string methodName { choices:["UMAP", "t-SNE"] }
@@ -456,7 +458,7 @@ export async function sequenceSpaceTopMenu(
456
458
 
457
459
  //top-menu: Bio | Convert | To Atomic Level...
458
460
  //name: To Atomic Level
459
- //description: returns molfiles for each monomer from HELM library
461
+ //description: Converts sequences to molblocks
460
462
  //input: dataframe df [Input data table]
461
463
  //input: column macroMolecule {semType: Macromolecule}
462
464
  export async function toAtomicLevel(df: DG.DataFrame, macroMolecule: DG.Column): Promise<void> {
@@ -479,6 +481,7 @@ export async function toAtomicLevel(df: DG.DataFrame, macroMolecule: DG.Column):
479
481
 
480
482
  //top-menu: Bio | Analyze | MSA...
481
483
  //name: MSA
484
+ //description: Performs multiple sequence alignment
482
485
  //tags: bio, panel
483
486
  export function multipleSequenceAlignmentDialog(): void {
484
487
  multipleSequenceAlignmentUI();
@@ -497,6 +500,7 @@ export async function alignSequences(sequenceCol: DG.Column<string> | null = nul
497
500
 
498
501
  //top-menu: Bio | Analyze | Composition
499
502
  //name: Composition Analysis
503
+ //description: Visualizes sequence composition on a WebLogo plot
500
504
  //meta.icon: files/icons/composition-analysis.svg
501
505
  //output: viewer result
502
506
  export async function compositionAnalysis(): Promise<void> {
@@ -704,7 +708,7 @@ export function similaritySearchViewer(): SequenceSimilarityViewer {
704
708
 
705
709
  //top-menu: Bio | Search | Similarity
706
710
  //name: similaritySearch
707
- //description: finds the most similar sequence
711
+ //description: Finds similar sequences
708
712
  //output: viewer result
709
713
  export function similaritySearchTopMenu(): void {
710
714
  const view = (grok.shell.v as DG.TableView);
@@ -722,7 +726,7 @@ export function diversitySearchViewer(): SequenceDiversityViewer {
722
726
 
723
727
  //top-menu: Bio | Search | Diversity
724
728
  //name: diversitySearch
725
- //description: finds the most diverse molecules
729
+ //description: Finds the most diverse sequences
726
730
  //output: viewer result
727
731
  export function diversitySearchTopMenu() {
728
732
  const view = (grok.shell.v as DG.TableView);
@@ -732,6 +736,7 @@ export function diversitySearchTopMenu() {
732
736
 
733
737
  //top-menu: Bio | Search | Substructure...
734
738
  //name: bioSubstructureSearch
739
+ //description: Finds sequence with the given subsequence
735
740
  export function bioSubstructureSearch(): void {
736
741
  const col = getMacromoleculeColumn();
737
742
  substructureSearchDialog(col);
@@ -768,6 +773,14 @@ export async function webLogoLargeApp(): Promise<void> {
768
773
  }
769
774
  }
770
775
 
776
+ // -- Handle context menu --
777
+
778
+ ///name: addCopyMenu
779
+ //input: object cell
780
+ //input: object menu
781
+ export function addCopyMenu(cell: DG.Cell, menu: DG.Menu): void {
782
+ addCopyMenuUI(cell, menu);
783
+ }
771
784
 
772
785
  // -- Demo --
773
786
 
@@ -129,7 +129,7 @@ RNA1{P.R(U)P.R(U)P.R(C)P.R(A)P.R(A)P.R(C)P.P.P}$$$$`,
129
129
  return df;
130
130
  }
131
131
 
132
- function converter(tgtNotation: NOTATION, tgtSeparator: string | null = null): ConverterFunc {
132
+ function converter(tgtNotation: NOTATION, tgtSeparator?: string): ConverterFunc {
133
133
  if (tgtNotation === NOTATION.SEPARATOR && !tgtSeparator)
134
134
  throw new Error(`Argument 'separator' is mandatory for target notation '${tgtNotation.toString()}'.`);
135
135
 
@@ -141,12 +141,12 @@ RNA1{P.R(U)P.R(U)P.R(C)P.R(A)P.R(A)P.R(C)P.P.P}$$$$`,
141
141
  };
142
142
  }
143
143
 
144
- async function _testConvert(srcKey: Samples, converter: ConverterFunc, tgtKey: Samples) {
144
+ async function _testConvert(srcKey: Samples, colConverter: ConverterFunc, tgtKey: Samples) {
145
145
  const srcDf: DG.DataFrame = await readCsv(srcKey);
146
146
  const srcCol: DG.Column = srcDf.getCol('seq');
147
147
 
148
148
  // conversion results
149
- const resCol: DG.Column = converter(srcCol);
149
+ const resCol: DG.Column = colConverter(srcCol);
150
150
 
151
151
  // The correct reference data to compare conversion results with.
152
152
  const tgtDf: DG.DataFrame = await readCsv(tgtKey);
@@ -135,7 +135,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
135
135
  const tempMonomerWidth: string | null = tableColTemp[tempTAGS.monomerWidth];
136
136
  const monomerWidth: string = (tempMonomerWidth != null) ? tempMonomerWidth : 'short';
137
137
  if (monomerWidth === 'short')
138
- maxLengthOfMonomer = tableColTemp[mmcrTemps.maxMonomerLength] ?? _package.properties.maxMonomerLength;
138
+ maxLengthOfMonomer = tableColTemp[mmcrTemps.maxMonomerLength] ?? _package.properties.MaxMonomerLength;
139
139
 
140
140
 
141
141
  let seqColTemp: MonomerPlacer = tableCol.temp[tempTAGS.bioSeqCol];
@@ -0,0 +1,30 @@
1
+ import * as grok from 'datagrok-api/grok';
2
+ import * as DG from 'datagrok-api/dg';
3
+ import * as ui from 'datagrok-api/ui';
4
+
5
+ import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
6
+ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
+ import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
8
+
9
+ import {_package} from '../package';
10
+
11
+
12
+ export function addCopyMenuUI(cell: DG.Cell, menu: DG.Menu): void {
13
+ const uh = UnitsHandler.getOrCreate(cell.column);
14
+ const tgtNotationList: string[] = Object.values(NOTATION).filter((v) => v !== uh.units);
15
+
16
+ menu.group('Copy')
17
+ .items(tgtNotationList, (tgtNotation) => {
18
+ const nc = new NotationConverter(cell.column);
19
+ const separator = tgtNotation === NOTATION.SEPARATOR ? _package.properties.DefaultSeparator : undefined;
20
+ const converter = nc.getConverter(tgtNotation as NOTATION, separator);
21
+ const tgtSeq = converter(cell.value);
22
+
23
+ if (!navigator.clipboard) {
24
+ grok.shell.warning('The clipboard functionality requires a secure origin — either HTTPS or localhost');
25
+ } else {
26
+ navigator.clipboard.writeText(tgtSeq);
27
+ grok.shell.info(`Value of notation '${tgtNotation}' copied to clipboard`);
28
+ }
29
+ });
30
+ }
@@ -97,7 +97,7 @@ export function convert(col?: DG.Column): void {
97
97
  ]))
98
98
  .onOK(async () => {
99
99
  const targetNotation = targetNotationInput.value as NOTATION;
100
- const separator: string | null = separatorInput.value;
100
+ const separator: string | undefined = separatorInput.value ?? undefined;
101
101
 
102
102
  await convertDo(tgtCol, targetNotation, separator);
103
103
  })
@@ -116,9 +116,7 @@ export function convert(col?: DG.Column): void {
116
116
  * @param {NOTATION} targetNotation Target notation
117
117
  * @param {string | null} separator Separator for SEPARATOR notation
118
118
  */
119
- export async function convertDo(
120
- srcCol: DG.Column, targetNotation: NOTATION, separator: string | null,
121
- ): Promise<DG.Column> {
119
+ export async function convertDo(srcCol: DG.Column, targetNotation: NOTATION, separator?: string): Promise<DG.Column> {
122
120
  const converter = new NotationConverter(srcCol);
123
121
  const newColumn = converter.convert(targetNotation, separator);
124
122
  srcCol.dataFrame.columns.add(newColumn);
@@ -24,7 +24,7 @@ export class MacromoleculeColumnWidget extends DG.Widget {
24
24
 
25
25
  async init(): Promise<void> {
26
26
  const uh = UnitsHandler.getOrCreate(this.seqCol);
27
- const pkgTooltipWebLogo = _package.properties.tooltipWebLogo;
27
+ const pkgTooltipWebLogo = _package.properties.TooltipWebLogo;
28
28
  const colTooltipWebLogo = this.seqCol.getTag(wlTAGS.tooltipWebLogo);
29
29
 
30
30
  if (pkgTooltipWebLogo !== false && !['false', 'off', 'disable', 'disabled'].includes(colTooltipWebLogo)) {
@@ -63,7 +63,7 @@ export class MonomerCellRenderer extends DG.GridCellRenderer {
63
63
 
64
64
  get defaultHeight(): number { return 15; }
65
65
 
66
- get defaultWidth(): number { return 30; }
66
+ get defaultWidth(): number { return 40; }
67
67
 
68
68
  /**
69
69
  * Cell renderer function.
@@ -95,6 +95,6 @@ export class MonomerCellRenderer extends DG.GridCellRenderer {
95
95
  const color = palette.get(s);
96
96
 
97
97
  g.fillStyle = color;
98
- g.fillText(monomerToShort(s, 3), x + (w / 2), y + (h / 2), w);
98
+ g.fillText(monomerToShort(s, 6), x + (w / 2), y + (h / 2), w);
99
99
  }
100
100
  }
@@ -316,7 +316,8 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
316
316
  this.filterSourceInput.root.style.position = 'absolute';
317
317
  this.filterSourceInput.root.style.left = '10px';
318
318
  this.filterSourceInput.root.style.top = '-3px';
319
- ui.tooltip.bind(this.filterSourceInput.root, 'Check to filter sequences for selected VRs');
319
+ //this.filterSourceInput.setTooltip('Check to filter sequences for selected VRs'); // TODO: GROK-13614
320
+ ui.tooltip.bind(this.filterSourceInput.input, 'Check to filter sequences for selected VRs');
320
321
 
321
322
  const _color: string = `#ffbb${Math.ceil(Math.random() * 255).toString(16)}`;
322
323
  this.host = ui.div([this.mainLayout, this.filterSourceInput!.root],
@@ -6,6 +6,7 @@ import {_package} from '../package';
6
6
  export class PackageSettingsEditorWidget extends DG.Widget {
7
7
  maxMonomerLengthProp: DG.Property;
8
8
  tooltipWebLogo: DG.Property;
9
+ defaultSeparator: DG.Property;
9
10
 
10
11
  constructor(propList: DG.Property[]) {
11
12
  super(ui.div([], {}));
@@ -15,24 +16,33 @@ export class PackageSettingsEditorWidget extends DG.Widget {
15
16
 
16
17
  this.maxMonomerLengthProp = props['MaxMonomerLength'];
17
18
  this.tooltipWebLogo = props['TooltipWebLogo'];
19
+ this.defaultSeparator = props['DefaultSeparator'];
18
20
  }
19
21
 
20
22
  async init(): Promise<void> {
21
23
  const maxMonomerLengthInput = ui.intInput('Max monomer length',
22
- _package.properties.maxMonomerLength,
24
+ _package.properties.MaxMonomerLength,
23
25
  (value: number) => {
24
26
  // Handle user changed value
25
- _package.properties.maxMonomerLength = value;
27
+ _package.properties.MaxMonomerLength = value;
26
28
  });
27
29
 
28
- const tooltipWebLogo = ui.boolInput('Tooltip WebLogo',
29
- _package.properties.tooltipWebLogo,
30
+ const tooltipWebLogoInput = ui.boolInput('Tooltip WebLogo',
31
+ _package.properties.TooltipWebLogo,
30
32
  (value: boolean) => {
31
- _package.properties.tooltipWebLogo = value;
33
+ _package.properties.TooltipWebLogo = value;
34
+ });
35
+
36
+ const defaultSeparatorInput = ui.choiceInput('Default Separator',
37
+ _package.properties.DefaultSeparator, ['.', '/', '-'],
38
+ (value: string) => {
39
+ _package.properties.DefaultSeparator = value;
32
40
  });
33
41
 
34
42
  this.root.appendChild(ui.form([
35
43
  maxMonomerLengthInput,
36
- tooltipWebLogo]));
44
+ tooltipWebLogoInput,
45
+ defaultSeparatorInput,
46
+ ]));
37
47
  }
38
48
  }
@@ -32,7 +32,7 @@ export function getMacromoleculeColumnPropertyPanel(col: DG.Column): DG.Widget {
32
32
  );
33
33
 
34
34
  const maxMonomerLength: DG.InputBase = ui.intInput('Max monomer length',
35
- col.temp[mmcrTemps.maxMonomerLength] ?? _package.properties.maxMonomerLength,
35
+ col.temp[mmcrTemps.maxMonomerLength] ?? _package.properties.MaxMonomerLength,
36
36
  (value: number) => {
37
37
  col.temp[mmcrTemps.maxMonomerLength] = value;
38
38
  col.setTag(mmcrTags.RendererSettingsChanged, rendererSettingsChangedState.true);