@datagrok/bio 2.13.2 → 2.13.3

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": "Aleksandr Tanas",
6
6
  "email": "atanas@datagrok.ai"
7
7
  },
8
- "version": "2.13.2",
8
+ "version": "2.13.3",
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",
@@ -13,30 +13,23 @@
13
13
  "directory": "packages/Bio"
14
14
  },
15
15
  "properties": [
16
- {
17
- "name": "MonomerWidthMode",
18
- "propertyType": "string",
19
- "choices": [
20
- "short",
21
- "long"
22
- ],
23
- "defaultValue": "short",
24
- "nullable": false
25
- },
26
16
  {
27
17
  "name": "MaxMonomerLength",
28
- "propertyType": "int",
29
- "defaultValue": 4,
18
+ "description": "The max length of monomer symbol displayed without shortening, 'long' to no limit",
19
+ "propertyType": "string",
20
+ "defaultValue": "4",
30
21
  "nullable": false
31
22
  },
32
23
  {
33
24
  "name": "TooltipWebLogo",
25
+ "description": "Display WebLogo in a Macromolecule column header tooltip",
34
26
  "propertyType": "bool",
35
27
  "defaultValue": "true",
36
28
  "nullable": false
37
29
  },
38
30
  {
39
31
  "name": "DefaultSeparator",
32
+ "description": "Default separator using to convert sequences into separator notation",
40
33
  "propertyType": "string",
41
34
  "defaultValue": ".",
42
35
  "nullable": false
@@ -4,7 +4,7 @@ import * as ui from 'datagrok-api/ui';
4
4
 
5
5
  import {Observable, Subject} from 'rxjs';
6
6
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
7
- import {MonomerWidthMode} from './utils/cell-renderer-consts';
7
+ import {Group} from 'datagrok-api/dg';
8
8
 
9
9
  /** Names of package properties/settings declared in properties section of {@link './package.json'} */
10
10
  export const enum BioPackagePropertiesNames {
@@ -19,22 +19,15 @@ export class BioPackageProperties extends Map<string, any> {
19
19
  private _onPropertyChanged: Subject<string> = new Subject<string>();
20
20
  public get onPropertyChanged(): Observable<string> { return this._onPropertyChanged; }
21
21
 
22
- public get MonomerWidthMode(): MonomerWidthMode {
23
- return super.get(BioPackagePropertiesNames.MonomerWidthMode) as MonomerWidthMode;
22
+ /** Monomer symbol maximum length displayed, null for unlimited. */
23
+ public get MaxMonomerLength(): number | null {
24
+ const vs = super.get(BioPackagePropertiesNames.MaxMonomerLength);
25
+ return vs === 'long' ? null : parseInt(vs);
24
26
  }
25
27
 
26
- public set MonomerWidthMode(value: MonomerWidthMode) {
27
- super.set(BioPackagePropertiesNames.MonomerWidthMode, value);
28
- this._onPropertyChanged.next(BioPackagePropertiesNames.MonomerWidthMode);
29
- }
30
-
31
- /** Monomer name maximum length displayed in short mode. */
32
- public get MaxMonomerLength(): number {
33
- return super.get(BioPackagePropertiesNames.MaxMonomerLength) as number;
34
- }
35
-
36
- public set MaxMonomerLength(value: number) {
37
- super.set(BioPackagePropertiesNames.MaxMonomerLength, value);
28
+ public set MaxMonomerLength(value: number | null) {
29
+ const vs = value === null ? 'long' : value.toString();
30
+ super.set(BioPackagePropertiesNames.MaxMonomerLength, vs);
38
31
  this._onPropertyChanged.next(BioPackagePropertiesNames.MaxMonomerLength);
39
32
  }
40
33
 
package/src/package.ts CHANGED
@@ -77,6 +77,7 @@ import {generateLongSequence, generateLongSequence2} from '@datagrok-libraries/b
77
77
  import {CyclizedNotationProvider} from './utils/cyclized';
78
78
  import {getMolColumnFromHelm} from './utils/helm-to-molfile/utils';
79
79
  import {PackageSettingsEditorWidget} from './widgets/package-settings-editor-widget';
80
+ import {getUserLibSettings, setUserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
80
81
 
81
82
  export const _package = new BioPackage();
82
83
 
@@ -115,6 +116,12 @@ export async function initBio() {
115
116
  await Promise.all([
116
117
  (async () => {
117
118
  const monomerLibManager = await MonomerLibManager.getInstance();
119
+ // Fix user lib settings for explicit stuck from a terminated test
120
+ const libSettings = await getUserLibSettings();
121
+ if (libSettings.explicit) {
122
+ libSettings.explicit = [];
123
+ await setUserLibSettings(libSettings);
124
+ }
118
125
  await monomerLibManager.loadLibraries();
119
126
  monomerLib = monomerLibManager.getBioLib();
120
127
  })(),
@@ -291,16 +298,16 @@ export function SeqActivityCliffsEditor(call: DG.FuncCall) {
291
298
 
292
299
  // -- Package settings editor --
293
300
 
294
- //name: packageSettingsEditor
295
- //description: The database connection
296
- //tags: packageSettingsEditor
297
- //input: object propList
298
- //output: widget result
299
- export function packageSettingsEditor(propList: DG.Property[]): DG.Widget {
300
- const widget = new PackageSettingsEditorWidget(propList);
301
- widget.init().then(); // Ignore promise returned
302
- return widget as DG.Widget;
303
- }
301
+ // //name: packageSettingsEditor
302
+ // //description: The database connection
303
+ // //tags: packageSettingsEditor
304
+ // //input: object propList
305
+ // //output: widget result
306
+ // export function packageSettingsEditor(propList: DG.Property[]): DG.Widget {
307
+ // const widget = new PackageSettingsEditorWidget(propList);
308
+ // widget.init().then(); // Ignore promise returned
309
+ // return widget as DG.Widget;
310
+ // }
304
311
 
305
312
  // -- Cell renderers --
306
313
 
@@ -2,33 +2,25 @@ 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
- export enum MonomerWidthMode {
6
- long = 'long',
7
- short = 'short',
8
- }
9
-
10
- export const enum Tags {
11
- RendererSettingsChanged = '.mm.cellRenderer.settingsChanged',
12
- }
13
-
14
5
  export const rendererSettingsChangedState = {
15
6
  true: '1',
16
7
  false: '0',
17
8
  };
18
9
 
19
10
  export const enum Temps {
20
- monomerWidth = '.mm.cellRenderer.monomerWidth',
11
+ maxMonomerLength = '.mm.cellRenderer.maxMonomerLength',
21
12
  colorCode = '.mm.cellRenderer.colorCode',
22
13
  compareWithCurrent = '.mm.cellRenderer.compareWithCurrent',
23
14
  highlightDifference = '.mm.cellRenderer.highlightDifference',
24
15
  gapLength = '.mm.cellRenderer.gapLength',
25
16
  monomerPlacer = '.mm.cellRenderer.monomerPlacer',
17
+
18
+ rendererSettingsChanged = '.mm.cellRenderer.settingsChanged',
26
19
  }
27
20
 
28
21
  export const enum tempTAGS {
29
22
  referenceSequence = 'reference-sequence',
30
23
  currentWord = 'current-word',
31
- monomerWidthMode = 'monomer-width-mode',
32
24
  }
33
25
 
34
26
  // export const MacromoleculeCellRendererDefaults = new class {
@@ -25,8 +25,8 @@ import {alphabetPolymerTypes, IMonomerLib} from '@datagrok-libraries/bio/src/typ
25
25
  import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
26
26
 
27
27
  import {
28
- Temps as mmcrTemps, Tags as mmcrTags,
29
- tempTAGS, rendererSettingsChangedState, MonomerWidthMode
28
+ Temps as mmcrTemps,
29
+ tempTAGS, rendererSettingsChangedState, Temps
30
30
  } from '../utils/cell-renderer-consts';
31
31
  import * as C from './constants';
32
32
 
@@ -152,18 +152,16 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
152
152
 
153
153
  let gapLength = 0;
154
154
  const msaGapLength = 8;
155
- let maxLengthOfMonomer = 50; // in case of long monomer representation, do not limit max length
156
155
 
157
156
  // Cell renderer settings
158
- const tempMonomerWidth: string | null = tableColTemp[tempTAGS.monomerWidthMode];
159
- const monomerWidth: string = (tempMonomerWidth != null) ? tempMonomerWidth :
160
- (_package.properties?.MonomerWidthMode ?? MonomerWidthMode.short);
161
- if (monomerWidth === 'short') {
162
- // Renderer can start to work before Bio package initialized, in that time _package.properties is null.
163
- // TODO: Render function is available but package init method is not completed
164
- const tagMaxMonomerLength: number = parseInt(tableCol.getTag(mmcrTAGS.maxMonomerLength));
165
- maxLengthOfMonomer =
166
- (!isNaN(tagMaxMonomerLength) ? tagMaxMonomerLength : _package.properties?.MaxMonomerLength) ?? 4;
157
+ let maxLengthOfMonomer: number = (_package.properties ? _package.properties.MaxMonomerLength : 4) ?? 50;
158
+ if (mmcrTAGS.maxMonomerLength in tableCol.tags) {
159
+ const v = parseInt(tableCol.getTag(mmcrTAGS.maxMonomerLength));
160
+ maxLengthOfMonomer = !isNaN(v) && v ? v : 50;
161
+ }
162
+ if (Temps.maxMonomerLength in tableColTemp) {
163
+ const v = tableColTemp[Temps.maxMonomerLength];
164
+ maxLengthOfMonomer = !isNaN(v) && v ? v : 50;
167
165
  }
168
166
 
169
167
  const [_gc, _tc, temp] =
@@ -184,7 +182,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
184
182
  g.save();
185
183
  try {
186
184
  if (
187
- tableCol.tags[mmcrTags.RendererSettingsChanged] === rendererSettingsChangedState.true ||
185
+ tableCol.temp[Temps.rendererSettingsChanged] === rendererSettingsChangedState.true ||
188
186
  seqColTemp.monomerLengthLimit != maxLengthOfMonomer
189
187
  ) {
190
188
  gapLength = tableColTemp[mmcrTemps.gapLength] as number ?? gapLength;
@@ -192,7 +190,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
192
190
  // particularly monomer representation and max width.
193
191
  seqColTemp.setMonomerLengthLimit(maxLengthOfMonomer);
194
192
  seqColTemp.setSeparatorWidth(seqColTemp.isMsa() ? msaGapLength : gapLength);
195
- tableCol.setTag(mmcrTags.RendererSettingsChanged, rendererSettingsChangedState.false);
193
+ tableCol.temp[Temps.rendererSettingsChanged] = rendererSettingsChangedState.false;
196
194
  }
197
195
 
198
196
  const [maxLengthWords, maxLengthWordsSum]: [number[], number[]] =
@@ -1,10 +1,9 @@
1
1
  import * as ui from 'datagrok-api/ui';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
 
4
- import {MonomerWidthMode} from '../utils/cell-renderer-consts';
5
-
6
4
  import {_package} from '../package';
7
5
 
6
+
8
7
  export class PackageSettingsEditorWidget extends DG.Widget {
9
8
  maxMonomerLengthProp: DG.Property;
10
9
  tooltipWebLogo: DG.Property;
@@ -22,34 +21,35 @@ export class PackageSettingsEditorWidget extends DG.Widget {
22
21
  }
23
22
 
24
23
  async init(): Promise<void> {
25
- const monomerWidthModeInput = ui.choiceInput('Monomer width mode',
26
- _package.properties.MonomerWidthMode,
27
- [MonomerWidthMode.short, MonomerWidthMode.long],
28
- (value: MonomerWidthMode) => {
29
- _package.properties.MonomerWidthMode = value;
30
- });
31
-
32
- const maxMonomerLengthInput = ui.intInput('Max monomer length',
33
- _package.properties.MaxMonomerLength,
34
- (value: number) => {
24
+ const maxMonomerLengthInput = ui.input.int('Max Monomer Length', {
25
+ value: _package.properties.MaxMonomerLength!,
26
+ nullable: true, min: 0,
27
+ onValueChanged: () => {
35
28
  // Handle user changed value
36
- _package.properties.MaxMonomerLength = value;
37
- });
38
-
39
- const tooltipWebLogoInput = ui.boolInput('Tooltip WebLogo',
40
- _package.properties.TooltipWebLogo,
41
- (value: boolean) => {
42
- _package.properties.TooltipWebLogo = value;
43
- });
44
-
45
- const defaultSeparatorInput = ui.choiceInput('Default Separator',
46
- _package.properties.DefaultSeparator, ['.', '/', '-'],
47
- (value: string) => {
48
- _package.properties.DefaultSeparator = value;
49
- });
29
+ _package.properties.MaxMonomerLength = maxMonomerLengthInput.value ?? null;
30
+ },
31
+ tooltipText: this.maxMonomerLengthProp.description,
32
+ });
33
+
34
+ const tooltipWebLogoInput = ui.input.bool('Tooltip WebLogo', {
35
+ value: _package.properties.TooltipWebLogo,
36
+ nullable: false,
37
+ onValueChanged: () => {
38
+ _package.properties.TooltipWebLogo = tooltipWebLogoInput.value;
39
+ },
40
+ tooltipText: this.tooltipWebLogo.description,
41
+ });
42
+
43
+ const defaultSeparatorInput = ui.input.choice('Default Separator', {
44
+ value: _package.properties.DefaultSeparator,
45
+ items: ['.', '/', '-'],
46
+ onValueChanged: () => {
47
+ _package.properties.DefaultSeparator = defaultSeparatorInput.value;
48
+ },
49
+ tooltipText: this.defaultSeparator.description,
50
+ });
50
51
 
51
52
  this.root.appendChild(ui.form([
52
- monomerWidthModeInput,
53
53
  maxMonomerLengthInput,
54
54
  tooltipWebLogoInput,
55
55
  defaultSeparatorInput,
@@ -6,11 +6,11 @@ import {getMolfilesFromSingleSeq} from '@datagrok-libraries/bio/src/monomer-work
6
6
  import {TAGS as mmcrTAGS} from '@datagrok-libraries/bio/src/utils/cell-renderer';
7
7
 
8
8
  import {
9
- Tags as mmcrTags, Temps as mmcrTemps, MonomerWidthMode,
10
- tempTAGS, rendererSettingsChangedState
9
+ Temps as mmcrTemps, rendererSettingsChangedState, Temps
11
10
  } from '../utils/cell-renderer-consts';
12
11
 
13
12
  import {_package} from '../package';
13
+ import {max} from 'rxjs/operators';
14
14
 
15
15
 
16
16
  /**
@@ -25,81 +25,77 @@ export function getMacromoleculeColumnPropertyPanel(col: DG.Column): DG.Widget {
25
25
  const columnsSet = new Set(columnsList);
26
26
  columnsSet.delete(col.name);
27
27
 
28
- const monomerWidthModeInput = ui.input.choice('Monomer width', {
29
- value: (col?.temp[tempTAGS.monomerWidthMode] != null) ? col.temp[tempTAGS.monomerWidthMode] :
30
- (_package.properties?.MonomerWidthMode ?? MonomerWidthMode.short),
31
- items: [MonomerWidthMode.short, MonomerWidthMode.long],
28
+ let maxMonomerLength: number | null = (_package.properties ? _package.properties.MaxMonomerLength : 4);
29
+ if (mmcrTAGS.maxMonomerLength in col.tags) {
30
+ const v = parseInt(col.getTag(mmcrTAGS.maxMonomerLength));
31
+ maxMonomerLength = !isNaN(v) ? v : maxMonomerLength;
32
+ }
33
+ if (Temps.maxMonomerLength in col.temp) {
34
+ const v = parseInt(col.temp[Temps.maxMonomerLength]);
35
+ maxMonomerLength = !isNaN(v) ? v : maxMonomerLength;
36
+ }
37
+ const maxMonomerLengthInput = ui.input.int('Max Monomer Length', {
38
+ value: maxMonomerLength!,
39
+ nullable: true, min: 1, max: 50, step: 1,
32
40
  onValueChanged: () => {
33
- const s = monomerWidthModeInput.value;
34
- col.temp[tempTAGS.monomerWidthMode] = s;
35
- col.setTag(mmcrTags.RendererSettingsChanged, rendererSettingsChangedState.true);
36
- col.dataFrame.fireValuesChanged();
37
-
38
- maxMonomerLengthInput.enabled = monomerWidthModeInput.value === MonomerWidthMode.short;
41
+ if (maxMonomerLengthInput.value == 0)
42
+ setTimeout(() => { maxMonomerLengthInput.value = null!; }, 0);
43
+ else {
44
+ const value = maxMonomerLengthInput.value ?? '';
45
+ const tagValue = value == null ? '' : value.toString();
46
+ col.temp[Temps.maxMonomerLength] = tagValue;
47
+ col.temp[Temps.rendererSettingsChanged] = rendererSettingsChangedState.true;
48
+ col.dataFrame.fireValuesChanged();
49
+ }
39
50
  },
51
+ tooltipText: `The max length of monomer symbol displayed without shortening, empty to no limit`
40
52
  });
41
- monomerWidthModeInput.setTooltip(
42
- `In short mode, only the 'Max monomer length' characters are displayed, followed by .. if there are more`);
43
-
44
- const tagMaxMonomerLength: number = parseInt(col.getTag(mmcrTAGS.maxMonomerLength));
45
- const maxMonomerLengthInput = ui.input.slider('Max monomer length', {
46
- value: !isNaN(tagMaxMonomerLength) ? tagMaxMonomerLength :
47
- (_package.properties?.MaxMonomerLength ?? 4),
48
- min: 1, max: 16, step: 1,
53
+
54
+ const gapLengthInput = ui.input.int('Monomer Margin', {
55
+ value: col.temp[mmcrTemps.gapLength] ?? 0,
49
56
  onValueChanged: () => {
50
- const value = maxMonomerLengthInput.value;
51
- maxMonomerLengthValueDiv.innerText = maxMonomerLengthInput.stringValue;
52
- col.setTag(mmcrTAGS.maxMonomerLength, value.toString());
53
- col.setTag(mmcrTags.RendererSettingsChanged, rendererSettingsChangedState.true);
57
+ col.temp[mmcrTemps.gapLength] = gapLengthInput.value;
58
+ col.temp[mmcrTemps.rendererSettingsChanged] = rendererSettingsChangedState.true;
54
59
  col.dataFrame.fireValuesChanged();
55
60
  },
61
+ tooltipText: 'The size of margin between monomers (in pixels)'
56
62
  });
57
- const maxMonomerLengthValueDiv = ui.divText(maxMonomerLengthInput.stringValue, 'ui-input-description');
58
- maxMonomerLengthInput.addOptions(maxMonomerLengthValueDiv);
59
- maxMonomerLengthInput.setTooltip(
60
- `The max length of monomer name displayed without shortening ` +
61
- ` in '${MonomerWidthMode.short}' monomer width mode.`);
62
- maxMonomerLengthInput.enabled = monomerWidthModeInput.value === MonomerWidthMode.short;
63
-
64
- const gapLengthInput = ui.intInput('Monomer margin', col.temp[mmcrTemps.gapLength] ?? 0,
65
- (value: number) => {
66
- col.temp[mmcrTemps.gapLength] = value;
67
- col.setTag(mmcrTags.RendererSettingsChanged, rendererSettingsChangedState.true);
68
- col.dataFrame.fireValuesChanged();
69
- });
70
- gapLengthInput.setTooltip('The size of margin between monomers (in pixels)');
71
63
 
72
- const colorCode = ui.boolInput('Color code',
73
- (col?.temp['color-code'] != null) ? col.temp['color-code'] : true,
74
- (v: boolean) => {
75
- col.temp['color-code'] = v;
64
+ const colorCodeInput = ui.input.bool('Color Code', {
65
+ value: (col?.temp['color-code'] != null) ? col.temp['color-code'] : true,
66
+ onValueChanged: () => {
67
+ col.temp['color-code'] = colorCodeInput.value;
76
68
  col.dataFrame.fireValuesChanged();
77
- });
78
- colorCode.setTooltip('Color code');
69
+ },
70
+ tooltipText: 'Color code'
71
+ });
79
72
 
80
- const referenceSequence = ui.stringInput('Reference sequence',
81
- (col?.temp['reference-sequence'] != null) ? col?.temp['reference-sequence'] : '', (v: string) => {
82
- col.temp['reference-sequence'] = v;
73
+ const referenceSequenceInput = ui.input.string('Reference Sequence', {
74
+ value: (col?.temp['reference-sequence'] != null) ? col?.temp['reference-sequence'] : '',
75
+ nullable: true,
76
+ onValueChanged: () => {
77
+ col.temp['reference-sequence'] = referenceSequenceInput.value;
83
78
  col.dataFrame.fireValuesChanged();
84
- });
85
- referenceSequence.setTooltip('Reference sequence is not empty, then the sequence will be render ' + '\n' +
86
- 'as a difference from the reference sequence');
87
-
88
- const compareWithCurrent = ui.boolInput('Compare with current',
89
- (col?.temp['compare-with-current'] != null) ? col.temp['compare-with-current'] : true,
90
- (v: boolean) => {
91
- col.temp['compare-with-current'] = v;
79
+ },
80
+ tooltipText: 'Reference sequence is not empty, then the sequence will be render ' + '\n' +
81
+ 'as a difference from the reference sequence'
82
+ });
83
+
84
+ const compareWithCurrentInput = ui.input.bool('Compare with current', {
85
+ value: (col?.temp['compare-with-current'] != null) ? col.temp['compare-with-current'] : true,
86
+ onValueChanged: () => {
87
+ col.temp['compare-with-current'] = compareWithCurrentInput.value;
92
88
  col.dataFrame.fireValuesChanged();
93
- });
94
- compareWithCurrent.setTooltip('When on, all sequences get rendered in the "diff" mode');
89
+ },
90
+ tooltipText: 'When on, all sequences get rendered in the "diff" mode'
91
+ });
95
92
 
96
93
  const rdKitInputs = ui.inputs([
97
- monomerWidthModeInput,
98
94
  maxMonomerLengthInput,
99
95
  gapLengthInput,
100
- referenceSequence,
101
- colorCode,
102
- compareWithCurrent,
96
+ referenceSequenceInput,
97
+ colorCodeInput,
98
+ compareWithCurrentInput,
103
99
  ]);
104
100
 
105
101
  return new DG.Widget(rdKitInputs);
package/webpack.config.js CHANGED
@@ -31,7 +31,7 @@ module.exports = {
31
31
  plugins: [
32
32
  new FuncGeneratorPlugin({outputPath: './src/package.g.ts'}),
33
33
  ],
34
- devtool: mode !== 'production' ? 'inline-source-map' : 'source-map',
34
+ devtool: 'source-map',
35
35
  externals: {
36
36
  'datagrok-api/dg': 'DG',
37
37
  'datagrok-api/grok': 'grok',