@datagrok/bio 2.11.42 → 2.12.0
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 +6 -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 +2 -2
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +2 -2
- package/dist/package.js.map +1 -1
- package/package.json +10 -10
- 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 +8 -8
- 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/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/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.ts +3 -3
- package/src/widgets/composition-analysis-widget.ts +8 -8
|
@@ -6,7 +6,7 @@ import $ from 'cash-dom';
|
|
|
6
6
|
import wu from 'wu';
|
|
7
7
|
import {fromEvent, Observable, Subject, Unsubscribable} from 'rxjs';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
10
10
|
import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
|
|
11
11
|
import {
|
|
12
12
|
monomerToShort, pickUpPalette, pickUpSeqCol, TAGS as bioTAGS, positionSeparator
|
|
@@ -17,8 +17,7 @@ import {
|
|
|
17
17
|
} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
18
18
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
19
19
|
import {intToHtmlA} from '@datagrok-libraries/utils/src/color';
|
|
20
|
-
import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
21
|
-
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
20
|
+
import {GAP_SYMBOL, ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
22
21
|
import {testEvent} from '@datagrok-libraries/utils/src/test';
|
|
23
22
|
import {PromiseSyncer} from '@datagrok-libraries/bio/src/utils/syncer';
|
|
24
23
|
|
|
@@ -26,7 +25,6 @@ import {AggFunc, getAgg} from '../utils/agg';
|
|
|
26
25
|
import {buildCompositionTable} from '../widgets/composition-analysis-widget';
|
|
27
26
|
|
|
28
27
|
import {_package} from '../package';
|
|
29
|
-
import {GAP_SYMBOL} from '../const';
|
|
30
28
|
|
|
31
29
|
declare global {
|
|
32
30
|
interface HTMLCanvasElement {
|
|
@@ -168,8 +166,7 @@ export class PositionInfo {
|
|
|
168
166
|
}
|
|
169
167
|
}
|
|
170
168
|
|
|
171
|
-
calcScreen(
|
|
172
|
-
isGap: (m: string) => boolean, posIdx: number, firstVisiblePosIdx: number,
|
|
169
|
+
calcScreen(posIdx: number, firstVisiblePosIdx: number,
|
|
173
170
|
absoluteMaxHeight: number, heightMode: PositionHeight, alphabetSizeLog: number,
|
|
174
171
|
positionWidthWithMargin: number, positionWidth: number, dpr: number, positionLabelsHeight: number
|
|
175
172
|
): void {
|
|
@@ -180,13 +177,13 @@ export class PositionInfo {
|
|
|
180
177
|
|
|
181
178
|
const entries = Object.entries(this._freqs)
|
|
182
179
|
.sort((a, b) => {
|
|
183
|
-
if (
|
|
180
|
+
if (a[0] !== GAP_SYMBOL && b[0] !== GAP_SYMBOL)
|
|
184
181
|
return b[1].value - a[1].value;
|
|
185
|
-
else if (
|
|
182
|
+
else if (a[0] === GAP_SYMBOL && b[0] === GAP_SYMBOL)
|
|
186
183
|
return 0;
|
|
187
|
-
else if (
|
|
184
|
+
else if (a[0] === GAP_SYMBOL)
|
|
188
185
|
return -1;
|
|
189
|
-
else /* (
|
|
186
|
+
else /* (b[0] === GAP_SYMBOL) */
|
|
190
187
|
return +1;
|
|
191
188
|
});
|
|
192
189
|
for (const [_m, pmi] of entries) {
|
|
@@ -200,11 +197,10 @@ export class PositionInfo {
|
|
|
200
197
|
}
|
|
201
198
|
|
|
202
199
|
render(g: CanvasRenderingContext2D,
|
|
203
|
-
isGap: (m: string) => boolean,
|
|
204
200
|
fontStyle: string, uppercaseLetterAscent: number, uppercaseLetterHeight: number, cp: SeqPalette
|
|
205
201
|
) {
|
|
206
202
|
for (const [monomer, pmInfo] of Object.entries(this._freqs)) {
|
|
207
|
-
if (
|
|
203
|
+
if (monomer !== GAP_SYMBOL) {
|
|
208
204
|
const monomerTxt = monomerToShort(monomer, 5);
|
|
209
205
|
const b = pmInfo.bounds!;
|
|
210
206
|
const left = b.left;
|
|
@@ -303,7 +299,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
303
299
|
|
|
304
300
|
private viewed: boolean = false;
|
|
305
301
|
|
|
306
|
-
private
|
|
302
|
+
private seqHandler: SeqHandler | null;
|
|
307
303
|
private initialized: boolean = false;
|
|
308
304
|
|
|
309
305
|
// private readonly colorScheme: ColorScheme = ColorSchemes[NucleotidesWebLogo.residuesSet];
|
|
@@ -373,7 +369,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
373
369
|
}
|
|
374
370
|
|
|
375
371
|
public get positionMarginValue(): number {
|
|
376
|
-
if (this.positionMarginState === PositionMarginStates.AUTO && this.
|
|
372
|
+
if (this.positionMarginState === PositionMarginStates.AUTO && this.seqHandler!.getAlphabetIsMultichar() === true)
|
|
377
373
|
return this.positionMargin;
|
|
378
374
|
else if (this.positionMarginState === PositionMarginStates.ON)
|
|
379
375
|
return this.positionMargin;
|
|
@@ -385,7 +381,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
385
381
|
super();
|
|
386
382
|
|
|
387
383
|
this.textBaseline = 'top';
|
|
388
|
-
this.
|
|
384
|
+
this.seqHandler = null;
|
|
389
385
|
|
|
390
386
|
// -- Data --
|
|
391
387
|
this.sequenceColumnName = this.string(PROPS.sequenceColumnName, defaults.sequenceColumnName,
|
|
@@ -589,7 +585,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
589
585
|
}
|
|
590
586
|
if (this.seqCol) {
|
|
591
587
|
try {
|
|
592
|
-
this.
|
|
588
|
+
this.seqHandler = SeqHandler.forColumn(this.seqCol);
|
|
593
589
|
|
|
594
590
|
this.palette = pickUpPalette(this.seqCol);
|
|
595
591
|
this.render(WlRenderLevel.Freqs, 'updateSeqCol()');
|
|
@@ -600,7 +596,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
600
596
|
throw err;
|
|
601
597
|
}
|
|
602
598
|
if (!this.seqCol) {
|
|
603
|
-
this.
|
|
599
|
+
this.seqHandler = null;
|
|
604
600
|
this.positionNames = [];
|
|
605
601
|
this.positionLabels = [];
|
|
606
602
|
this.startPosition = -1;
|
|
@@ -817,6 +813,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
817
813
|
case PROPS.sequenceColumnName:
|
|
818
814
|
this.updateSeqCol();
|
|
819
815
|
break;
|
|
816
|
+
case PROPS.sequenceColumnName:
|
|
820
817
|
case PROPS.startPositionName:
|
|
821
818
|
case PROPS.endPositionName:
|
|
822
819
|
case PROPS.filterSource:
|
|
@@ -956,9 +953,10 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
956
953
|
// region updatePositions
|
|
957
954
|
|
|
958
955
|
const dfFilter = this.getFilter();
|
|
959
|
-
const maxLength: number = dfFilter.trueCount === 0 ? this.
|
|
960
|
-
wu.
|
|
961
|
-
|
|
956
|
+
const maxLength: number = dfFilter.trueCount === 0 ? this.seqHandler!.maxLength :
|
|
957
|
+
wu.count(0).take(this.seqHandler!.length).map((rowIdx) => {
|
|
958
|
+
const mList = this.seqHandler!.getSplitted(rowIdx);
|
|
959
|
+
return dfFilter.get(rowIdx) && !!mList ? mList.length : 0;
|
|
962
960
|
}).reduce((max, l) => Math.max(max, l), 0);
|
|
963
961
|
|
|
964
962
|
/** positionNames and positionLabel can be set up through the column's tags only */
|
|
@@ -979,7 +977,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
979
977
|
// endregion updatePositions
|
|
980
978
|
|
|
981
979
|
const length: number = this.startPosition <= this.endPosition ? this.endPosition - this.startPosition + 1 : 0;
|
|
982
|
-
this.
|
|
980
|
+
this.seqHandler = SeqHandler.forColumn(this.seqCol);
|
|
983
981
|
const posCount: number = this.startPosition <= this.endPosition ? this.endPosition - this.startPosition + 1 : 0;
|
|
984
982
|
this.positions = new Array(posCount);
|
|
985
983
|
for (let jPos = 0; jPos < length; jPos++) {
|
|
@@ -991,18 +989,16 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
991
989
|
|
|
992
990
|
// 2022-05-05 askalkin instructed to show WebLogo based on filter (not selection)
|
|
993
991
|
const dfRowCount = this.dataFrame.rowCount;
|
|
994
|
-
const splitted = this.unitsHandler.splitted;
|
|
995
992
|
|
|
996
993
|
for (let jPos = 0; jPos < length; ++jPos) {
|
|
994
|
+
const pi = this.positions[jPos];
|
|
997
995
|
// Here we want to build lists of values for every monomer in position jPos
|
|
998
996
|
for (let rowI = 0; rowI < dfRowCount; ++rowI) {
|
|
999
997
|
if (dfFilter.get(rowI)) {
|
|
1000
|
-
const seqMList: ISeqSplitted = splitted[rowI];
|
|
1001
|
-
const om: string = seqMList[this.startPosition + jPos] || this.unitsHandler.defaultGapSymbol;
|
|
1002
|
-
const cm: string = this.unitsHandler?.defaultGapSymbol === om ? GAP_SYMBOL : om;
|
|
1003
|
-
const pi = this.positions[jPos];
|
|
1004
|
-
const pmi = pi.getFreq(cm);
|
|
1005
998
|
++pi.sumRowCount;
|
|
999
|
+
const seqMList: ISeqSplitted = this.seqHandler.getSplitted(rowI);
|
|
1000
|
+
const cm: string = seqMList.getCanonical(this.startPosition + jPos);
|
|
1001
|
+
const pmi = pi.getFreq(cm);
|
|
1006
1002
|
pmi.value = ++pmi.rowCount;
|
|
1007
1003
|
}
|
|
1008
1004
|
}
|
|
@@ -1019,10 +1015,10 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1019
1015
|
|
|
1020
1016
|
for (let rowI = 0; rowI < dfRowCount; ++rowI) {
|
|
1021
1017
|
if (dfFilter.get(rowI)) { // respect the filter
|
|
1022
|
-
const seqMList: ISeqSplitted =
|
|
1023
|
-
const
|
|
1018
|
+
const seqMList: ISeqSplitted = this.seqHandler.getSplitted(rowI);
|
|
1019
|
+
const cm: string = seqMList.getCanonical(this.startPosition + jPos);
|
|
1024
1020
|
const value: number | null = valueCol.get(rowI);
|
|
1025
|
-
this.positions[jPos].getFreq(
|
|
1021
|
+
this.positions[jPos].getFreq(cm).push(value);
|
|
1026
1022
|
}
|
|
1027
1023
|
}
|
|
1028
1024
|
this.positions[jPos].aggregate(this.valueAggrType);
|
|
@@ -1061,7 +1057,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1061
1057
|
`this.positions.length = ${this.positions.length}, jPos = ${jPos}`);
|
|
1062
1058
|
continue;
|
|
1063
1059
|
}
|
|
1064
|
-
this.positions[jPos].calcScreen(
|
|
1060
|
+
this.positions[jPos].calcScreen(
|
|
1065
1061
|
jPos, this.slider.min, absoluteMaxHeight, this.positionHeight,
|
|
1066
1062
|
alphabetSizeLog, this._positionWidthWithMargin, this._positionWidth, dpr, positionLabelsHeight);
|
|
1067
1063
|
}
|
|
@@ -1117,10 +1113,8 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1117
1113
|
// Hacks to scale uppercase characters to target rectangle
|
|
1118
1114
|
const uppercaseLetterAscent = 0.25;
|
|
1119
1115
|
const uppercaseLetterHeight = 12.2;
|
|
1120
|
-
for (let jPos = firstPos; jPos <= lastPos; jPos++)
|
|
1121
|
-
this.positions[jPos].render(g,
|
|
1122
|
-
fontStyle, uppercaseLetterAscent, uppercaseLetterHeight, this.palette);
|
|
1123
|
-
}
|
|
1116
|
+
for (let jPos = firstPos; jPos <= lastPos; jPos++)
|
|
1117
|
+
this.positions[jPos].render(g, fontStyle, uppercaseLetterAscent, uppercaseLetterHeight, this.palette);
|
|
1124
1118
|
} finally {
|
|
1125
1119
|
g.restore();
|
|
1126
1120
|
}
|
|
@@ -1135,18 +1129,16 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1135
1129
|
return;
|
|
1136
1130
|
}
|
|
1137
1131
|
this.requestedRenderLevel = WlRenderLevel.None;
|
|
1138
|
-
this.
|
|
1139
|
-
.
|
|
1140
|
-
|
|
1141
|
-
_package.logger.error(errMsg, undefined, errStack);
|
|
1142
|
-
});
|
|
1132
|
+
this.viewSyncer.sync(logPrefix, async () => {
|
|
1133
|
+
await this.renderInt(renderLevel);
|
|
1134
|
+
});
|
|
1143
1135
|
}
|
|
1144
1136
|
|
|
1145
1137
|
private _lastWidth: number;
|
|
1146
1138
|
private _lastHeight: number;
|
|
1147
1139
|
|
|
1148
1140
|
public getAlphabetSize(): number {
|
|
1149
|
-
return this.
|
|
1141
|
+
return this.seqHandler?.getAlphabetSize() ?? 0;
|
|
1150
1142
|
}
|
|
1151
1143
|
|
|
1152
1144
|
// -- Handle events --
|
|
@@ -1212,10 +1204,10 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1212
1204
|
tooltipRows.push(pi.buildCompositionTable(this.palette!));
|
|
1213
1205
|
const tooltipEl = ui.divV(tooltipRows);
|
|
1214
1206
|
ui.tooltip.show(tooltipEl, args.x + 16, args.y + 16);
|
|
1215
|
-
} else if (pi !== null && monomer && this.dataFrame && this.seqCol && this.
|
|
1207
|
+
} else if (pi !== null && monomer && this.dataFrame && this.seqCol && this.seqHandler) {
|
|
1216
1208
|
// Monomer at position tooltip
|
|
1217
1209
|
// const monomerAtPosSeqCount = countForMonomerAtPosition(
|
|
1218
|
-
// this.dataFrame, this.
|
|
1210
|
+
// this.dataFrame, this.seqHandler!, this.getFilter(), monomer, atPI);
|
|
1219
1211
|
const pmi = pi.getFreq(monomer);
|
|
1220
1212
|
|
|
1221
1213
|
const tooltipRows = [
|
|
@@ -1243,10 +1235,10 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1243
1235
|
const [pi, monomer] = this.getMonomer(this.canvas.getCursorPosition(args, dpr), dpr);
|
|
1244
1236
|
|
|
1245
1237
|
// prevents deselect all rows if we miss monomer bounds
|
|
1246
|
-
if (pi !== null && monomer !== null && this.dataFrame && this.seqCol && this.
|
|
1238
|
+
if (pi !== null && monomer !== null && this.dataFrame && this.seqCol && this.seqHandler) {
|
|
1247
1239
|
// Calculate a new BitSet object for selection to prevent interfering with existing
|
|
1248
1240
|
const selBS: DG.BitSet = DG.BitSet.create(this.dataFrame.selection.length, (rowI: number) => {
|
|
1249
|
-
return checkSeqForMonomerAtPos(this.dataFrame, this.
|
|
1241
|
+
return checkSeqForMonomerAtPos(this.dataFrame, this.seqHandler!, this.getFilter(), rowI, monomer, pi);
|
|
1250
1242
|
});
|
|
1251
1243
|
this.dataFrame.selection.init((i) => selBS.get(i));
|
|
1252
1244
|
}
|
|
@@ -1281,8 +1273,8 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1281
1273
|
const callLog = `invalidate(${caller ? ` <- ${caller} ` : ''})`;
|
|
1282
1274
|
const logPrefix = `${this.viewerToLog()}.${callLog}`;
|
|
1283
1275
|
// Put the event trigger in the tail of the synced calls queue.
|
|
1276
|
+
this.render(WlRenderLevel.None, callLog); // Put render request to the syncer
|
|
1284
1277
|
this.viewSyncer.sync(`${logPrefix}`, async () => {
|
|
1285
|
-
this.render(WlRenderLevel.None, callLog);
|
|
1286
1278
|
this._onRendered.next();
|
|
1287
1279
|
});
|
|
1288
1280
|
}
|
|
@@ -1333,23 +1325,23 @@ function renderPositionLabels(g: CanvasRenderingContext2D,
|
|
|
1333
1325
|
}
|
|
1334
1326
|
|
|
1335
1327
|
export function checkSeqForMonomerAtPos(
|
|
1336
|
-
df: DG.DataFrame,
|
|
1328
|
+
df: DG.DataFrame, sh: SeqHandler, filter: DG.BitSet, rowI: number, monomer: string, at: PositionInfo,
|
|
1337
1329
|
): boolean {
|
|
1338
|
-
const seqMList: ISeqSplitted =
|
|
1339
|
-
const
|
|
1340
|
-
return
|
|
1330
|
+
const seqMList: ISeqSplitted = sh.getSplitted(rowI);
|
|
1331
|
+
const seqCM: string | null = at.pos < seqMList.length ? seqMList.getCanonical(at.pos) : null;
|
|
1332
|
+
return seqCM !== null && seqCM === monomer;
|
|
1341
1333
|
}
|
|
1342
1334
|
|
|
1343
1335
|
export function countForMonomerAtPosition(
|
|
1344
|
-
df: DG.DataFrame,
|
|
1336
|
+
df: DG.DataFrame, sh: SeqHandler, filter: DG.BitSet, monomer: string, at: PositionInfo
|
|
1345
1337
|
): number {
|
|
1346
1338
|
let count = 0;
|
|
1347
1339
|
let rowI = -1;
|
|
1348
1340
|
while ((rowI = filter.findNext(rowI, true)) != -1) {
|
|
1349
|
-
const seqMList: ISeqSplitted =
|
|
1341
|
+
const seqMList: ISeqSplitted = sh.getSplitted(rowI);
|
|
1350
1342
|
const seqMPos: number = at.pos;
|
|
1351
|
-
const
|
|
1352
|
-
if (
|
|
1343
|
+
const seqCM: string | null = seqMPos < seqMList.length ? seqMList.getCanonical(seqMPos) : null;
|
|
1344
|
+
if (seqCM !== null && seqCM === monomer) count++;
|
|
1353
1345
|
}
|
|
1354
1346
|
return count;
|
|
1355
1347
|
}
|
|
@@ -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';
|
|
@@ -120,7 +120,7 @@ export class BioSubstructureFilter extends DG.Filter implements IRenderer {
|
|
|
120
120
|
this.filterSyncer.sync(logPrefix, async () => {
|
|
121
121
|
superAttach(dataFrame);
|
|
122
122
|
this.column = dataFrame.columns.bySemType(DG.SEMTYPE.MACROMOLECULE);
|
|
123
|
-
const
|
|
123
|
+
const sh = SeqHandler.forColumn(this.column!);
|
|
124
124
|
this.columnName ??= this.column?.name;
|
|
125
125
|
this.notation ??= this.column?.getTag(DG.TAGS.UNITS);
|
|
126
126
|
|
|
@@ -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) => {
|