@datagrok/bio 2.11.42 → 2.12.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/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/detectors.js +11 -11
- package/dist/36.js +1 -1
- package/dist/36.js.map +1 -1
- package/dist/413.js +1 -1
- package/dist/413.js.map +1 -1
- package/dist/590.js +1 -1
- package/dist/590.js.map +1 -1
- package/dist/709.js +1 -1
- package/dist/709.js.map +1 -1
- package/dist/895.js +1 -1
- package/dist/895.js.map +1 -1
- package/dist/package-test.js +3 -3
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +2 -2
- package/dist/package.js.map +1 -1
- package/files/tests/libraries/HELMmonomerSchema.json +1 -1
- package/package.json +11 -11
- package/src/analysis/sequence-activity-cliffs.ts +9 -9
- package/src/analysis/sequence-diversity-viewer.ts +3 -3
- package/src/analysis/sequence-search-base-viewer.ts +2 -2
- package/src/analysis/sequence-similarity-viewer.ts +10 -10
- package/src/analysis/sequence-space.ts +26 -23
- package/src/calculations/monomerLevelMols.ts +13 -11
- package/src/package.ts +12 -15
- package/src/tests/WebLogo-layout-tests.ts +5 -2
- package/src/tests/WebLogo-positions-test.ts +5 -5
- package/src/tests/bio-tests.ts +13 -6
- package/src/tests/converters-test.ts +4 -4
- package/src/tests/detectors-benchmark-tests.ts +5 -5
- package/src/tests/detectors-tests.ts +13 -13
- package/src/tests/fasta-export-tests.ts +10 -4
- package/src/tests/mm-distance-tests.ts +10 -10
- package/src/tests/msa-tests.ts +8 -15
- package/src/tests/renderers-monomer-placer.ts +3 -3
- package/src/tests/renderers-test.ts +6 -8
- package/src/tests/splitters-test.ts +14 -13
- package/src/tests/substructure-filters-tests.ts +143 -1
- package/src/tests/to-atomic-level-tests.ts +2 -2
- package/src/tests/units-handler-get-region.ts +4 -4
- package/src/tests/units-handler-splitted-tests.ts +19 -17
- package/src/tests/units-handler-tests.ts +32 -32
- package/src/utils/cell-renderer.ts +40 -34
- package/src/utils/check-input-column.ts +5 -5
- package/src/utils/context-menu.ts +9 -6
- package/src/utils/convert.ts +9 -9
- package/src/utils/get-region-func-editor.ts +11 -11
- package/src/utils/get-region.ts +10 -12
- package/src/utils/macromolecule-column-widget.ts +4 -3
- package/src/utils/monomer-lib/library-file-manager/event-manager.ts +1 -1
- package/src/utils/multiple-sequence-alignment-ui.ts +6 -6
- package/src/utils/pepsea.ts +1 -0
- package/src/utils/poly-tool/transformation.ts +3 -3
- package/src/utils/poly-tool/ui.ts +46 -135
- package/src/utils/save-as-fasta.ts +14 -15
- package/src/utils/sequence-to-mol.ts +4 -4
- package/src/viewers/web-logo-viewer.ts +46 -54
- package/src/widgets/bio-substructure-filter-types.ts +19 -45
- package/src/widgets/bio-substructure-filter.ts +45 -23
- package/src/widgets/composition-analysis-widget.ts +8 -8
|
@@ -6,50 +6,24 @@ import {Observable, Subject, Unsubscribable} from 'rxjs';
|
|
|
6
6
|
import {_package} from '../package';
|
|
7
7
|
|
|
8
8
|
export interface IFilterProps {
|
|
9
|
-
get onChanged(): Observable<void>;
|
|
10
|
-
|
|
11
|
-
save(): object;
|
|
12
|
-
apply(propsObj: object): void;
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
/** Fasta and Helm */
|
|
16
12
|
export class BioFilterProps implements IFilterProps {
|
|
17
|
-
private _onChanged: Subject<void> = new Subject<void>();
|
|
18
|
-
|
|
19
|
-
get onChanged(): Observable<void> { return this._onChanged; }
|
|
20
|
-
|
|
21
13
|
constructor(
|
|
22
|
-
public substructure: string
|
|
14
|
+
public readonly substructure: string,
|
|
15
|
+
/** Pass false from an inheritors constructor, at the end set true. */ protected readOnly: boolean = true,
|
|
23
16
|
) {
|
|
24
17
|
return new Proxy(this, {
|
|
25
18
|
set: (target: any, key: string | symbol, value: any) => {
|
|
26
19
|
_package.logger.debug(`BioFilterProps.set ${key.toString()}( '${value}' )`);
|
|
20
|
+
if (this.readOnly)
|
|
21
|
+
throw new Error('Properties are immutable.');
|
|
27
22
|
target[key] = value;
|
|
28
|
-
this._onChanged.next();
|
|
29
23
|
return true;
|
|
30
24
|
}
|
|
31
25
|
});
|
|
32
26
|
}
|
|
33
|
-
|
|
34
|
-
save(): object {
|
|
35
|
-
const propsObj = {};
|
|
36
|
-
for (const [key, value] of Object.entries(this)) {
|
|
37
|
-
if (key !== '_onChanged') {
|
|
38
|
-
// @ts-ignore
|
|
39
|
-
propsObj[key] = this[key];
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return propsObj;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
apply(propsObj: object) {
|
|
46
|
-
for (const [key, value] of Object.entries(this)) {
|
|
47
|
-
if (key !== '_onChanged') {
|
|
48
|
-
// @ts-ignore
|
|
49
|
-
this[key] = propsObj[key];
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
27
|
}
|
|
54
28
|
|
|
55
29
|
export interface IBioFilter {
|
|
@@ -58,6 +32,9 @@ export interface IBioFilter {
|
|
|
58
32
|
get props(): IFilterProps;
|
|
59
33
|
set props(value: IFilterProps);
|
|
60
34
|
|
|
35
|
+
applyProps(props: IFilterProps): void;
|
|
36
|
+
saveProps(): IFilterProps;
|
|
37
|
+
|
|
61
38
|
get onChanged(): Observable<void>;
|
|
62
39
|
get filterPanel(): HTMLElement;
|
|
63
40
|
get filterSummary(): string;
|
|
@@ -79,7 +56,6 @@ export abstract class BioFilterBase<TProps extends BioFilterProps> implements IB
|
|
|
79
56
|
|
|
80
57
|
private _props: TProps;
|
|
81
58
|
protected _propsChanging: boolean = false;
|
|
82
|
-
private _propsOnChangedSub: Unsubscribable | null = null;
|
|
83
59
|
|
|
84
60
|
abstract get type(): string;
|
|
85
61
|
|
|
@@ -91,33 +67,31 @@ export abstract class BioFilterBase<TProps extends BioFilterProps> implements IB
|
|
|
91
67
|
set props(value: TProps) {
|
|
92
68
|
this._propsChanging = true;
|
|
93
69
|
try {
|
|
94
|
-
if (this._propsOnChangedSub) {
|
|
95
|
-
this._propsOnChangedSub.unsubscribe();
|
|
96
|
-
this._propsOnChangedSub = null;
|
|
97
|
-
}
|
|
98
70
|
this._props = value;
|
|
99
71
|
this.applyProps();
|
|
100
72
|
this.onChanged.next();
|
|
101
|
-
this._propsOnChangedSub = this._props.onChanged
|
|
102
|
-
.subscribe(() => {
|
|
103
|
-
this.onChanged.next();
|
|
104
|
-
});
|
|
105
73
|
} finally {
|
|
106
74
|
this._propsChanging = false;
|
|
107
75
|
}
|
|
108
76
|
};
|
|
109
77
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
78
|
+
saveProps(): IFilterProps {
|
|
79
|
+
const propsObj = {};
|
|
80
|
+
for (const [key, value] of Object.entries(this.props)) {
|
|
81
|
+
if (key !== '_onChanged') {
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
propsObj[key] = this.props[key];
|
|
84
|
+
}
|
|
116
85
|
}
|
|
86
|
+
return propsObj;
|
|
117
87
|
}
|
|
118
88
|
|
|
119
89
|
abstract applyProps(): void;
|
|
120
90
|
|
|
91
|
+
abstract attach(): Promise<void>;
|
|
92
|
+
|
|
93
|
+
async detach(): Promise<void> { }
|
|
94
|
+
|
|
121
95
|
get filterSummary(): string { return this.props.substructure; };
|
|
122
96
|
|
|
123
97
|
get isFiltering(): boolean { return this.props.substructure !== ''; }
|
|
@@ -10,14 +10,14 @@ import * as grok from 'datagrok-api/grok';
|
|
|
10
10
|
|
|
11
11
|
import wu from 'wu';
|
|
12
12
|
import $ from 'cash-dom';
|
|
13
|
-
import {fromEvent, Observable, Subject,
|
|
13
|
+
import {fromEvent, Observable, Subject, Unsubscribable} from 'rxjs';
|
|
14
14
|
|
|
15
15
|
import {TAGS as bioTAGS, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
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
19
|
import {IHelmWebEditor, IWebEditorApp} from '@datagrok-libraries/bio/src/helm/types';
|
|
20
|
-
import {
|
|
20
|
+
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
21
21
|
import {IRenderer} from '@datagrok-libraries/bio/src/types/renderer';
|
|
22
22
|
import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
|
|
23
23
|
import {PromiseSyncer} from '@datagrok-libraries/bio/src/utils/syncer';
|
|
@@ -44,9 +44,10 @@ class FilterState {
|
|
|
44
44
|
export class SeparatorFilterProps extends BioFilterProps {
|
|
45
45
|
constructor(
|
|
46
46
|
substructure: string,
|
|
47
|
-
public separator?: string
|
|
47
|
+
public readonly separator?: string,
|
|
48
48
|
) {
|
|
49
|
-
super(substructure);
|
|
49
|
+
super(substructure, false);
|
|
50
|
+
this.readOnly = true;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
@@ -119,8 +120,14 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
119
120
|
const logPrefix = `${this.filterToLog()}.attach()`;
|
|
120
121
|
this.filterSyncer.sync(logPrefix, async () => {
|
|
121
122
|
superAttach(dataFrame);
|
|
122
|
-
|
|
123
|
-
|
|
123
|
+
|
|
124
|
+
if (!this.column) {
|
|
125
|
+
if (this.columnName)
|
|
126
|
+
this.column = this.dataFrame!.getCol(this.columnName);
|
|
127
|
+
else
|
|
128
|
+
this.column = dataFrame.columns.bySemType(DG.SEMTYPE.MACROMOLECULE);
|
|
129
|
+
}
|
|
130
|
+
const sh = SeqHandler.forColumn(this.column!);
|
|
124
131
|
this.columnName ??= this.column?.name;
|
|
125
132
|
this.notation ??= this.column?.getTag(DG.TAGS.UNITS);
|
|
126
133
|
|
|
@@ -134,7 +141,7 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
134
141
|
this.viewSubs.push(DG.debounce(this.bioFilter!.onChanged, this.debounceTime)
|
|
135
142
|
.subscribe(this.bioFilterOnChangedDebounced.bind(this)));
|
|
136
143
|
this.viewSubs.push(grok.events.onResetFilterRequest
|
|
137
|
-
.subscribe(
|
|
144
|
+
.subscribe(this.grokEventsOnResetFilterRequest.bind(this)));
|
|
138
145
|
this.viewSubs.push(grok.events.onCustomEvent(FILTER_SYNC_EVENT)
|
|
139
146
|
.subscribe(this.filterOnSync.bind(this)));
|
|
140
147
|
});
|
|
@@ -164,6 +171,8 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
164
171
|
// -- Layout --
|
|
165
172
|
|
|
166
173
|
applyFilter(): void {
|
|
174
|
+
const logPrefix = `${this.filterToLog()}.applyFilter()`;
|
|
175
|
+
this.logger.debug(`${logPrefix}, IN`);
|
|
167
176
|
if (this.bitset && !this.isDetached)
|
|
168
177
|
this.dataFrame?.filter.and(this.bitset);
|
|
169
178
|
}
|
|
@@ -172,8 +181,10 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
172
181
|
* @return {any} - filter state
|
|
173
182
|
*/
|
|
174
183
|
saveState(): any {
|
|
184
|
+
const logPrefix = `${this.filterToLog()}.saveState()`;
|
|
175
185
|
const state = super.saveState();
|
|
176
|
-
|
|
186
|
+
this.logger.debug(`${logPrefix}, super.state = ${JSON.stringify(state)}`);
|
|
187
|
+
state.props = this.bioFilter!.saveProps();
|
|
177
188
|
return state;
|
|
178
189
|
}
|
|
179
190
|
|
|
@@ -181,21 +192,20 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
181
192
|
* @param {any} state - filter state
|
|
182
193
|
*/
|
|
183
194
|
applyState(state: any): void {
|
|
195
|
+
const logPrefix = `${this.filterToLog()}.applyState()`;
|
|
184
196
|
super.applyState(state); //column, columnName
|
|
185
|
-
if (state.props)
|
|
186
|
-
this.bioFilter!.props.apply(state.props);
|
|
187
197
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
198
|
+
this.filterSyncer.sync(logPrefix, async () => {
|
|
199
|
+
if (state.props && this.bioFilter)
|
|
200
|
+
this.bioFilter.props = state.props;
|
|
201
|
+
});
|
|
192
202
|
}
|
|
193
203
|
|
|
194
204
|
private fireFilterSync(): void {
|
|
195
205
|
const logPrefix = `${this.filterToLog()}.fireFilterSync()`;
|
|
196
206
|
_package.logger.debug(`${logPrefix}, ` +
|
|
197
207
|
`bioFilter = ${!!this.bioFilter ? this.bioFilter.constructor.name : 'null'}` +
|
|
198
|
-
(!!this.bioFilter ? `, props = ${JSON.stringify(this.bioFilter!.
|
|
208
|
+
(!!this.bioFilter ? `, props = ${JSON.stringify(this.bioFilter!.saveProps())}` : ''));
|
|
199
209
|
|
|
200
210
|
grok.events.fireCustomEvent(FILTER_SYNC_EVENT, new FilterState(
|
|
201
211
|
this.bioFilter!.props, this.filterId, this.dataFrame!.id, this.columnName!, this.bitset));
|
|
@@ -213,7 +223,7 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
213
223
|
const logPrefix = `${this.filterToLog()}.bioFilterOnChangedDebounced()`;
|
|
214
224
|
_package.logger.debug(`${logPrefix}, start, ` +
|
|
215
225
|
`isFiltering = ${this.isFiltering}, ` +
|
|
216
|
-
`props = ${JSON.stringify(this.bioFilter!.
|
|
226
|
+
`props = ${JSON.stringify(this.bioFilter!.saveProps())}`);
|
|
217
227
|
|
|
218
228
|
if (!this.isFiltering) {
|
|
219
229
|
this.bitset = null;
|
|
@@ -241,6 +251,12 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
241
251
|
});
|
|
242
252
|
}
|
|
243
253
|
|
|
254
|
+
grokEventsOnResetFilterRequest(): void {
|
|
255
|
+
const logPrefix = `${this.filterToLog()}.grokEventsOnResetFilterRequest()`;
|
|
256
|
+
_package.logger.debug(`${logPrefix}`);
|
|
257
|
+
this.bioFilter?.resetFilter();
|
|
258
|
+
}
|
|
259
|
+
|
|
244
260
|
// -- IRenderer --
|
|
245
261
|
|
|
246
262
|
private _onRendered = new Subject<void>();
|
|
@@ -282,13 +298,14 @@ export class FastaBioFilter extends BioFilterBase<BioFilterProps> {
|
|
|
282
298
|
super();
|
|
283
299
|
|
|
284
300
|
this.substructureInput = ui.stringInput('', '', () => {
|
|
285
|
-
this.props
|
|
301
|
+
this.props = new BioFilterProps(this.substructureInput.value);
|
|
286
302
|
if (!this._propsChanging) this.onChanged.next();
|
|
287
303
|
}, {placeholder: 'Substructure'});
|
|
288
304
|
}
|
|
289
305
|
|
|
290
306
|
public applyProps() {
|
|
291
|
-
this.substructureInput.value
|
|
307
|
+
if (this.substructureInput.value !== this.props.substructure)
|
|
308
|
+
this.substructureInput.value = this.props.substructure;
|
|
292
309
|
}
|
|
293
310
|
|
|
294
311
|
get filterPanel() {
|
|
@@ -309,7 +326,7 @@ export class FastaBioFilter extends BioFilterBase<BioFilterProps> {
|
|
|
309
326
|
}
|
|
310
327
|
|
|
311
328
|
export class SeparatorBioFilter extends BioFilterBase<SeparatorFilterProps> {
|
|
312
|
-
readonly emptyProps = new SeparatorFilterProps('');
|
|
329
|
+
readonly emptyProps = new SeparatorFilterProps('', undefined);
|
|
313
330
|
|
|
314
331
|
readonly substructureInput: DG.InputBase<string>;
|
|
315
332
|
readonly separatorInput: DG.InputBase<string>;
|
|
@@ -321,18 +338,23 @@ export class SeparatorBioFilter extends BioFilterBase<SeparatorFilterProps> {
|
|
|
321
338
|
super();
|
|
322
339
|
|
|
323
340
|
this.substructureInput = ui.stringInput('', '', () => {
|
|
324
|
-
this.props
|
|
341
|
+
this.props = new SeparatorFilterProps(this.substructureInput.value, this.props.separator);
|
|
325
342
|
if (!this._propsChanging) this.onChanged.next();
|
|
326
343
|
}, {placeholder: 'Substructure'});
|
|
327
344
|
this.separatorInput = ui.stringInput('', this.colSeparator = colSeparator, () => {
|
|
328
|
-
|
|
345
|
+
const separator: string | undefined = !!this.separatorInput.value ? this.separatorInput.value : undefined;
|
|
346
|
+
this.props = new SeparatorFilterProps(this.props.substructure, separator);
|
|
329
347
|
if (!this._propsChanging) this.onChanged.next();
|
|
330
348
|
}, {placeholder: 'Separator'});
|
|
331
349
|
}
|
|
332
350
|
|
|
333
351
|
applyProps(): void {
|
|
334
|
-
this.substructureInput.value
|
|
335
|
-
|
|
352
|
+
if (this.substructureInput.value !== this.props.substructure)
|
|
353
|
+
this.substructureInput.value = this.props.substructure;
|
|
354
|
+
|
|
355
|
+
const separatorValue = this.props.separator ?? this.colSeparator;
|
|
356
|
+
if (this.separatorInput.value !== separatorValue)
|
|
357
|
+
this.separatorInput.value = separatorValue;
|
|
336
358
|
}
|
|
337
359
|
|
|
338
360
|
get filterSummary(): string {
|
|
@@ -8,8 +8,8 @@ import {TAGS as bioTAGS, ALPHABET, getPaletteByType} from '@datagrok-libraries/b
|
|
|
8
8
|
import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
|
|
9
9
|
import {UnknownSeqPalettes} from '@datagrok-libraries/bio/src/unknown';
|
|
10
10
|
import '../../css/composition-analysis.css';
|
|
11
|
-
import {
|
|
12
|
-
import {GAP_SYMBOL} from '
|
|
11
|
+
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
12
|
+
import {GAP_SYMBOL} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
export function getCompositionAnalysisWidget(val: DG.SemanticValue): DG.Widget {
|
|
@@ -30,12 +30,12 @@ export function getCompositionAnalysisWidget(val: DG.SemanticValue): DG.Widget {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const counts: { [m: string]: number } = {};
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const parts =
|
|
36
|
-
wu(parts).filter((
|
|
37
|
-
const count = counts[
|
|
38
|
-
counts[
|
|
33
|
+
const sh = SeqHandler.forColumn(val.cell.column as DG.Column<string>);
|
|
34
|
+
const rowIdx = val.cell.rowIndex;
|
|
35
|
+
const parts = sh.getSplitted(rowIdx);
|
|
36
|
+
wu(parts.canonicals).filter((cm) => cm !== GAP_SYMBOL).forEach((cm) => {
|
|
37
|
+
const count = counts[cm] || 0;
|
|
38
|
+
counts[cm] = count + 1;
|
|
39
39
|
});
|
|
40
40
|
const table = buildCompositionTable(palette, counts);
|
|
41
41
|
Array.from(table.rows).forEach((row) => {
|