@platforma-sdk/ui-vue 1.45.35 → 1.45.37
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/.turbo/turbo-build.log +204 -235
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +13 -0
- package/dist/AgGridVue/useAgGridOptions.js +2 -3
- package/dist/AgGridVue/useAgGridOptions.js.map +1 -1
- package/dist/components/BlockLayout.vue2.js +3 -3
- package/dist/components/BlockLayout.vue2.js.map +1 -1
- package/dist/components/BlockLoader.vue.js.map +1 -1
- package/dist/components/LoaderPage.vue.js +2 -2
- package/dist/components/LoaderPage.vue.js.map +1 -1
- package/dist/components/NotFound.vue.js +3 -3
- package/dist/components/NotFound.vue.js.map +1 -1
- package/dist/components/PlAdvancedFilter/OperandButton.vue2.js.map +1 -1
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js +73 -73
- package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
- package/dist/components/PlAdvancedFilter/SingleFilter.vue2.js +100 -100
- package/dist/components/PlAdvancedFilter/SingleFilter.vue2.js.map +1 -1
- package/dist/components/PlAgCellFile/PlAgCellFile.vue.js.map +1 -1
- package/dist/components/PlAgCellProgress/PlAgCellProgress.vue.js.map +1 -1
- package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue.js +6 -6
- package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue.js.map +1 -1
- package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue.js.map +1 -1
- package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue.js.map +1 -1
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue.js +22 -22
- package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue.js.map +1 -1
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.js +3 -3
- package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue2.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js +50 -50
- package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue.js.map +1 -1
- package/dist/components/PlAgDataTable/PlAgRowCount.vue.js +7 -8
- package/dist/components/PlAgDataTable/PlAgRowCount.vue.js.map +1 -1
- package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js +35 -35
- package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js.map +1 -1
- package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js +16 -17
- package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js.map +1 -1
- package/dist/components/PlAgRowNumHeader.vue.js +14 -15
- package/dist/components/PlAgRowNumHeader.vue.js.map +1 -1
- package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue.js +16 -16
- package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue.js.map +1 -1
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js +6 -6
- package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/DynamicForm.vue2.js +57 -57
- package/dist/components/PlAnnotations/components/DynamicForm.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js +6 -6
- package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
- package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js.map +1 -1
- package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue.js +7 -7
- package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Item.vue2.js +23 -23
- package/dist/components/PlBtnExportArchive/Item.vue2.js.map +1 -1
- package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue2.js.map +1 -1
- package/dist/components/PlBtnExportArchive/Summary.vue2.js +22 -22
- package/dist/components/PlBtnExportArchive/Summary.vue2.js.map +1 -1
- package/dist/components/PlTableFilters/PlTableAddFilterV2.vue.js +9 -9
- package/dist/components/PlTableFilters/PlTableAddFilterV2.vue.js.map +1 -1
- package/dist/components/PlTableFilters/PlTableFilterEntryV2.vue.js +3 -3
- package/dist/components/PlTableFilters/PlTableFilterEntryV2.vue.js.map +1 -1
- package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js +9 -9
- package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
- package/dist/components/ValueOrErrorsComponent.vue.js.map +1 -1
- package/dist/index.js +48 -50
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +0 -1
- package/dist/plugins/Monetization/EndOfPeriod.vue2.js +9 -9
- package/dist/plugins/Monetization/EndOfPeriod.vue2.js.map +1 -1
- package/dist/plugins/Monetization/LimitCard.vue2.js +40 -40
- package/dist/plugins/Monetization/LimitCard.vue2.js.map +1 -1
- package/dist/plugins/Monetization/MonetizationSidebar.vue.js +3 -3
- package/dist/plugins/Monetization/MonetizationSidebar.vue.js.map +1 -1
- package/dist/plugins/Monetization/RunStatus.vue2.js +12 -12
- package/dist/plugins/Monetization/RunStatus.vue2.js.map +1 -1
- package/dist/plugins/Monetization/UserCabinetCard.vue2.js +22 -22
- package/dist/plugins/Monetization/UserCabinetCard.vue2.js.map +1 -1
- package/package.json +7 -8
- package/src/lib.ts +0 -2
- package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js +0 -6
- package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js.map +0 -1
- package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js +0 -5
- package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Consensus.vue.d.ts +0 -9
- package/dist/components/PlMultiSequenceAlignment/Consensus.vue.js +0 -10
- package/dist/components/PlMultiSequenceAlignment/Consensus.vue.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js +0 -122
- package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js +0 -9
- package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Legend.vue.d.ts +0 -6
- package/dist/components/PlMultiSequenceAlignment/Legend.vue.js +0 -10
- package/dist/components/PlMultiSequenceAlignment/Legend.vue.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js +0 -28
- package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Legend.vue3.js +0 -13
- package/dist/components/PlMultiSequenceAlignment/Legend.vue3.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.d.ts +0 -25
- package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.js +0 -10
- package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js +0 -138
- package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js +0 -31
- package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.d.ts +0 -8
- package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js +0 -10
- package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js +0 -77
- package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js +0 -9
- package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.d.ts +0 -71
- package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.js +0 -10
- package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js +0 -224
- package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue3.js +0 -9
- package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue3.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.d.ts +0 -8
- package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js +0 -10
- package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js +0 -127
- package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js +0 -9
- package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Toolbar.vue.d.ts +0 -16
- package/dist/components/PlMultiSequenceAlignment/Toolbar.vue.js +0 -10
- package/dist/components/PlMultiSequenceAlignment/Toolbar.vue.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js +0 -228
- package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/Toolbar.vue3.js +0 -19
- package/dist/components/PlMultiSequenceAlignment/Toolbar.vue3.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/cell-size.d.ts +0 -4
- package/dist/components/PlMultiSequenceAlignment/cell-size.js +0 -8
- package/dist/components/PlMultiSequenceAlignment/cell-size.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/chemical-properties.d.ts +0 -44
- package/dist/components/PlMultiSequenceAlignment/chemical-properties.js +0 -132
- package/dist/components/PlMultiSequenceAlignment/chemical-properties.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/data.d.ts +0 -61
- package/dist/components/PlMultiSequenceAlignment/data.js +0 -370
- package/dist/components/PlMultiSequenceAlignment/data.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/index.d.ts +0 -1
- package/dist/components/PlMultiSequenceAlignment/markup.d.ts +0 -16
- package/dist/components/PlMultiSequenceAlignment/markup.js +0 -84
- package/dist/components/PlMultiSequenceAlignment/markup.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/migrations.d.ts +0 -3
- package/dist/components/PlMultiSequenceAlignment/migrations.js +0 -24
- package/dist/components/PlMultiSequenceAlignment/migrations.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.d.ts +0 -6
- package/dist/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.d.ts +0 -7
- package/dist/components/PlMultiSequenceAlignment/residue-counts.d.ts +0 -2
- package/dist/components/PlMultiSequenceAlignment/residue-counts.js +0 -13
- package/dist/components/PlMultiSequenceAlignment/residue-counts.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/settings.d.ts +0 -2
- package/dist/components/PlMultiSequenceAlignment/settings.js +0 -9
- package/dist/components/PlMultiSequenceAlignment/settings.js.map +0 -1
- package/dist/components/PlMultiSequenceAlignment/types.d.ts +0 -5
- package/dist/components/PlMultiSequenceAlignment/useMiPlots.d.ts +0 -4
- package/dist/components/PlMultiSequenceAlignment/useMiPlots.js +0 -19
- package/dist/components/PlMultiSequenceAlignment/useMiPlots.js.map +0 -1
- package/src/components/PlMultiSequenceAlignment/Consensus.vue +0 -165
- package/src/components/PlMultiSequenceAlignment/Legend.vue +0 -44
- package/src/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue +0 -299
- package/src/components/PlMultiSequenceAlignment/PhylogeneticTree.vue +0 -110
- package/src/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue +0 -314
- package/src/components/PlMultiSequenceAlignment/README.md +0 -216
- package/src/components/PlMultiSequenceAlignment/SeqLogo.vue +0 -166
- package/src/components/PlMultiSequenceAlignment/Toolbar.vue +0 -228
- package/src/components/PlMultiSequenceAlignment/cell-size.ts +0 -4
- package/src/components/PlMultiSequenceAlignment/chemical-properties.ts +0 -199
- package/src/components/PlMultiSequenceAlignment/data.ts +0 -661
- package/src/components/PlMultiSequenceAlignment/index.ts +0 -1
- package/src/components/PlMultiSequenceAlignment/markup.ts +0 -141
- package/src/components/PlMultiSequenceAlignment/migrations.ts +0 -46
- package/src/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.ts +0 -54
- package/src/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.ts +0 -89
- package/src/components/PlMultiSequenceAlignment/residue-counts.ts +0 -124
- package/src/components/PlMultiSequenceAlignment/settings.ts +0 -7
- package/src/components/PlMultiSequenceAlignment/types.ts +0 -3
- package/src/components/PlMultiSequenceAlignment/useMiPlots.ts +0 -23
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { isJsonEqual } from '@milaboratories/helpers';
|
|
3
|
-
import {
|
|
4
|
-
type ListOptionNormalized,
|
|
5
|
-
PlAlert,
|
|
6
|
-
PlSplash,
|
|
7
|
-
} from '@milaboratories/uikit';
|
|
8
|
-
import {
|
|
9
|
-
getRawPlatformaInstance,
|
|
10
|
-
type PColumnPredicate,
|
|
11
|
-
type PFrameHandle,
|
|
12
|
-
type PlMultiSequenceAlignmentColorSchemeOption,
|
|
13
|
-
type PlMultiSequenceAlignmentModel,
|
|
14
|
-
type PlMultiSequenceAlignmentSettings,
|
|
15
|
-
type PlSelectionModel,
|
|
16
|
-
} from '@platforma-sdk/model';
|
|
17
|
-
import {
|
|
18
|
-
computed,
|
|
19
|
-
onBeforeMount,
|
|
20
|
-
onUnmounted,
|
|
21
|
-
reactive,
|
|
22
|
-
useCssModule,
|
|
23
|
-
useTemplateRef,
|
|
24
|
-
watchEffect,
|
|
25
|
-
} from 'vue';
|
|
26
|
-
import {
|
|
27
|
-
SEQUENCE_LIMIT,
|
|
28
|
-
useLabelColumnsOptions,
|
|
29
|
-
useMarkupColumnsOptions,
|
|
30
|
-
useMultipleAlignmentData,
|
|
31
|
-
useSequenceColumnsOptions,
|
|
32
|
-
} from './data';
|
|
33
|
-
import { runMigrations } from './migrations';
|
|
34
|
-
import MultiSequenceAlignmentView from './MultiSequenceAlignmentView.vue';
|
|
35
|
-
import { defaultSettings } from './settings';
|
|
36
|
-
import Toolbar from './Toolbar.vue';
|
|
37
|
-
|
|
38
|
-
const model = defineModel<PlMultiSequenceAlignmentModel>({ default: {} });
|
|
39
|
-
|
|
40
|
-
onBeforeMount(() => {
|
|
41
|
-
runMigrations(model);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const settings = reactive<PlMultiSequenceAlignmentSettings>({
|
|
45
|
-
...defaultSettings,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const props = defineProps<{
|
|
49
|
-
/**
|
|
50
|
-
* Handle to PFrame created using `createPFrameForGraphs`.
|
|
51
|
-
* Should contain all desired sequence and label columns.
|
|
52
|
-
*/
|
|
53
|
-
readonly pFrame: PFrameHandle | undefined;
|
|
54
|
-
/**
|
|
55
|
-
* Return true if column should be shown in sequence columns dropdown.
|
|
56
|
-
* By default, all sequence columns are selected.
|
|
57
|
-
*/
|
|
58
|
-
readonly sequenceColumnPredicate: PColumnPredicate;
|
|
59
|
-
/**
|
|
60
|
-
* Row selection model (from `PlAgDataTableV2` or `GraphMaker`).
|
|
61
|
-
* If not provided or empty, all rows will be considered selected.
|
|
62
|
-
* Warning: should be forwarded as a field of `reactive` object
|
|
63
|
-
*/
|
|
64
|
-
readonly selection?: PlSelectionModel;
|
|
65
|
-
}>();
|
|
66
|
-
|
|
67
|
-
const classes = useCssModule();
|
|
68
|
-
|
|
69
|
-
const sequenceColumns = reactive(useSequenceColumnsOptions(() => ({
|
|
70
|
-
pFrame: props.pFrame,
|
|
71
|
-
sequenceColumnPredicate: props.sequenceColumnPredicate,
|
|
72
|
-
})));
|
|
73
|
-
|
|
74
|
-
const labelColumns = reactive(useLabelColumnsOptions(() => ({
|
|
75
|
-
pFrame: props.pFrame,
|
|
76
|
-
sequenceColumnIds: settings.sequenceColumnIds,
|
|
77
|
-
})));
|
|
78
|
-
|
|
79
|
-
const markupColumns = reactive(useMarkupColumnsOptions(() => ({
|
|
80
|
-
pFrame: props.pFrame,
|
|
81
|
-
sequenceColumnIds: settings.sequenceColumnIds,
|
|
82
|
-
})));
|
|
83
|
-
|
|
84
|
-
const multipleAlignmentData = reactive(useMultipleAlignmentData(() => ({
|
|
85
|
-
pFrame: props.pFrame,
|
|
86
|
-
sequenceColumnIds: settings.sequenceColumnIds,
|
|
87
|
-
labelColumnIds: settings.labelColumnIds,
|
|
88
|
-
selection: props.selection,
|
|
89
|
-
colorScheme: settings.colorScheme,
|
|
90
|
-
alignmentParams: settings.alignmentParams,
|
|
91
|
-
shouldBuildPhylogeneticTree: settings.widgets.includes('tree'),
|
|
92
|
-
})));
|
|
93
|
-
|
|
94
|
-
const formatNumber = new Intl.NumberFormat('en').format;
|
|
95
|
-
|
|
96
|
-
const colorSchemeOptions = computed<
|
|
97
|
-
ListOptionNormalized<PlMultiSequenceAlignmentColorSchemeOption>[]
|
|
98
|
-
>(
|
|
99
|
-
() => [
|
|
100
|
-
{
|
|
101
|
-
label: 'Chemical Properties',
|
|
102
|
-
value: { type: 'chemical-properties' },
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
label: 'No Color',
|
|
106
|
-
value: { type: 'no-color' },
|
|
107
|
-
},
|
|
108
|
-
...(markupColumns.data ?? []).map(({ label, value }) => ({
|
|
109
|
-
label,
|
|
110
|
-
value: {
|
|
111
|
-
type: 'markup' as const,
|
|
112
|
-
columnIds: value,
|
|
113
|
-
},
|
|
114
|
-
})),
|
|
115
|
-
],
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
const error = computed(() =>
|
|
119
|
-
sequenceColumns.error
|
|
120
|
-
?? labelColumns.error
|
|
121
|
-
?? markupColumns.error
|
|
122
|
-
?? multipleAlignmentData.error,
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
function applySettings(
|
|
126
|
-
settingsPatch: Partial<PlMultiSequenceAlignmentSettings>,
|
|
127
|
-
) {
|
|
128
|
-
model.value = Object.fromEntries(
|
|
129
|
-
Object.entries({ ...model.value, ...settingsPatch })
|
|
130
|
-
.filter(([_key, value]) => value !== undefined),
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
watchEffect(() => {
|
|
135
|
-
const patch: Partial<PlMultiSequenceAlignmentSettings> = Object.fromEntries(
|
|
136
|
-
Object.entries({
|
|
137
|
-
...defaultSettings,
|
|
138
|
-
sequenceColumnIds: sequenceColumns.data?.defaults,
|
|
139
|
-
labelColumnIds: labelColumns.data?.defaults,
|
|
140
|
-
...model.value,
|
|
141
|
-
}).filter(([key, value]) =>
|
|
142
|
-
!isJsonEqual(
|
|
143
|
-
settings[key as keyof PlMultiSequenceAlignmentSettings],
|
|
144
|
-
value,
|
|
145
|
-
),
|
|
146
|
-
),
|
|
147
|
-
);
|
|
148
|
-
Object.assign(settings, patch);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// Reset stale settings
|
|
152
|
-
watchEffect(() => {
|
|
153
|
-
const settingsToReset: (keyof PlMultiSequenceAlignmentSettings)[] = [];
|
|
154
|
-
if (
|
|
155
|
-
!sequenceColumns.isLoading
|
|
156
|
-
&& settings.sequenceColumnIds?.some((id) =>
|
|
157
|
-
(sequenceColumns.data?.options ?? []).every(
|
|
158
|
-
({ value }) => !isJsonEqual(value, id),
|
|
159
|
-
),
|
|
160
|
-
)
|
|
161
|
-
) {
|
|
162
|
-
settingsToReset.push('sequenceColumnIds');
|
|
163
|
-
}
|
|
164
|
-
if (
|
|
165
|
-
!labelColumns.isLoading
|
|
166
|
-
&& settings.labelColumnIds?.some((id) =>
|
|
167
|
-
(labelColumns.data?.options ?? []).every(
|
|
168
|
-
({ value }) => !isJsonEqual(value, id),
|
|
169
|
-
),
|
|
170
|
-
)
|
|
171
|
-
) {
|
|
172
|
-
settingsToReset.push('labelColumnIds');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const markupColumnIds = settings.colorScheme?.type === 'markup'
|
|
176
|
-
? settings.colorScheme.columnIds
|
|
177
|
-
: undefined;
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
-
!markupColumns.isLoading
|
|
181
|
-
&& markupColumnIds
|
|
182
|
-
&& (markupColumns.data ?? []).every(
|
|
183
|
-
({ value }) => !isJsonEqual(value, markupColumnIds),
|
|
184
|
-
)
|
|
185
|
-
) {
|
|
186
|
-
settingsToReset.push('colorScheme');
|
|
187
|
-
}
|
|
188
|
-
if (settingsToReset.length) {
|
|
189
|
-
applySettings(Object.fromEntries(
|
|
190
|
-
settingsToReset.map((key) => [key, undefined]),
|
|
191
|
-
));
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const msaEl = useTemplateRef('msa');
|
|
196
|
-
|
|
197
|
-
async function exportPdf() {
|
|
198
|
-
const exportToPdf = getRawPlatformaInstance()?.lsDriver
|
|
199
|
-
?.exportToPdf;
|
|
200
|
-
if (!exportToPdf) {
|
|
201
|
-
return console.error(
|
|
202
|
-
'API getPlatformaRawInstance().lsDriver.exportToPdf is not available',
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
const msaRoot = msaEl.value?.rootEl;
|
|
206
|
-
if (!msaRoot) {
|
|
207
|
-
throw new Error('MSA element is not available.');
|
|
208
|
-
}
|
|
209
|
-
const printTarget = document.createElement('div');
|
|
210
|
-
printTarget.id = `print-target-${crypto.randomUUID()}`;
|
|
211
|
-
const printStyleSheet = new CSSStyleSheet();
|
|
212
|
-
document.adoptedStyleSheets.push(printStyleSheet);
|
|
213
|
-
printStyleSheet.insertRule(`
|
|
214
|
-
@media screen {
|
|
215
|
-
#${printTarget.id} {
|
|
216
|
-
visibility: hidden;
|
|
217
|
-
position: fixed;
|
|
218
|
-
}
|
|
219
|
-
}`);
|
|
220
|
-
const msaClone = msaRoot.cloneNode(true) as HTMLElement;
|
|
221
|
-
msaClone.dataset.prePrint = '';
|
|
222
|
-
printTarget.replaceChildren(msaClone);
|
|
223
|
-
document.body.appendChild(printTarget);
|
|
224
|
-
const { height, width } = printTarget.getBoundingClientRect();
|
|
225
|
-
const margin = CSS.cm(1);
|
|
226
|
-
const pageSize = [width, height]
|
|
227
|
-
.map((value) => CSS.px(value).add(margin.mul(2)))
|
|
228
|
-
.join(' ');
|
|
229
|
-
printStyleSheet.insertRule(`
|
|
230
|
-
@media print {
|
|
231
|
-
@page {
|
|
232
|
-
size: ${pageSize};
|
|
233
|
-
margin: ${margin};
|
|
234
|
-
}
|
|
235
|
-
body > :not(#${printTarget.id}) {
|
|
236
|
-
display: none;
|
|
237
|
-
}
|
|
238
|
-
}`);
|
|
239
|
-
try {
|
|
240
|
-
await exportToPdf();
|
|
241
|
-
} catch (error) {
|
|
242
|
-
console.error(error);
|
|
243
|
-
} finally {
|
|
244
|
-
document.body.removeChild(printTarget);
|
|
245
|
-
const index = document.adoptedStyleSheets.indexOf(printStyleSheet);
|
|
246
|
-
if (index >= 0) {
|
|
247
|
-
document.adoptedStyleSheets.splice(index, 1);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
onUnmounted(() => {
|
|
253
|
-
multipleAlignmentData.data = undefined;
|
|
254
|
-
});
|
|
255
|
-
</script>
|
|
256
|
-
|
|
257
|
-
<template>
|
|
258
|
-
<Toolbar
|
|
259
|
-
:settings="settings"
|
|
260
|
-
:sequence-column-options="sequenceColumns.data?.options"
|
|
261
|
-
:label-column-options="labelColumns.data?.options"
|
|
262
|
-
:color-scheme-options="colorSchemeOptions"
|
|
263
|
-
@update-settings="applySettings"
|
|
264
|
-
@export="exportPdf"
|
|
265
|
-
/>
|
|
266
|
-
<PlAlert v-if="error" type="error">
|
|
267
|
-
{{ error }}
|
|
268
|
-
</PlAlert>
|
|
269
|
-
<PlAlert
|
|
270
|
-
v-else-if="!multipleAlignmentData.isLoading && !multipleAlignmentData.data"
|
|
271
|
-
type="warn"
|
|
272
|
-
icon
|
|
273
|
-
>
|
|
274
|
-
Please select at least one sequence column and two or more rows to run
|
|
275
|
-
alignment
|
|
276
|
-
</PlAlert>
|
|
277
|
-
<template v-else>
|
|
278
|
-
<PlAlert
|
|
279
|
-
v-if="multipleAlignmentData.data?.exceedsLimit"
|
|
280
|
-
type="warn"
|
|
281
|
-
icon
|
|
282
|
-
label="Visualization is limited"
|
|
283
|
-
>
|
|
284
|
-
MSA visualization supports {{ formatNumber(2) }} to
|
|
285
|
-
{{ formatNumber(SEQUENCE_LIMIT) }} sequences. Only the first
|
|
286
|
-
{{ formatNumber(SEQUENCE_LIMIT) }} will be displayed.
|
|
287
|
-
</PlAlert>
|
|
288
|
-
<PlSplash
|
|
289
|
-
type="transparent"
|
|
290
|
-
:class="classes.splash"
|
|
291
|
-
:loading="multipleAlignmentData.isLoading"
|
|
292
|
-
>
|
|
293
|
-
<MultiSequenceAlignmentView
|
|
294
|
-
v-if="multipleAlignmentData.data"
|
|
295
|
-
ref="msa"
|
|
296
|
-
:sequences="multipleAlignmentData.data.sequences"
|
|
297
|
-
:labels="multipleAlignmentData.data.labels"
|
|
298
|
-
:highlight-legend="multipleAlignmentData.data.highlightLegend"
|
|
299
|
-
:phylogenetic-tree="multipleAlignmentData.data.phylogeneticTree"
|
|
300
|
-
:widgets="settings.widgets"
|
|
301
|
-
/>
|
|
302
|
-
</PlSplash>
|
|
303
|
-
</template>
|
|
304
|
-
</template>
|
|
305
|
-
|
|
306
|
-
<style module>
|
|
307
|
-
.splash {
|
|
308
|
-
flex: 1;
|
|
309
|
-
display: flex;
|
|
310
|
-
flex-direction: column;
|
|
311
|
-
gap: 12px;
|
|
312
|
-
overflow: hidden;
|
|
313
|
-
}
|
|
314
|
-
</style>
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
# `PlMultiSequenceAlignment`
|
|
2
|
-
|
|
3
|
-
The name of the component is usually shortened to MSA.
|
|
4
|
-
|
|
5
|
-
For the design, see
|
|
6
|
-
https://www.figma.com/design/pndFzfW2eqdIWfA8IoraMg/%F0%9F%A7%AC-MSA?t=LRoRiHQhyga7Ndzx-0.
|
|
7
|
-
|
|
8
|
-
## Structure
|
|
9
|
-
|
|
10
|
-
### PlMultiSequenceAlignment
|
|
11
|
-
|
|
12
|
-
Defined in `PlMultiSequenceAlignment.vue`.
|
|
13
|
-
|
|
14
|
-
This component is a "wrapper" that takes supplied data, runs data fetchers from
|
|
15
|
-
`data.ts` and draws `<MultiSequenceAlignmentView />`. It also draws a
|
|
16
|
-
`<Toolbar />` and is responsible for loading and error states.
|
|
17
|
-
|
|
18
|
-
The inputs are:
|
|
19
|
-
|
|
20
|
-
- `pFrame`
|
|
21
|
-
- `sequenceColumnPredicate`: predicate function by which the component filters
|
|
22
|
-
the columns to find only the sequence columns
|
|
23
|
-
- `selection`: `PlSelectionModel` that is returned from GraphMaker,
|
|
24
|
-
PlAgDataTable or potentially some other component, indicates which rows should
|
|
25
|
-
be selected from the columns
|
|
26
|
-
- `modelValue`: a storage for MSA settings
|
|
27
|
-
|
|
28
|
-
The settings for MSA are derived from `modelValue`, filling the `undefined` gaps
|
|
29
|
-
with default settings (defined in `settings.ts`).
|
|
30
|
-
|
|
31
|
-
### MultiSequenceAlignmentView
|
|
32
|
-
|
|
33
|
-
Defined in `MultiSequenceAlignmentView.vue`.
|
|
34
|
-
|
|
35
|
-
This is the presentational part, where most of the rendering is happening. It's
|
|
36
|
-
meant to have as little logic as possible to prevent the out-of-sync states. The
|
|
37
|
-
rendering is optimized to be as much monospace text-only as possible, with
|
|
38
|
-
[highlighting](#highlighting-color-scheme) implemented as a background image. A
|
|
39
|
-
lot of the rendering relies on the specific dimensions of the font. Gaps between
|
|
40
|
-
letters are implemented with `letter-spacing`.
|
|
41
|
-
|
|
42
|
-
### Data
|
|
43
|
-
|
|
44
|
-
Defined in `data.ts`.
|
|
45
|
-
|
|
46
|
-
This is MSA data fetcher that is split between 4 Vue composables:
|
|
47
|
-
|
|
48
|
-
- `useSequenceColumnsOptions`
|
|
49
|
-
- `useLabelColumnsOptions`
|
|
50
|
-
- `useMarkupColumnsOptions`
|
|
51
|
-
- `useMultipleAlignmentData`
|
|
52
|
-
|
|
53
|
-
First 3 composable are very similar. They take a list of columns from
|
|
54
|
-
`pFrameDriver.listColumns(pFrame)` and return all the options that would be
|
|
55
|
-
reasonable for the user to be able to choose from.
|
|
56
|
-
|
|
57
|
-
`useSequenceColumnsOptions` and `useLabelColumnsOptions` specifically also
|
|
58
|
-
return a list of default options that are preselected for the user.
|
|
59
|
-
|
|
60
|
-
`useMultipleAlignmentData` does the actual computation. It runs
|
|
61
|
-
`pFrameDriver.calculateTableData`, `multiSequenceAlignment`, highlighting and
|
|
62
|
-
returns data in this format:
|
|
63
|
-
|
|
64
|
-
- `sequences`: list of sequences rows, aligned and concatenated with a single
|
|
65
|
-
whitespace (`["<r0c0> <r0c1>", "<r1c0> <r1c1>", ...]`; "r"—row, "c"—column);
|
|
66
|
-
every row is the same length
|
|
67
|
-
- `sequenceNames`: list of sequence names, should match the names of the options
|
|
68
|
-
in a dropdown, which user selected
|
|
69
|
-
- `labelRows`: list of lists of labels,
|
|
70
|
-
(`[["<r0l0>", "<r0l1>", ...], ["<r1l0>", "<r1l1>", ...]]`, "r"—row, "l"—label)
|
|
71
|
-
- `residueCounts`: see [Residue counts](#residue-counts)
|
|
72
|
-
- `highlightImage`: optional, see [Highlighting](#highlighting-color-scheme)
|
|
73
|
-
- `exceedsLimit`: see [Row limit](#row-limit)
|
|
74
|
-
|
|
75
|
-
Most of the data generated by it is in the format that is useful for
|
|
76
|
-
`<MultiSequenceAlignmentView />`.
|
|
77
|
-
|
|
78
|
-
### Highlighting (Color Scheme)
|
|
79
|
-
|
|
80
|
-
There are two ways to colorize the MSA output. Both output a
|
|
81
|
-
[Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) that is an SVG
|
|
82
|
-
file which is later scaled up to fit the table layout. Current implementation
|
|
83
|
-
uses <path> tags to group multiple runs of the same color. The viewbox is
|
|
84
|
-
doubled in one of the directions to use SVG strokes without resorting to
|
|
85
|
-
fractional positions.
|
|
86
|
-
|
|
87
|
-
There's also an option to not colorize the output at all.
|
|
88
|
-
|
|
89
|
-
#### Chemical properties
|
|
90
|
-
|
|
91
|
-
Defined in `chemical-properties.ts`.
|
|
92
|
-
|
|
93
|
-
This is an implementation of Clustal X color scheme. See
|
|
94
|
-
https://www.jalview.org/help/html/colourSchemes/clustal.html and
|
|
95
|
-
https://www.rbvi.ucsf.edu/chimera/1.2065/docs/ContributedSoftware/multalignviewer/cxcolor.html
|
|
96
|
-
for reference.
|
|
97
|
-
|
|
98
|
-
#### Markup
|
|
99
|
-
|
|
100
|
-
Defined in `markup.ts`.
|
|
101
|
-
|
|
102
|
-
This color scheme highlights the parts of sequences that have a special meaning.
|
|
103
|
-
Markup format looks like `<id_0>:<start_0>+<length_0>|<id_1>:<start_1>|...`,
|
|
104
|
-
where `start` and `length` are encoded as base-36 numbers. `length` is optional,
|
|
105
|
-
and is 1 by default. Markup entries can overlap, although right now it's not
|
|
106
|
-
really handled in the UI. IDs bear no special meaning, and can be used in the UI
|
|
107
|
-
directly, or the labels can be looked up in the
|
|
108
|
-
`pl7.app/sequence/annotation/mapping` annotation of the markup column.
|
|
109
|
-
|
|
110
|
-
For example, a string `1:P+A|2:1G+7|3:2O+D` encodes this markup:
|
|
111
|
-
|
|
112
|
-
| id | start | length |
|
|
113
|
-
| -- | ----- | ------ |
|
|
114
|
-
| 1 | 25 | 10 |
|
|
115
|
-
| 2 | 52 | 7 |
|
|
116
|
-
| 3 | 96 | 13 |
|
|
117
|
-
|
|
118
|
-
Note that the markup itself is for an original sequence, not an aligned one. So
|
|
119
|
-
it needs to be adjusted for an aligned sequence (see function
|
|
120
|
-
`markupAlignedSequence`).
|
|
121
|
-
|
|
122
|
-
### Alignment
|
|
123
|
-
|
|
124
|
-
Defined in `multi-sequence-alignment.ts`.
|
|
125
|
-
|
|
126
|
-
To run the actual alignment, MSA component uses
|
|
127
|
-
(kalign)[https://github.com/TimoLassmann/kalign]. It is used as a WASM binary
|
|
128
|
-
through a (Web
|
|
129
|
-
Worker)[https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker].
|
|
130
|
-
Currently, the source is (biowasm)[https://biowasm.com/cdn/v3/kalign/3.3.1],
|
|
131
|
-
which we repackaged to work bundled and without a CDN.
|
|
132
|
-
|
|
133
|
-
The worker is reused between multiple calls. The results are cached by input
|
|
134
|
-
sequences and alignment params.
|
|
135
|
-
|
|
136
|
-
### Widgets
|
|
137
|
-
|
|
138
|
-
#### Consensus
|
|
139
|
-
|
|
140
|
-
Defined in `Consensus.vue`.
|
|
141
|
-
|
|
142
|
-
This widget visualizes the most used residue in a column using `miplots4`'s
|
|
143
|
-
`discrete` plot with a `bar` layer.
|
|
144
|
-
|
|
145
|
-
#### SeqLogo
|
|
146
|
-
|
|
147
|
-
Defined in `SeqLogo.vue`.
|
|
148
|
-
|
|
149
|
-
For reference, see https://ivanek.github.io/seqLogo/articles/seqLogo.html. This
|
|
150
|
-
is rendered using `miplots4`'s `discrete` plot with a `logo` layer.
|
|
151
|
-
|
|
152
|
-
#### Legend
|
|
153
|
-
|
|
154
|
-
Defined in `Legend.vue`.
|
|
155
|
-
|
|
156
|
-
Legend for a selected color scheme.
|
|
157
|
-
|
|
158
|
-
### Toolbar
|
|
159
|
-
|
|
160
|
-
Defined in `Toolbar.vue`.
|
|
161
|
-
|
|
162
|
-
Displays the current (settings)[#settings]. Updates to settings are applied to
|
|
163
|
-
model, from which the settings are re-derived afterwards.
|
|
164
|
-
|
|
165
|
-
### Residue counts
|
|
166
|
-
|
|
167
|
-
Defined in `residue-counts.ts`.
|
|
168
|
-
|
|
169
|
-
Supplemental data for [chemical properties](#chemical-properties) color scheme,
|
|
170
|
-
[Consensus](#consensus) and [SeqLogo](#seqlogo) widgets. Simply counts how many
|
|
171
|
-
times each residue was used in a column.
|
|
172
|
-
|
|
173
|
-
### Settings
|
|
174
|
-
|
|
175
|
-
Defined in `settings.ts`.
|
|
176
|
-
|
|
177
|
-
Derived from the `PlMultiSequenceAlignmentModel`, providing defaults for
|
|
178
|
-
`undefined` fields in a model.
|
|
179
|
-
|
|
180
|
-
- `sequenceColumnIds`: defines which sequence columns should be displayed
|
|
181
|
-
- `labelColumnIds`: defines which label columns should be displayed
|
|
182
|
-
- `colorScheme`: defined which [Color scheme](#highlighting-color-scheme) should
|
|
183
|
-
be used for output highlighting
|
|
184
|
-
- `widgets`: defines which [Widgets](#widgets) to display
|
|
185
|
-
- `alignmentParams`: params that are used for [kalign](#alignment); currently
|
|
186
|
-
`gpo`, `gpe` and `tgpe`
|
|
187
|
-
|
|
188
|
-
Technically, `sequenceColumnIds` and `labelColumnIds` shouldn't be optional, but
|
|
189
|
-
they are implemented as such because the defaults are fetched when the
|
|
190
|
-
`PlMultiSequenceAlignment` component renders.
|
|
191
|
-
|
|
192
|
-
### Migrations
|
|
193
|
-
|
|
194
|
-
Defined in `migrations.ts`.
|
|
195
|
-
|
|
196
|
-
Defines migrations to run for the MSA model before anything is rendered. Useful
|
|
197
|
-
when model format is changed and to upgrade an empty model to one with a
|
|
198
|
-
version. Also, the simplest way to reset all the MSA settings would be to set
|
|
199
|
-
the model to `{}` and run migrations.
|
|
200
|
-
|
|
201
|
-
### `useMiPlots.ts`
|
|
202
|
-
|
|
203
|
-
A helper to import `miplots4` dependency dynamically to avoid blowing up the
|
|
204
|
-
bundle. Probably should be moved outside this component at some point.
|
|
205
|
-
|
|
206
|
-
## Notes
|
|
207
|
-
|
|
208
|
-
### Row limit
|
|
209
|
-
|
|
210
|
-
There's an agreed upon limit of 1,000 rows, over which the alignment won't be
|
|
211
|
-
run. This limit is artificial, but it prevents a user from running a computation
|
|
212
|
-
that might be too heavy, especially given that at the moment there's no way to
|
|
213
|
-
terminate the alignment process.
|
|
214
|
-
|
|
215
|
-
This limit is imposed on `useMultipleAlignmentData`
|
|
216
|
-
/`pFrameDriver.calculateTableData` level.
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import type {
|
|
3
|
-
ChartInterface,
|
|
4
|
-
DataByColumns,
|
|
5
|
-
Settings,
|
|
6
|
-
} from '@milaboratories/miplots4';
|
|
7
|
-
import { PlAlert } from '@milaboratories/uikit';
|
|
8
|
-
import {
|
|
9
|
-
computed,
|
|
10
|
-
onBeforeUnmount,
|
|
11
|
-
shallowRef,
|
|
12
|
-
useCssModule,
|
|
13
|
-
useTemplateRef,
|
|
14
|
-
watchEffect,
|
|
15
|
-
} from 'vue';
|
|
16
|
-
import { cellSize } from './cell-size';
|
|
17
|
-
import type { ResidueCounts } from './types';
|
|
18
|
-
import { useMiPlots } from './useMiPlots';
|
|
19
|
-
|
|
20
|
-
const props = defineProps<{
|
|
21
|
-
residueCounts: ResidueCounts;
|
|
22
|
-
}>();
|
|
23
|
-
|
|
24
|
-
const classes = useCssModule();
|
|
25
|
-
|
|
26
|
-
const plotEl = useTemplateRef('plotEl');
|
|
27
|
-
|
|
28
|
-
const palette = {
|
|
29
|
-
blue: '#549EE7',
|
|
30
|
-
red: '#E85456',
|
|
31
|
-
green: '#65BF65',
|
|
32
|
-
magenta: '#9178E1',
|
|
33
|
-
pink: '#D568D5',
|
|
34
|
-
orange: '#C59445',
|
|
35
|
-
cyan: '#62C7CC',
|
|
36
|
-
yellow: '#D5D549',
|
|
37
|
-
black: '#000000',
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const residueColors = {
|
|
41
|
-
A: palette.blue,
|
|
42
|
-
R: palette.red,
|
|
43
|
-
N: palette.green,
|
|
44
|
-
D: palette.magenta,
|
|
45
|
-
C: palette.pink,
|
|
46
|
-
Q: palette.green,
|
|
47
|
-
E: palette.magenta,
|
|
48
|
-
G: palette.orange,
|
|
49
|
-
H: palette.cyan,
|
|
50
|
-
I: palette.blue,
|
|
51
|
-
L: palette.blue,
|
|
52
|
-
K: palette.red,
|
|
53
|
-
M: palette.blue,
|
|
54
|
-
F: palette.blue,
|
|
55
|
-
P: palette.yellow,
|
|
56
|
-
S: palette.green,
|
|
57
|
-
T: palette.green,
|
|
58
|
-
W: palette.blue,
|
|
59
|
-
Y: palette.cyan,
|
|
60
|
-
V: palette.blue,
|
|
61
|
-
B: palette.black,
|
|
62
|
-
X: palette.black,
|
|
63
|
-
Z: palette.black,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const settings = computed(() => ({
|
|
67
|
-
type: 'discrete',
|
|
68
|
-
title: {
|
|
69
|
-
name: '',
|
|
70
|
-
show: false,
|
|
71
|
-
},
|
|
72
|
-
size: {
|
|
73
|
-
width: props.residueCounts.length * cellSize.inline,
|
|
74
|
-
height: 80,
|
|
75
|
-
innerOffset: 0,
|
|
76
|
-
outerOffset: 0,
|
|
77
|
-
},
|
|
78
|
-
frame: {
|
|
79
|
-
type: 'empty',
|
|
80
|
-
},
|
|
81
|
-
xAxis: {
|
|
82
|
-
title: '',
|
|
83
|
-
showGrid: false,
|
|
84
|
-
showTicks: false,
|
|
85
|
-
hiddenLabels: true,
|
|
86
|
-
},
|
|
87
|
-
yAxis: {
|
|
88
|
-
title: '',
|
|
89
|
-
showGrid: false,
|
|
90
|
-
showTicks: false,
|
|
91
|
-
hiddenLabels: true,
|
|
92
|
-
},
|
|
93
|
-
y: {
|
|
94
|
-
type: 'column',
|
|
95
|
-
value: 'countKey',
|
|
96
|
-
},
|
|
97
|
-
primaryGrouping: {
|
|
98
|
-
columnName: {
|
|
99
|
-
type: 'column',
|
|
100
|
-
value: 'columnKey',
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
secondaryGrouping: {
|
|
104
|
-
columnName: {
|
|
105
|
-
type: 'column',
|
|
106
|
-
value: 'residueKey',
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
layers: [{
|
|
110
|
-
type: 'logo',
|
|
111
|
-
aes: { fillColor: residueColors },
|
|
112
|
-
}],
|
|
113
|
-
} satisfies Settings));
|
|
114
|
-
|
|
115
|
-
const data = computed<DataByColumns>(() => {
|
|
116
|
-
const countKey: number[] = [];
|
|
117
|
-
const columnKey: number[] = [];
|
|
118
|
-
const residueKey: string[] = [];
|
|
119
|
-
for (const [columnIndex, column] of props.residueCounts.entries()) {
|
|
120
|
-
for (const [residue, count] of Object.entries(column)) {
|
|
121
|
-
if (residue === '-') continue;
|
|
122
|
-
countKey.push(count);
|
|
123
|
-
columnKey.push(columnIndex);
|
|
124
|
-
residueKey.push(residue);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return ({
|
|
128
|
-
type: 'columns',
|
|
129
|
-
id: `seq-logo-${crypto.randomUUID()}`,
|
|
130
|
-
values: { countKey, columnKey, residueKey },
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const { miplots, error } = useMiPlots();
|
|
135
|
-
|
|
136
|
-
const plot = shallowRef<ChartInterface>();
|
|
137
|
-
|
|
138
|
-
watchEffect(async () => {
|
|
139
|
-
if (!plotEl.value || !miplots.value) return;
|
|
140
|
-
if (!plot.value) {
|
|
141
|
-
plot.value = miplots.value.newPlot(data.value, settings.value);
|
|
142
|
-
plot.value.mount(plotEl.value);
|
|
143
|
-
} else {
|
|
144
|
-
plot.value.updateSettingsAndData(data.value, settings.value);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
onBeforeUnmount(() => {
|
|
149
|
-
plot.value?.unmount();
|
|
150
|
-
});
|
|
151
|
-
</script>
|
|
152
|
-
|
|
153
|
-
<template>
|
|
154
|
-
<PlAlert v-if="error" type="error">
|
|
155
|
-
{{ error.message }}
|
|
156
|
-
</PlAlert>
|
|
157
|
-
<div v-else ref="plotEl" :class="classes.container" />
|
|
158
|
-
</template>
|
|
159
|
-
|
|
160
|
-
<style module>
|
|
161
|
-
.container {
|
|
162
|
-
svg {
|
|
163
|
-
display: block;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
</style>
|