@platforma-sdk/ui-vue 1.34.17 → 1.35.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 +13 -0
- package/dist/lib.css +1 -1
- package/dist/lib.js +7041 -6851
- package/dist/lib.js.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/Consensus.vue.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/Legend.vue.d.ts +5 -1
- package/dist/src/components/PlMultiSequenceAlignment/Legend.vue.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.d.ts +5 -0
- package/dist/src/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/Toolbar.vue.d.ts +4 -2
- package/dist/src/components/PlMultiSequenceAlignment/Toolbar.vue.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/chemical-properties.d.ts +9 -0
- package/dist/src/components/PlMultiSequenceAlignment/chemical-properties.d.ts.map +1 -0
- package/dist/src/components/PlMultiSequenceAlignment/data.d.ts +32 -33
- package/dist/src/components/PlMultiSequenceAlignment/data.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/markup.d.ts +15 -0
- package/dist/src/components/PlMultiSequenceAlignment/markup.d.ts.map +1 -0
- package/dist/src/components/PlMultiSequenceAlignment/settings.d.ts +2 -2
- package/dist/src/components/PlMultiSequenceAlignment/settings.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/types.d.ts +17 -1
- package/dist/src/components/PlMultiSequenceAlignment/types.d.ts.map +1 -1
- package/dist/src/components/PlMultiSequenceAlignment/useMiPlots.d.ts.map +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/components/PlMultiSequenceAlignment/Consensus.vue +5 -5
- package/src/components/PlMultiSequenceAlignment/Legend.vue +9 -9
- package/src/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue +31 -40
- package/src/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue +110 -18
- package/src/components/PlMultiSequenceAlignment/Toolbar.vue +9 -10
- package/src/components/PlMultiSequenceAlignment/{highlight/chemical-properties.ts → chemical-properties.ts} +71 -68
- package/src/components/PlMultiSequenceAlignment/data.ts +159 -42
- package/src/components/PlMultiSequenceAlignment/markup.ts +107 -0
- package/src/components/PlMultiSequenceAlignment/settings.ts +2 -2
- package/src/components/PlMultiSequenceAlignment/types.ts +13 -1
- package/src/components/PlMultiSequenceAlignment/useMiPlots.ts +1 -2
- package/dist/src/components/PlMultiSequenceAlignment/highlight/chemical-properties.d.ts +0 -20
- package/dist/src/components/PlMultiSequenceAlignment/highlight/chemical-properties.d.ts.map +0 -1
- package/dist/src/components/PlMultiSequenceAlignment/highlight/index.d.ts +0 -7
- package/dist/src/components/PlMultiSequenceAlignment/highlight/index.d.ts.map +0 -1
- package/dist/src/components/PlMultiSequenceAlignment/highlight/types.d.ts +0 -8
- package/dist/src/components/PlMultiSequenceAlignment/highlight/types.d.ts.map +0 -1
- package/src/components/PlMultiSequenceAlignment/highlight/index.ts +0 -33
- package/src/components/PlMultiSequenceAlignment/highlight/types.ts +0 -7
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
type CanonicalizedJson,
|
|
6
6
|
canonicalizeJson,
|
|
7
7
|
createRowSelectionColumn,
|
|
8
|
+
ensureError,
|
|
8
9
|
getAxisId,
|
|
9
10
|
getRawPlatformaInstance,
|
|
10
11
|
isLabelColumn,
|
|
@@ -20,13 +21,12 @@ import {
|
|
|
20
21
|
pTableValue,
|
|
21
22
|
} from '@platforma-sdk/model';
|
|
22
23
|
import { computedAsync } from '@vueuse/core';
|
|
23
|
-
import { type MaybeRefOrGetter, ref, toValue } from 'vue';
|
|
24
|
+
import { type MaybeRefOrGetter, ref, shallowRef, toValue } from 'vue';
|
|
25
|
+
import { type Markup, markupAlignedSequence, parseMarkup } from './markup';
|
|
24
26
|
import { multiSequenceAlignment } from './multi-sequence-alignment';
|
|
25
27
|
|
|
26
28
|
const getPFrameDriver = () => getRawPlatformaInstance().pFrameDriver;
|
|
27
29
|
|
|
28
|
-
const getEmptyOptions = () => ({ defaults: [], options: [] });
|
|
29
|
-
|
|
30
30
|
export const sequenceLimit = 1000;
|
|
31
31
|
|
|
32
32
|
export function useSequenceColumnsOptions(
|
|
@@ -35,10 +35,20 @@ export function useSequenceColumnsOptions(
|
|
|
35
35
|
sequenceColumnPredicate: PColumnPredicate;
|
|
36
36
|
}>,
|
|
37
37
|
) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
const error = shallowRef<Error>();
|
|
39
|
+
const data = computedAsync(
|
|
40
|
+
async () => {
|
|
41
|
+
try {
|
|
42
|
+
error.value = undefined;
|
|
43
|
+
return await getSequenceColumnsOptions(toValue(params));
|
|
44
|
+
} catch (err) {
|
|
45
|
+
error.value = ensureError(err);
|
|
46
|
+
return { options: [], defaults: [] };
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{ options: [], defaults: [] },
|
|
41
50
|
);
|
|
51
|
+
return { data, error };
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
export function useLabelColumnsOptions(
|
|
@@ -50,10 +60,42 @@ export function useLabelColumnsOptions(
|
|
|
50
60
|
| undefined;
|
|
51
61
|
}>,
|
|
52
62
|
) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
63
|
+
const error = shallowRef<Error>();
|
|
64
|
+
const data = computedAsync(
|
|
65
|
+
async () => {
|
|
66
|
+
try {
|
|
67
|
+
error.value = undefined;
|
|
68
|
+
return await getLabelColumnsOptions(toValue(params));
|
|
69
|
+
} catch (err) {
|
|
70
|
+
error.value = ensureError(err);
|
|
71
|
+
return { options: [], defaults: [] };
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{ options: [], defaults: [] },
|
|
56
75
|
);
|
|
76
|
+
return { data, error };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function useMarkupColumnsOptions(
|
|
80
|
+
params: MaybeRefOrGetter<{
|
|
81
|
+
pFrame: PFrameHandle | undefined;
|
|
82
|
+
sequenceColumnIds: PObjectId[];
|
|
83
|
+
}>,
|
|
84
|
+
) {
|
|
85
|
+
const error = shallowRef<Error>();
|
|
86
|
+
const data = computedAsync(
|
|
87
|
+
async () => {
|
|
88
|
+
try {
|
|
89
|
+
error.value = undefined;
|
|
90
|
+
return await getMarkupColumnsOptions(toValue(params));
|
|
91
|
+
} catch (err) {
|
|
92
|
+
error.value = ensureError(err);
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
[],
|
|
97
|
+
);
|
|
98
|
+
return { data, error };
|
|
57
99
|
}
|
|
58
100
|
|
|
59
101
|
export function useMultipleAlignmentData(
|
|
@@ -61,17 +103,27 @@ export function useMultipleAlignmentData(
|
|
|
61
103
|
pframe: PFrameHandle | undefined;
|
|
62
104
|
sequenceColumnIds: PObjectId[];
|
|
63
105
|
labelColumnIds: PTableColumnId[];
|
|
106
|
+
markupColumnId: PObjectId | undefined;
|
|
64
107
|
linkerColumnPredicate: PColumnPredicate | undefined;
|
|
65
108
|
selection: PlSelectionModel | undefined;
|
|
66
109
|
}>,
|
|
67
110
|
) {
|
|
68
111
|
const loading = ref(true);
|
|
69
|
-
const
|
|
70
|
-
|
|
112
|
+
const error = shallowRef<Error>();
|
|
113
|
+
const data = computedAsync(
|
|
114
|
+
async () => {
|
|
115
|
+
try {
|
|
116
|
+
error.value = undefined;
|
|
117
|
+
return await getMultipleAlignmentData(toValue(params));
|
|
118
|
+
} catch (err) {
|
|
119
|
+
error.value = ensureError(err);
|
|
120
|
+
return { sequences: [], labels: [] };
|
|
121
|
+
}
|
|
122
|
+
},
|
|
71
123
|
{ sequences: [], labels: [] },
|
|
72
124
|
{ evaluating: loading },
|
|
73
125
|
);
|
|
74
|
-
return { data
|
|
126
|
+
return { data, error, loading };
|
|
75
127
|
}
|
|
76
128
|
|
|
77
129
|
async function getSequenceColumnsOptions({
|
|
@@ -80,11 +132,8 @@ async function getSequenceColumnsOptions({
|
|
|
80
132
|
}: {
|
|
81
133
|
pFrame: PFrameHandle | undefined;
|
|
82
134
|
sequenceColumnPredicate: (column: PColumnIdAndSpec) => boolean;
|
|
83
|
-
}): Promise<{
|
|
84
|
-
|
|
85
|
-
defaults: PObjectId[];
|
|
86
|
-
}> {
|
|
87
|
-
if (!pFrame) return getEmptyOptions();
|
|
135
|
+
}): Promise<OptionsWithDefaults<PObjectId>> {
|
|
136
|
+
if (!pFrame) return { options: [], defaults: [] };
|
|
88
137
|
const pFrameDriver = getPFrameDriver();
|
|
89
138
|
const columns = await pFrameDriver.listColumns(pFrame);
|
|
90
139
|
const options = columns
|
|
@@ -107,11 +156,8 @@ async function getLabelColumnsOptions({
|
|
|
107
156
|
labelColumnOptionPredicate:
|
|
108
157
|
| ((column: PColumnIdAndSpec) => boolean)
|
|
109
158
|
| undefined;
|
|
110
|
-
}): Promise<{
|
|
111
|
-
|
|
112
|
-
defaults: PTableColumnId[];
|
|
113
|
-
}> {
|
|
114
|
-
if (!pFrame) return getEmptyOptions();
|
|
159
|
+
}): Promise<OptionsWithDefaults<PTableColumnId>> {
|
|
160
|
+
if (!pFrame) return { options: [], defaults: [] };
|
|
115
161
|
const pFrameDriver = getPFrameDriver();
|
|
116
162
|
const columns = await pFrameDriver.listColumns(pFrame);
|
|
117
163
|
const optionMap = new Map<CanonicalizedJson<PTableColumnId>, string>();
|
|
@@ -154,24 +200,52 @@ async function getLabelColumnsOptions({
|
|
|
154
200
|
return { options, defaults };
|
|
155
201
|
}
|
|
156
202
|
|
|
157
|
-
async function
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
203
|
+
async function getMarkupColumnsOptions({
|
|
204
|
+
pFrame,
|
|
205
|
+
sequenceColumnIds,
|
|
206
|
+
}: {
|
|
207
|
+
pFrame: PFrameHandle | undefined;
|
|
208
|
+
sequenceColumnIds: PObjectId[];
|
|
209
|
+
}): Promise<ListOptionNormalized<PObjectId>[]> {
|
|
210
|
+
if (!pFrame || sequenceColumnIds.length !== 1) return [];
|
|
211
|
+
const pFrameDriver = getPFrameDriver();
|
|
212
|
+
const columns = await pFrameDriver.listColumns(pFrame);
|
|
213
|
+
const sequenceColumn = columns.find((column) =>
|
|
214
|
+
column.columnId === sequenceColumnIds[0],
|
|
215
|
+
);
|
|
216
|
+
if (!sequenceColumn) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
`Couldn't find sequence column (ID: ${sequenceColumnIds[0]})`,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return columns
|
|
222
|
+
.filter((column) =>
|
|
223
|
+
column.spec.annotations?.['pl7.app/sequence/isAnnotation'] === 'true'
|
|
224
|
+
&& isJsonEqual(sequenceColumn.spec.axesSpec, column.spec.axesSpec)
|
|
225
|
+
&& Object.entries(sequenceColumn.spec.domain ?? {}).every((
|
|
226
|
+
[key, value],
|
|
227
|
+
) => column.spec.domain?.[key] === value),
|
|
228
|
+
).map(({ columnId, spec }) => ({
|
|
229
|
+
value: columnId,
|
|
230
|
+
label: spec.annotations?.['pl7.app/label'] ?? 'Unlabelled column',
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function getMultipleAlignmentData({
|
|
235
|
+
pframe,
|
|
236
|
+
sequenceColumnIds,
|
|
237
|
+
labelColumnIds,
|
|
238
|
+
markupColumnId,
|
|
239
|
+
linkerColumnPredicate,
|
|
240
|
+
selection,
|
|
241
|
+
}: {
|
|
242
|
+
pframe: PFrameHandle | undefined;
|
|
243
|
+
sequenceColumnIds: PObjectId[];
|
|
244
|
+
labelColumnIds: PTableColumnId[];
|
|
245
|
+
markupColumnId: PObjectId | undefined;
|
|
246
|
+
linkerColumnPredicate: PColumnPredicate | undefined;
|
|
247
|
+
selection: PlSelectionModel | undefined;
|
|
248
|
+
}): Promise<MultipleAlignmentData> {
|
|
175
249
|
if (!pframe || sequenceColumnIds.length === 0) {
|
|
176
250
|
return { sequences: [], labels: [] };
|
|
177
251
|
}
|
|
@@ -219,13 +293,18 @@ async function getMultipleAlignmentData(
|
|
|
219
293
|
};
|
|
220
294
|
}
|
|
221
295
|
|
|
296
|
+
// left join with labels
|
|
222
297
|
const secondaryEntry: JoinEntry<PObjectId>[] = labelColumnIds
|
|
223
298
|
.flatMap((column) => {
|
|
224
299
|
if (column.type !== 'column') return [];
|
|
225
300
|
return { type: 'column', column: column.id };
|
|
226
301
|
});
|
|
227
302
|
|
|
228
|
-
//
|
|
303
|
+
// and markup
|
|
304
|
+
if (markupColumnId) {
|
|
305
|
+
secondaryEntry.push({ type: 'column', column: markupColumnId });
|
|
306
|
+
}
|
|
307
|
+
|
|
229
308
|
const request: CalculateTableDataRequest<PObjectId> = {
|
|
230
309
|
src: {
|
|
231
310
|
type: 'outer',
|
|
@@ -281,6 +360,9 @@ async function getMultipleAlignmentData(
|
|
|
281
360
|
return column;
|
|
282
361
|
});
|
|
283
362
|
|
|
363
|
+
const markupColumn = markupColumnId
|
|
364
|
+
&& table.find(({ spec }) => spec.id === markupColumnId);
|
|
365
|
+
|
|
284
366
|
const alignedSequences = await Promise.all(
|
|
285
367
|
sequenceColumns.map((column) =>
|
|
286
368
|
multiSequenceAlignment(Array.from(
|
|
@@ -305,5 +387,40 @@ async function getMultipleAlignmentData(
|
|
|
305
387
|
),
|
|
306
388
|
);
|
|
307
389
|
|
|
308
|
-
|
|
390
|
+
const result: MultipleAlignmentData = { sequences, labels };
|
|
391
|
+
|
|
392
|
+
if (markupColumn) {
|
|
393
|
+
const labels = JSON.parse(
|
|
394
|
+
markupColumn.spec.spec.annotations
|
|
395
|
+
?.['pl7.app/sequence/annotation/mapping'] ?? '{}',
|
|
396
|
+
);
|
|
397
|
+
const data = Array.from(
|
|
398
|
+
{ length: rowCount },
|
|
399
|
+
(_, row) => {
|
|
400
|
+
const markup = parseMarkup(
|
|
401
|
+
pTableValue(markupColumn.data, row, { na: '', absent: '' })
|
|
402
|
+
?.toString()
|
|
403
|
+
?? '',
|
|
404
|
+
);
|
|
405
|
+
return markupAlignedSequence(sequences[row][0], markup);
|
|
406
|
+
},
|
|
407
|
+
);
|
|
408
|
+
result.markup = { labels, data };
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return result;
|
|
309
412
|
}
|
|
413
|
+
|
|
414
|
+
type MultipleAlignmentData = {
|
|
415
|
+
sequences: string[][];
|
|
416
|
+
labels: string[][];
|
|
417
|
+
markup?: {
|
|
418
|
+
labels: Record<string, string>;
|
|
419
|
+
data: Markup[];
|
|
420
|
+
};
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
type OptionsWithDefaults<T> = {
|
|
424
|
+
options: ListOptionNormalized<T>[];
|
|
425
|
+
defaults: T[];
|
|
426
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ColorMap } from './types';
|
|
2
|
+
|
|
3
|
+
export type Markup = { id: string; start: number; length: number }[];
|
|
4
|
+
|
|
5
|
+
export function parseMarkup(row: string): Markup {
|
|
6
|
+
return Array.from(row.matchAll(
|
|
7
|
+
/(?<id>[^:]*):(?<start>[0-9A-Za-z]*)(?:\+(?<length>[0-9A-Za-z]*))?\|?/g,
|
|
8
|
+
)).map((match) => {
|
|
9
|
+
const matchGroups = match.groups as {
|
|
10
|
+
id: string;
|
|
11
|
+
start: string;
|
|
12
|
+
length: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
const start = Number.parseInt(matchGroups.start, 36);
|
|
15
|
+
const length = matchGroups.length
|
|
16
|
+
? Number.parseInt(matchGroups.length, 36)
|
|
17
|
+
: 0;
|
|
18
|
+
return {
|
|
19
|
+
id: matchGroups.id,
|
|
20
|
+
start,
|
|
21
|
+
length,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function markupAlignedSequence(
|
|
27
|
+
alignedSequence: string,
|
|
28
|
+
markup: Markup,
|
|
29
|
+
): Markup {
|
|
30
|
+
const indexMap = alignedSequence.split('').reduce<number[]>(
|
|
31
|
+
(acc, char, index) => {
|
|
32
|
+
if (char !== '-') acc.push(index);
|
|
33
|
+
return acc;
|
|
34
|
+
},
|
|
35
|
+
[],
|
|
36
|
+
);
|
|
37
|
+
const adjusted = markup.map((segment) => {
|
|
38
|
+
const start = indexMap[segment.start];
|
|
39
|
+
const end = indexMap[segment.start + segment.length - 1] + 1;
|
|
40
|
+
return {
|
|
41
|
+
id: segment.id,
|
|
42
|
+
start: start,
|
|
43
|
+
length: end - start,
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
return adjusted;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function colorizeSequencesByMarkup(
|
|
50
|
+
{ markupRows, columnCount, colorMap }: {
|
|
51
|
+
markupRows: Markup[];
|
|
52
|
+
columnCount: number;
|
|
53
|
+
colorMap: ColorMap;
|
|
54
|
+
},
|
|
55
|
+
): Promise<Blob> {
|
|
56
|
+
const canvas = new OffscreenCanvas(columnCount, markupRows.length);
|
|
57
|
+
const context = canvas.getContext('2d')!;
|
|
58
|
+
for (const [rowIndex, markup] of markupRows.entries()) {
|
|
59
|
+
for (const segment of markup) {
|
|
60
|
+
const color = colorMap[segment.id]?.color;
|
|
61
|
+
if (!color) continue;
|
|
62
|
+
context.fillStyle = color;
|
|
63
|
+
context.fillRect(segment.start, rowIndex, segment.length, 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return canvas.convertToBlob();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const markupColors = [
|
|
70
|
+
'#E5F2FF',
|
|
71
|
+
'#FFE8E8',
|
|
72
|
+
'#F0EBFF',
|
|
73
|
+
'#FFFFE3',
|
|
74
|
+
'#E5F7E5',
|
|
75
|
+
'#FEEAFE',
|
|
76
|
+
'#FDEED6',
|
|
77
|
+
'#E8FDFE',
|
|
78
|
+
'#CCDFF2',
|
|
79
|
+
'#F2CCCD',
|
|
80
|
+
'#D5CCF2',
|
|
81
|
+
'#F2F2CC',
|
|
82
|
+
'#CCF2CC',
|
|
83
|
+
'#F2CCF2',
|
|
84
|
+
'#EFDDBF',
|
|
85
|
+
'#DEEEEF',
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
if (import.meta.vitest) {
|
|
89
|
+
const { test, expect } = import.meta.vitest;
|
|
90
|
+
test('annotateAlignedRow', () => {
|
|
91
|
+
const alignedSequence
|
|
92
|
+
= 'EVRLVESGGALVQPGGSLRLSCVAASGFTFINNWVTWVRQAPGKGLEWVANIKEDGSQKYYVDSVKGRFTISRDNAEKSVYLQMSSLRVDDTAVYYCAR------------GRAV----D---QWGQGTLVTVSS';
|
|
93
|
+
// 0 10 20 30 40 50 60 70 80 90 100 110 120 130
|
|
94
|
+
// EVRLVESGGALVQPGGSLRLSCVAASGFTFINNWVTWVRQAPGKGLEWVANIKEDGSQKYYVDSVKGRFTISRDNAEKSVYLQMSSLRVDDTAVYYCARGRAVDQWGQGTLVTVSS
|
|
95
|
+
const markup = [
|
|
96
|
+
{ id: '1', start: 0, length: 99 },
|
|
97
|
+
{ id: '2', start: 99, length: 3 },
|
|
98
|
+
{ id: '3', start: 102, length: 14 },
|
|
99
|
+
];
|
|
100
|
+
const alignedMarkup = markupAlignedSequence(alignedSequence, markup);
|
|
101
|
+
expect(alignedMarkup).toEqual([
|
|
102
|
+
{ id: '1', start: 0, length: 99 },
|
|
103
|
+
{ id: '2', start: 111, length: 3 },
|
|
104
|
+
{ id: '3', start: 114, length: 21 },
|
|
105
|
+
]);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ColorSchemeOption } from './types';
|
|
2
2
|
|
|
3
3
|
export const defaultSettings = {
|
|
4
|
-
colorScheme: 'chemical-properties' as
|
|
4
|
+
colorScheme: { type: 'chemical-properties' } as ColorSchemeOption,
|
|
5
5
|
consensus: true,
|
|
6
6
|
seqLogo: true,
|
|
7
7
|
legend: true,
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import type { PObjectId } from '@platforma-sdk/model';
|
|
2
|
+
|
|
3
|
+
export type ColorSchemeOption =
|
|
4
|
+
| { type: 'no-color' }
|
|
5
|
+
| { type: 'chemical-properties' }
|
|
6
|
+
| { type: 'markup'; columnId: PObjectId };
|
|
7
|
+
|
|
8
|
+
export type ColorScheme = {
|
|
9
|
+
type: ColorSchemeOption['type'];
|
|
10
|
+
colors: ColorMap;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type ColorMap = Record<string, { label: string; color: string }>;
|
|
2
14
|
|
|
3
15
|
export type ResidueCounts = Record<string, number>[];
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ResidueCounts } from '../types';
|
|
2
|
-
import type { SegmentedColumn } from './types';
|
|
3
|
-
export declare const chemicalCategories: readonly ["hydrophobic", "positiveCharge", "negativeCharge", "polar", "cysteine", "glycine", "proline", "aromatic"];
|
|
4
|
-
export type ChemicalCategory = typeof chemicalCategories[number];
|
|
5
|
-
export declare const chemicalPropertiesLabels: Record<ChemicalCategory, string>;
|
|
6
|
-
export declare const chemicalPropertiesColors: Record<ChemicalCategory, string>;
|
|
7
|
-
type ColumnChemicalProperties = {
|
|
8
|
-
residues: string;
|
|
9
|
-
category: ChemicalCategory;
|
|
10
|
-
}[];
|
|
11
|
-
export declare const getColumnChemicalProperties: ({ residueCounts, rowCount }: {
|
|
12
|
-
residueCounts: ResidueCounts;
|
|
13
|
-
rowCount: number;
|
|
14
|
-
}) => ColumnChemicalProperties[];
|
|
15
|
-
export declare function alignedSequencesToSegmentedColumns({ alignedSequences, consensuses }: {
|
|
16
|
-
alignedSequences: string[];
|
|
17
|
-
consensuses: ColumnChemicalProperties[];
|
|
18
|
-
}): SegmentedColumn<ChemicalCategory>[];
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=chemical-properties.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chemical-properties.d.ts","sourceRoot":"","sources":["../../../../../src/components/PlMultiSequenceAlignment/highlight/chemical-properties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,kBAAkB,qHASrB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAEjE,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CASrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CASrE,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,EAAE,CAAC;AAEJ,eAAO,MAAM,2BAA2B,gCACT;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,KACA,wBAAwB,EAsBvB,CAAC;AAEL,wBAAgB,kCAAkC,CAChD,EAAE,gBAAgB,EAAE,WAAW,EAAE,EAAE;IACjC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,wBAAwB,EAAE,CAAC;CACzC,GACA,eAAe,CAAC,gBAAgB,CAAC,EAAE,CAuBrC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { SegmentedColumn } from './types';
|
|
2
|
-
export declare const colorizeSegmentedColumns: <T extends string>({ columns, rowCount, colors }: {
|
|
3
|
-
columns: SegmentedColumn<T>[];
|
|
4
|
-
rowCount: number;
|
|
5
|
-
colors: Record<T, string>;
|
|
6
|
-
}) => Blob;
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/PlMultiSequenceAlignment/highlight/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,MAAM,iCACxB;IAC7B,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;CAC3B,KACA,IAwBF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/PlMultiSequenceAlignment/highlight/types.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,CAAC,CAAC,IAAI;IACtB,QAAQ,EAAE,CAAC,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { SegmentedColumn } from './types';
|
|
2
|
-
|
|
3
|
-
export const colorizeSegmentedColumns = <T extends string>(
|
|
4
|
-
{ columns, rowCount, colors }: {
|
|
5
|
-
columns: SegmentedColumn<T>[];
|
|
6
|
-
rowCount: number;
|
|
7
|
-
colors: Record<T, string>;
|
|
8
|
-
},
|
|
9
|
-
): Blob => {
|
|
10
|
-
const pathsByColor: Record<string, string> = {};
|
|
11
|
-
for (const [columnIndex, column] of columns.entries()) {
|
|
12
|
-
for (const { category, start, end } of column) {
|
|
13
|
-
const color = colors[category];
|
|
14
|
-
pathsByColor[color] = (pathsByColor[color] ?? '').concat(
|
|
15
|
-
[
|
|
16
|
-
`M${columnIndex},${start}`,
|
|
17
|
-
'h1',
|
|
18
|
-
`v${end - start + 1}`,
|
|
19
|
-
'h-1',
|
|
20
|
-
'z',
|
|
21
|
-
].join(''),
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return new Blob([
|
|
26
|
-
`<svg viewBox="0 0 ${columns.length} ${rowCount}" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">`,
|
|
27
|
-
...Object.entries(pathsByColor).map(
|
|
28
|
-
([color, pathDefinition]) =>
|
|
29
|
-
`<path d="${pathDefinition}" fill="${color}" />`,
|
|
30
|
-
),
|
|
31
|
-
`</svg>`,
|
|
32
|
-
], { type: 'image/svg+xml' });
|
|
33
|
-
};
|