@platforma-sdk/ui-vue 1.42.53 → 1.43.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.
Files changed (84) hide show
  1. package/.turbo/turbo-build.log +213 -207
  2. package/.turbo/turbo-type-check.log +1 -1
  3. package/CHANGELOG.md +20 -0
  4. package/dist/AgGridVue/useAgGridOptions.js +2 -3
  5. package/dist/AgGridVue/useAgGridOptions.js.map +1 -1
  6. package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js +6 -0
  7. package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js.map +1 -0
  8. package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js +5 -0
  9. package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js.map +1 -0
  10. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js +2 -3
  11. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js.map +1 -1
  12. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js +11 -12
  13. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js.map +1 -1
  14. package/dist/components/PlAgRowNumHeader.vue.js +8 -9
  15. package/dist/components/PlAgRowNumHeader.vue.js.map +1 -1
  16. package/dist/components/PlMultiSequenceAlignment/Consensus.vue.d.ts +1 -0
  17. package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js +48 -46
  18. package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js.map +1 -1
  19. package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js +5 -7
  20. package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js.map +1 -1
  21. package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js +14 -13
  22. package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js.map +1 -1
  23. package/dist/components/PlMultiSequenceAlignment/Legend.vue3.js +9 -8
  24. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.d.ts +16 -9
  25. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js +117 -85
  26. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js.map +1 -1
  27. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js +25 -18
  28. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js.map +1 -1
  29. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.d.ts +8 -0
  30. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js +10 -0
  31. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js.map +1 -0
  32. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js +77 -0
  33. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js.map +1 -0
  34. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js +9 -0
  35. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js.map +1 -0
  36. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.d.ts +26 -18
  37. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js +119 -120
  38. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js.map +1 -1
  39. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js +7 -124
  40. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js.map +1 -1
  41. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js +124 -2
  42. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js.map +1 -1
  43. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js +9 -0
  44. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js.map +1 -0
  45. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js +90 -90
  46. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js.map +1 -1
  47. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue3.js +9 -7
  48. package/dist/components/PlMultiSequenceAlignment/cell-size.d.ts +4 -0
  49. package/dist/components/PlMultiSequenceAlignment/cell-size.js +8 -0
  50. package/dist/components/PlMultiSequenceAlignment/cell-size.js.map +1 -0
  51. package/dist/components/PlMultiSequenceAlignment/data.d.ts +15 -10
  52. package/dist/components/PlMultiSequenceAlignment/data.js +309 -202
  53. package/dist/components/PlMultiSequenceAlignment/data.js.map +1 -1
  54. package/dist/components/PlMultiSequenceAlignment/markup.js +9 -7
  55. package/dist/components/PlMultiSequenceAlignment/markup.js.map +1 -1
  56. package/dist/components/PlMultiSequenceAlignment/migrations.js +15 -13
  57. package/dist/components/PlMultiSequenceAlignment/migrations.js.map +1 -1
  58. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.d.ts +6 -0
  59. package/dist/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.d.ts +7 -0
  60. package/dist/components/PlMultiSequenceAlignment/settings.js +3 -4
  61. package/dist/components/PlMultiSequenceAlignment/settings.js.map +1 -1
  62. package/dist/index.js +25 -27
  63. package/dist/index.js.map +1 -1
  64. package/dist/lib.d.ts +1 -2
  65. package/package.json +6 -6
  66. package/src/components/PlMultiSequenceAlignment/Consensus.vue +38 -39
  67. package/src/components/PlMultiSequenceAlignment/Legend.vue +9 -9
  68. package/src/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue +222 -126
  69. package/src/components/PlMultiSequenceAlignment/PhylogeneticTree.vue +110 -0
  70. package/src/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue +28 -22
  71. package/src/components/PlMultiSequenceAlignment/SeqLogo.vue +77 -69
  72. package/src/components/PlMultiSequenceAlignment/Toolbar.vue +47 -39
  73. package/src/components/PlMultiSequenceAlignment/cell-size.ts +4 -0
  74. package/src/components/PlMultiSequenceAlignment/data.ts +361 -149
  75. package/src/components/PlMultiSequenceAlignment/markup.ts +10 -8
  76. package/src/components/PlMultiSequenceAlignment/migrations.ts +6 -1
  77. package/src/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.ts +54 -0
  78. package/src/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.ts +89 -0
  79. package/src/components/PlMultiSequenceAlignment/settings.ts +1 -2
  80. package/src/lib.ts +1 -3
  81. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.d.ts +0 -7
  82. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.js +0 -51
  83. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.js.map +0 -1
  84. package/src/components/PlMultiSequenceAlignment/multi-sequence-alignment.ts +0 -101
@@ -6,7 +6,7 @@ import {
6
6
  } from '@platforma-sdk/model';
7
7
  import { type Ref } from 'vue';
8
8
 
9
- const latestVersion = 1;
9
+ const latestVersion = 2;
10
10
 
11
11
  export function runMigrations(model: Ref<PlMultiSequenceAlignmentModel>) {
12
12
  const currentVersion = getCurrentVersion(model.value);
@@ -20,6 +20,11 @@ export function runMigrations(model: Ref<PlMultiSequenceAlignmentModel>) {
20
20
  .map((id) => parseJson(id));
21
21
  }
22
22
  }
23
+ if (currentVersion < 2) {
24
+ if (model.value.colorScheme?.type === 'markup') {
25
+ delete model.value.colorScheme;
26
+ }
27
+ }
23
28
  } catch (error) {
24
29
  console.error(error);
25
30
  model.value = {};
@@ -0,0 +1,54 @@
1
+ import kalign from '@milaboratories/biowasm-tools/kalign';
2
+ import type { PlMultiSequenceAlignmentSettings } from '@platforma-sdk/model';
3
+
4
+ addEventListener(
5
+ 'message',
6
+ async ({ data }: MessageEvent<RequestMessage>) => {
7
+ try {
8
+ postMessage(await onMessage(data));
9
+ } catch (error) {
10
+ reportError(error);
11
+ }
12
+ },
13
+ );
14
+
15
+ export type RequestMessage = {
16
+ sequences: string[];
17
+ params: PlMultiSequenceAlignmentSettings['alignmentParams'];
18
+ };
19
+
20
+ export type ResponseMessage = string[];
21
+
22
+ async function onMessage(
23
+ { sequences, params }: RequestMessage,
24
+ ): Promise<ResponseMessage> {
25
+ if (sequences.length < 2) {
26
+ throw new Error(
27
+ 'Cannot run multiple sequences alignment on less than 2 sequences.',
28
+ );
29
+ }
30
+ const input = sequences
31
+ .map((sequence, index) => `>${index}\n${sequence}`)
32
+ .join('\n');
33
+ const output = await kalign(input, params);
34
+ return parseKalignOutput(output);
35
+ }
36
+
37
+ function parseKalignOutput(output: string): string[] {
38
+ const result: string[] = [];
39
+ let index = -1;
40
+ for (let line of output.split('\n')) {
41
+ line = line.trim();
42
+ if (!line) {
43
+ continue;
44
+ }
45
+ if (line.startsWith('>')) {
46
+ index += 1;
47
+ continue;
48
+ }
49
+ if (index >= 0) {
50
+ result[index] = (result[index] ?? '').concat(line);
51
+ }
52
+ }
53
+ return result;
54
+ }
@@ -0,0 +1,89 @@
1
+ import rapidnj from '@milaboratories/biowasm-tools/rapidnj';
2
+
3
+ addEventListener(
4
+ 'message',
5
+ async ({ data }: MessageEvent<RequestMessage>) => {
6
+ try {
7
+ postMessage(await onMessage(data));
8
+ } catch (error) {
9
+ reportError(error);
10
+ }
11
+ },
12
+ );
13
+
14
+ export type RequestMessage = string[];
15
+
16
+ export type ResponseMessage = TreeNodeData[];
17
+
18
+ async function onMessage(sequences: RequestMessage): Promise<ResponseMessage> {
19
+ if (sequences.length < 2) {
20
+ throw new Error(
21
+ 'Cannot build phylogenetic tree for less than 2 sequences.',
22
+ );
23
+ }
24
+ const input = sequences
25
+ .map((sequence, index) => `>${index}\n${sequence}`)
26
+ .join('\n');
27
+ const output = await rapidnj(input);
28
+ return Array.from(parseRapidnjOutput(output));
29
+ }
30
+
31
+ function parseRapidnjOutput(input: string) {
32
+ let prevIndex = 0;
33
+ const root = new TreeNode();
34
+ let node = root;
35
+ let virtualId = -1;
36
+ for (const match of input.matchAll(/[(,);]/g)) {
37
+ const [token] = match;
38
+ const [id, length] = input.slice(prevIndex, match.index).split(':');
39
+ if (id) node.id = Number(id.slice(1, -1));
40
+ if (length) node.length = Number(length);
41
+ node.id ??= virtualId--;
42
+ switch (token) {
43
+ case '(':
44
+ node = node.newChild();
45
+ break;
46
+ case ',':
47
+ node = node.parent!.newChild();
48
+ break;
49
+ case ')':
50
+ node = node.parent!;
51
+ break;
52
+ case ';':
53
+ return root;
54
+ }
55
+ prevIndex = match.index + 1;
56
+ }
57
+ throw new Error('Missing semicolon.');
58
+ }
59
+
60
+ class TreeNode {
61
+ id?: number;
62
+ length?: number;
63
+ parent?: TreeNode;
64
+ children?: TreeNode[];
65
+
66
+ newChild(): TreeNode {
67
+ const node = new TreeNode();
68
+ node.parent = this;
69
+ (this.children ??= []).push(node);
70
+ return node;
71
+ }
72
+
73
+ *[Symbol.iterator](): Generator<TreeNodeData> {
74
+ if (this.id === undefined) {
75
+ throw new Error('Node ID cannot be undefined.');
76
+ }
77
+ const result: TreeNodeData = { id: this.id };
78
+ if (this.length !== undefined) result.length = this.length;
79
+ if (this.parent) result.parentId = this.parent.id;
80
+ yield result;
81
+ for (const child of this.children ?? []) yield * child;
82
+ }
83
+ }
84
+
85
+ export interface TreeNodeData {
86
+ id: number;
87
+ length?: number;
88
+ parentId?: number;
89
+ }
@@ -1,8 +1,7 @@
1
1
  import type { PlMultiSequenceAlignmentSettings } from '@platforma-sdk/model';
2
- import { defaultAlignmentParams } from './multi-sequence-alignment';
3
2
 
4
3
  export const defaultSettings: PlMultiSequenceAlignmentSettings = {
5
4
  colorScheme: { type: 'chemical-properties' },
6
5
  widgets: ['seqLogo', 'consensus', 'legend'],
7
- alignmentParams: defaultAlignmentParams,
6
+ alignmentParams: { gpo: 5.5, gpe: 2.0, tgpe: 1.0 },
8
7
  };
package/src/lib.ts CHANGED
@@ -15,8 +15,8 @@ export * from './components/PlAgColumnHeader';
15
15
  export * from './components/PlAgCellFile';
16
16
  export * from './components/PlAgCellProgress';
17
17
  export * from './components/PlAgCellStatusTag';
18
- export * from './components/PlAgChartStackedBarCell';
19
18
  export * from './components/PlAgChartHistogramCell';
19
+ export * from './components/PlAgChartStackedBarCell';
20
20
 
21
21
  export * from './components/PlAgDataTable';
22
22
 
@@ -50,8 +50,6 @@ export * from './computedResult';
50
50
 
51
51
  export * from './composition/fileContent';
52
52
 
53
- export { multiSequenceAlignment } from './components/PlMultiSequenceAlignment/multi-sequence-alignment';
54
-
55
53
  export * from '@milaboratories/uikit';
56
54
 
57
55
  export type * from '@milaboratories/uikit';
@@ -1,7 +0,0 @@
1
- import { PlMultiSequenceAlignmentModel } from '@platforma-sdk/model';
2
- export declare const defaultAlignmentParams: {
3
- gpo: number;
4
- gpe: number;
5
- tgpe: number;
6
- };
7
- export declare function multiSequenceAlignment(sequences: string[], alignmentParams?: PlMultiSequenceAlignmentModel['alignmentParams']): Promise<string[]>;
@@ -1,51 +0,0 @@
1
- import l from "@milaboratories/biowasm-tools";
2
- import { objectHash as s } from "../../objectHash.js";
3
- const c = /* @__PURE__ */ new Map(), f = {
4
- gpo: 5.5,
5
- gpe: 2,
6
- tgpe: 1
7
- }, m = /* @__PURE__ */ (() => {
8
- let n;
9
- return async () => (n || (n = await new l(["kalign"])), n);
10
- })();
11
- async function $(n, a = f) {
12
- if (n.length < 2) return n;
13
- const i = await s([n, a]);
14
- let t = c.get(i);
15
- if (t) return t;
16
- const e = await m(), o = {
17
- input: `/shared/data/input-${i}`,
18
- output: `/shared/data/output-${i}`,
19
- ...a
20
- };
21
- e.mount(
22
- new File(
23
- n.map((r, u) => `>${u}
24
- ${r}
25
- `),
26
- // HACK: remove when mount will handle mounts properly
27
- o.input.split("/").at(-1)
28
- )
29
- ), await e.exec(`kalign ${Object.entries(o).map(([r, u]) => `--${r} ${u}`).join(" ")}`);
30
- const p = await e.cat(o.output);
31
- return t = g(p), c.set(i, t), t;
32
- }
33
- function g(n) {
34
- const a = [];
35
- let i = -1;
36
- for (let t of n.split(`
37
- `))
38
- if (t = t.trim(), !!t) {
39
- if (t.startsWith(">")) {
40
- i += 1;
41
- continue;
42
- }
43
- i >= 0 && (a[i] = (a[i] ?? "").concat(t));
44
- }
45
- return a;
46
- }
47
- export {
48
- f as defaultAlignmentParams,
49
- $ as multiSequenceAlignment
50
- };
51
- //# sourceMappingURL=multi-sequence-alignment.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"multi-sequence-alignment.js","sources":["../../../src/components/PlMultiSequenceAlignment/multi-sequence-alignment.ts"],"sourcesContent":["import Aioli from '@milaboratories/biowasm-tools';\nimport type { PlMultiSequenceAlignmentModel } from '@platforma-sdk/model';\nimport { objectHash } from '../../objectHash';\n\nconst cache = new Map<string, string[]>();\n\nexport const defaultAlignmentParams = {\n gpo: 5.5,\n gpe: 2.0,\n tgpe: 1.0,\n} satisfies PlMultiSequenceAlignmentModel['alignmentParams'];\n\nconst getCli = (() => {\n let cli: Aioli;\n return async () => {\n if (!cli) {\n cli = await new Aioli(['kalign']);\n }\n return cli;\n };\n})();\n\nexport async function multiSequenceAlignment(\n sequences: string[],\n alignmentParams: PlMultiSequenceAlignmentModel['alignmentParams'] =\n defaultAlignmentParams,\n): Promise<string[]> {\n if (sequences.length < 2) return sequences;\n const hash = await objectHash([sequences, alignmentParams]);\n let result = cache.get(hash);\n if (result) return result;\n const CLI = await getCli();\n const params = {\n input: `/shared/data/input-${hash}`,\n output: `/shared/data/output-${hash}`,\n ...alignmentParams,\n };\n CLI.mount(\n new File(\n sequences.map((sequence, index) => `>${index}\\n${sequence}\\n`),\n // HACK: remove when mount will handle mounts properly\n params.input.split('/').at(-1)!,\n ),\n );\n await CLI.exec(`kalign ${\n Object.entries(params)\n .map(([key, value]) => `--${key} ${value}`)\n .join(' ')\n }`);\n const output = await CLI.cat(params.output);\n result = parseKalignOutput(output);\n cache.set(hash, result);\n return result;\n}\n\nfunction parseKalignOutput(output: string): string[] {\n const result: string[] = [];\n let index = -1;\n for (let line of output.split('\\n')) {\n line = line.trim();\n if (!line) {\n continue;\n }\n if (line.startsWith('>')) {\n index += 1;\n continue;\n }\n if (index >= 0) {\n result[index] = (result[index] ?? '').concat(line);\n }\n }\n return result;\n}\n\nif (import.meta.vitest) {\n const { test, expect } = import.meta.vitest;\n\n test('parseKalignOutput', () => {\n const serialized = `some garbage\n[some more garbage]\n>1aab_\nGKGDPKKPRG-KMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKTMSAKEKGKF\nEDMAKADKARYEREMKTY-IPPKGE---------\n>1j46_A\n-----MQDRV-KRPMNAFIVWSRDQRRKMALENPRMRNSEISKQLGYQWKMLTEAEKWPF\nFQEAQKLQAMHREKYPNYKYRPRRKAKMLPK---\n>1k99_A\nMKKLKKHPDFPKKPLTPYFRFFMEKRAKYAKLHPEMSNLDLTKILSKKYKELPEKKKMKY\nIQDFQREKQ-EFERNLARFREDHPDLIQNAKK--\n>2lef_A\n-----MHI---KKPLNAFMLYMKEMRANVVAESTLKESAAINQILGRRWHALSREEQAKY\nYELARKERQLHMQLYPGWSARDNYGKKKKRKREK`;\n\n expect(parseKalignOutput(serialized)).toEqual([\n 'GKGDPKKPRG-KMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKTMSAKEKGKFEDMAKADKARYEREMKTY-IPPKGE---------',\n '-----MQDRV-KRPMNAFIVWSRDQRRKMALENPRMRNSEISKQLGYQWKMLTEAEKWPFFQEAQKLQAMHREKYPNYKYRPRRKAKMLPK---',\n 'MKKLKKHPDFPKKPLTPYFRFFMEKRAKYAKLHPEMSNLDLTKILSKKYKELPEKKKMKYIQDFQREKQ-EFERNLARFREDHPDLIQNAKK--',\n '-----MHI---KKPLNAFMLYMKEMRANVVAESTLKESAAINQILGRRWHALSREEQAKYYELARKERQLHMQLYPGWSARDNYGKKKKRKREK',\n ]);\n });\n}\n"],"names":["cache","defaultAlignmentParams","getCli","cli","Aioli","multiSequenceAlignment","sequences","alignmentParams","hash","objectHash","result","CLI","params","sequence","index","key","value","output","parseKalignOutput","line"],"mappings":";;AAIA,MAAMA,wBAAY,IAAA,GAELC,IAAyB;AAAA,EACpC,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AACR,GAEMC,IAAU,uBAAM;AACpB,MAAIC;AACJ,SAAO,aACAA,MACHA,IAAM,MAAM,IAAIC,EAAM,CAAC,QAAQ,CAAC,IAE3BD;AAEX,GAAA;AAEA,eAAsBE,EACpBC,GACAC,IACAN,GACmB;AACnB,MAAIK,EAAU,SAAS,EAAG,QAAOA;AACjC,QAAME,IAAO,MAAMC,EAAW,CAACH,GAAWC,CAAe,CAAC;AAC1D,MAAIG,IAASV,EAAM,IAAIQ,CAAI;AAC3B,MAAIE,EAAQ,QAAOA;AACnB,QAAMC,IAAM,MAAMT,EAAA,GACZU,IAAS;AAAA,IACb,OAAO,sBAAsBJ,CAAI;AAAA,IACjC,QAAQ,uBAAuBA,CAAI;AAAA,IACnC,GAAGD;AAAA,EAAA;AAEL,EAAAI,EAAI;AAAA,IACF,IAAI;AAAA,MACFL,EAAU,IAAI,CAACO,GAAUC,MAAU,IAAIA,CAAK;AAAA,EAAKD,CAAQ;AAAA,CAAI;AAAA;AAAA,MAE7DD,EAAO,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE;AAAA,IAAA;AAAA,EAC/B,GAEF,MAAMD,EAAI,KAAK,UACb,OAAO,QAAQC,CAAM,EAClB,IAAI,CAAC,CAACG,GAAKC,CAAK,MAAM,KAAKD,CAAG,IAAIC,CAAK,EAAE,EACzC,KAAK,GAAG,CACb,EAAE;AACF,QAAMC,IAAS,MAAMN,EAAI,IAAIC,EAAO,MAAM;AAC1C,SAAAF,IAASQ,EAAkBD,CAAM,GACjCjB,EAAM,IAAIQ,GAAME,CAAM,GACfA;AACT;AAEA,SAASQ,EAAkBD,GAA0B;AACnD,QAAMP,IAAmB,CAAA;AACzB,MAAII,IAAQ;AACZ,WAASK,KAAQF,EAAO,MAAM;AAAA,CAAI;AAEhC,QADAE,IAAOA,EAAK,KAAA,GACR,EAACA,GAGL;AAAA,UAAIA,EAAK,WAAW,GAAG,GAAG;AACxB,QAAAL,KAAS;AACT;AAAA,MACF;AACA,MAAIA,KAAS,MACXJ,EAAOI,CAAK,KAAKJ,EAAOI,CAAK,KAAK,IAAI,OAAOK,CAAI;AAAA;AAGrD,SAAOT;AACT;"}
@@ -1,101 +0,0 @@
1
- import Aioli from '@milaboratories/biowasm-tools';
2
- import type { PlMultiSequenceAlignmentModel } from '@platforma-sdk/model';
3
- import { objectHash } from '../../objectHash';
4
-
5
- const cache = new Map<string, string[]>();
6
-
7
- export const defaultAlignmentParams = {
8
- gpo: 5.5,
9
- gpe: 2.0,
10
- tgpe: 1.0,
11
- } satisfies PlMultiSequenceAlignmentModel['alignmentParams'];
12
-
13
- const getCli = (() => {
14
- let cli: Aioli;
15
- return async () => {
16
- if (!cli) {
17
- cli = await new Aioli(['kalign']);
18
- }
19
- return cli;
20
- };
21
- })();
22
-
23
- export async function multiSequenceAlignment(
24
- sequences: string[],
25
- alignmentParams: PlMultiSequenceAlignmentModel['alignmentParams'] =
26
- defaultAlignmentParams,
27
- ): Promise<string[]> {
28
- if (sequences.length < 2) return sequences;
29
- const hash = await objectHash([sequences, alignmentParams]);
30
- let result = cache.get(hash);
31
- if (result) return result;
32
- const CLI = await getCli();
33
- const params = {
34
- input: `/shared/data/input-${hash}`,
35
- output: `/shared/data/output-${hash}`,
36
- ...alignmentParams,
37
- };
38
- CLI.mount(
39
- new File(
40
- sequences.map((sequence, index) => `>${index}\n${sequence}\n`),
41
- // HACK: remove when mount will handle mounts properly
42
- params.input.split('/').at(-1)!,
43
- ),
44
- );
45
- await CLI.exec(`kalign ${
46
- Object.entries(params)
47
- .map(([key, value]) => `--${key} ${value}`)
48
- .join(' ')
49
- }`);
50
- const output = await CLI.cat(params.output);
51
- result = parseKalignOutput(output);
52
- cache.set(hash, result);
53
- return result;
54
- }
55
-
56
- function parseKalignOutput(output: string): string[] {
57
- const result: string[] = [];
58
- let index = -1;
59
- for (let line of output.split('\n')) {
60
- line = line.trim();
61
- if (!line) {
62
- continue;
63
- }
64
- if (line.startsWith('>')) {
65
- index += 1;
66
- continue;
67
- }
68
- if (index >= 0) {
69
- result[index] = (result[index] ?? '').concat(line);
70
- }
71
- }
72
- return result;
73
- }
74
-
75
- if (import.meta.vitest) {
76
- const { test, expect } = import.meta.vitest;
77
-
78
- test('parseKalignOutput', () => {
79
- const serialized = `some garbage
80
- [some more garbage]
81
- >1aab_
82
- GKGDPKKPRG-KMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKTMSAKEKGKF
83
- EDMAKADKARYEREMKTY-IPPKGE---------
84
- >1j46_A
85
- -----MQDRV-KRPMNAFIVWSRDQRRKMALENPRMRNSEISKQLGYQWKMLTEAEKWPF
86
- FQEAQKLQAMHREKYPNYKYRPRRKAKMLPK---
87
- >1k99_A
88
- MKKLKKHPDFPKKPLTPYFRFFMEKRAKYAKLHPEMSNLDLTKILSKKYKELPEKKKMKY
89
- IQDFQREKQ-EFERNLARFREDHPDLIQNAKK--
90
- >2lef_A
91
- -----MHI---KKPLNAFMLYMKEMRANVVAESTLKESAAINQILGRRWHALSREEQAKY
92
- YELARKERQLHMQLYPGWSARDNYGKKKKRKREK`;
93
-
94
- expect(parseKalignOutput(serialized)).toEqual([
95
- 'GKGDPKKPRG-KMSSYAFFVQTSREEHKKKHPDASVNFSEFSKKCSERWKTMSAKEKGKFEDMAKADKARYEREMKTY-IPPKGE---------',
96
- '-----MQDRV-KRPMNAFIVWSRDQRRKMALENPRMRNSEISKQLGYQWKMLTEAEKWPFFQEAQKLQAMHREKYPNYKYRPRRKAKMLPK---',
97
- 'MKKLKKHPDFPKKPLTPYFRFFMEKRAKYAKLHPEMSNLDLTKILSKKYKELPEKKKMKYIQDFQREKQ-EFERNLARFREDHPDLIQNAKK--',
98
- '-----MHI---KKPLNAFMLYMKEMRANVVAESTLKESAAINQILGRRWHALSREEQAKYYELARKERQLHMQLYPGWSARDNYGKKKKRKREK',
99
- ]);
100
- });
101
- }