@platforma-open/milaboratories.humanization-score.model 0.3.0 → 0.3.2

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/dist/index.cjs CHANGED
@@ -6,12 +6,8 @@ const defaultGraphStateHistogram = () => ({
6
6
  title: "Humanness Score Distribution",
7
7
  template: "bins",
8
8
  currentTab: null,
9
- axesSettings: { other: { binsCount: 20 } }
10
- });
11
- const defaultGraphStateBoxplot = () => ({
12
- title: "Humanness by Sample",
13
- template: "box",
14
- currentTab: null
9
+ axesSettings: { other: { binsCount: 20 } },
10
+ layersSettings: { bins: { fillColor: "#2D93FA" } }
15
11
  });
16
12
  const inputSelectors = [{
17
13
  axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/clonotypeKey" }],
@@ -23,13 +19,11 @@ const inputSelectors = [{
23
19
  const dataModel = new _platforma_sdk_model.DataModelBuilder().from("v1").upgradeLegacy(({ args, uiState }) => ({
24
20
  ...args,
25
21
  tableState: uiState.tableState,
26
- graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram(),
27
- graphStateBoxplot: uiState.graphStateBoxplot ?? defaultGraphStateBoxplot()
22
+ graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram()
28
23
  })).init(() => ({
29
24
  customBlockLabel: "",
30
25
  tableState: (0, _platforma_sdk_model.createPlDataTableStateV2)(),
31
- graphStateHistogram: defaultGraphStateHistogram(),
32
- graphStateBoxplot: defaultGraphStateBoxplot()
26
+ graphStateHistogram: defaultGraphStateHistogram()
33
27
  }));
34
28
  const platforma = _platforma_sdk_model.BlockModelV3.create(dataModel).args((data) => {
35
29
  if (!data.inputAnchor) throw new Error("Input anchor is required");
@@ -41,12 +35,14 @@ const platforma = _platforma_sdk_model.BlockModelV3.create(dataModel).args((data
41
35
  }).output("inputOptions", (ctx) => ctx.resultPool.getOptions(inputSelectors)).outputWithStatus("pt", (ctx) => {
42
36
  const pCols = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
43
37
  if (pCols === void 0) return;
38
+ const anchorCol = pCols[0];
39
+ if (anchorCol === void 0) return;
44
40
  return (0, _platforma_sdk_model.createPlDataTableV3)(ctx, {
45
41
  tableState: ctx.data.tableState,
46
- columns: new _platforma_sdk_model.ArrayColumnProvider(pCols).getAllColumns().map((column) => ({
47
- column,
48
- isPrimary: true
49
- }))
42
+ columns: {
43
+ anchors: { main: anchorCol.spec },
44
+ selector: { mode: "enrichment" }
45
+ }
50
46
  });
51
47
  }).outputWithStatus("histogramPf", (ctx) => {
52
48
  const pCols = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
@@ -59,72 +55,20 @@ const platforma = _platforma_sdk_model.BlockModelV3.create(dataModel).args((data
59
55
  columnId: c.id,
60
56
  spec: c.spec
61
57
  }));
62
- }).outputWithStatus("perSamplePf", (ctx) => {
63
- const humanness = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
64
- if (humanness === void 0) return void 0;
65
- const ref = ctx.data.inputAnchor;
66
- if (ref === void 0) return void 0;
67
- const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{
68
- axes: [{
69
- anchor: "main",
70
- idx: 0
71
- }, {
72
- anchor: "main",
73
- idx: 1
74
- }],
75
- annotations: {
76
- "pl7.app/isAbundance": "true",
77
- "pl7.app/abundance/normalized": "false",
78
- "pl7.app/abundance/isPrimary": "true"
79
- }
80
- }]);
81
- return (0, _platforma_sdk_model.createPFrameForGraphs)(ctx, [...humanness, ...abundance ?? []]);
82
- }).output("perSamplePfPcols", (ctx) => {
83
- const humanness = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
84
- if (humanness === void 0 || humanness.length === 0) return void 0;
85
- const ref = ctx.data.inputAnchor;
86
- if (ref === void 0) return void 0;
87
- const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{
88
- axes: [{
89
- anchor: "main",
90
- idx: 0
91
- }, {
92
- anchor: "main",
93
- idx: 1
94
- }],
95
- annotations: {
96
- "pl7.app/isAbundance": "true",
97
- "pl7.app/abundance/normalized": "false",
98
- "pl7.app/abundance/isPrimary": "true"
99
- }
100
- }]);
101
- return [...humanness, ...abundance ?? []].map((c) => ({
102
- columnId: c.id,
103
- spec: c.spec
104
- }));
105
58
  }).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).title(() => "Humanization Score").subtitle((ctx) => {
106
59
  if (ctx.data.customBlockLabel) return ctx.data.customBlockLabel;
107
60
  return "Humanization Score";
108
- }).sections((_) => [
109
- {
110
- type: "link",
111
- href: "/",
112
- label: "Table"
113
- },
114
- {
115
- type: "link",
116
- href: "/histogram",
117
- label: "Score Distribution"
118
- },
119
- {
120
- type: "link",
121
- href: "/by-sample",
122
- label: "By Sample"
123
- }
124
- ]).done();
61
+ }).sections((_) => [{
62
+ type: "link",
63
+ href: "/",
64
+ label: "Table"
65
+ }, {
66
+ type: "link",
67
+ href: "/histogram",
68
+ label: "Score Distribution"
69
+ }]).done();
125
70
  //#endregion
126
71
  exports.HUMANNESS_SCORE_COLUMN = HUMANNESS_SCORE_COLUMN;
127
- exports.defaultGraphStateBoxplot = defaultGraphStateBoxplot;
128
72
  exports.defaultGraphStateHistogram = defaultGraphStateHistogram;
129
73
  exports.platforma = platforma;
130
74
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["DataModelBuilder","BlockModelV3","ArrayColumnProvider"],"sources":["../src/index.ts"],"sourcesContent":["import type { GraphMakerState } from '@milaboratories/graph-maker';\nimport type {\n PColumnIdAndSpec,\n PFrameHandle,\n PlDataTableStateV2,\n PlRef,\n} from '@platforma-sdk/model';\nimport {\n ArrayColumnProvider,\n BlockModelV3,\n DataModelBuilder,\n createPFrameForGraphs,\n createPlDataTableStateV2,\n createPlDataTableV3,\n} from '@platforma-sdk/model';\nexport type * from '@milaboratories/helpers';\n\ntype OldArgs = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n};\n\ntype OldUiState = {\n tableState: PlDataTableStateV2;\n graphStateHistogram?: GraphMakerState;\n graphStateBoxplot?: GraphMakerState;\n};\n\nexport type BlockData = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n tableState: PlDataTableStateV2;\n // Distribution of the per-clonotype humanness score across the whole dataset.\n graphStateHistogram: GraphMakerState;\n // Per-sample distribution of humanness (box/violin), grouped by sampleId.\n graphStateBoxplot: GraphMakerState;\n};\n\n// Humanness score column name emitted by `clonotype-process.tpl.tengo`.\nexport const HUMANNESS_SCORE_COLUMN = 'pl7.app/humannessScore';\n\nexport const defaultGraphStateHistogram = (): GraphMakerState => ({\n title: 'Humanness Score Distribution',\n template: 'bins',\n currentTab: null,\n axesSettings: {\n other: { binsCount: 20 },\n },\n});\n\nexport const defaultGraphStateBoxplot = (): GraphMakerState => ({\n title: 'Humanness by Sample',\n template: 'box',\n currentTab: null,\n});\n\n// Selectors for the input dataset anchor — shared between `inputOptions`\n// (the dropdown) and `subtitle` (so the default label matches the dataset name).\nconst inputSelectors = [{\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/clonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}, {\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/scClonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}];\n\nconst dataModel = new DataModelBuilder()\n .from<BlockData>('v1')\n .upgradeLegacy<OldArgs, OldUiState>(({ args, uiState }) => ({\n ...args,\n tableState: uiState.tableState,\n graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram(),\n graphStateBoxplot: uiState.graphStateBoxplot ?? defaultGraphStateBoxplot(),\n }))\n .init(() => ({\n customBlockLabel: '',\n tableState: createPlDataTableStateV2(),\n graphStateHistogram: defaultGraphStateHistogram(),\n graphStateBoxplot: defaultGraphStateBoxplot(),\n }));\n\nexport const platforma = BlockModelV3.create(dataModel)\n\n .args((data) => {\n if (!data.inputAnchor) throw new Error('Input anchor is required');\n\n return {\n // Empty when unset; the workflow falls back to the input dataset name so\n // the provenance trace label matches the block subtitle.\n customBlockLabel: data.customBlockLabel || '',\n inputAnchor: data.inputAnchor,\n mem: data.mem,\n };\n })\n\n .output('inputOptions', (ctx) =>\n ctx.resultPool.getOptions(inputSelectors),\n )\n\n .outputWithStatus('pt', (ctx) => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) {\n return undefined;\n }\n return createPlDataTableV3(ctx, {\n tableState: ctx.data.tableState,\n columns: new ArrayColumnProvider(pCols)\n .getAllColumns()\n .map((column) => ({ column, isPrimary: true })),\n });\n })\n\n // --- Score distribution (histogram) ---------------------------------------\n // One row per clonotype, so the histogram counts UNIQUE clonotypes by humanness\n // score — it is deliberately NOT weighted by clonotype abundance. The question it\n // answers is \"how many distinct candidates sit below/above a humanness level\"\n // (i.e. how much humanization work is there), not \"how human is the repertoire by\n // read mass\". No human-like threshold line is drawn: this score is a 9-mer\n // fraction rescaled to 0..100, not a cutoff validated against therapeutic mAbs.\n .outputWithStatus('histogramPf', (ctx): PFrameHandle | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) return undefined;\n return createPFrameForGraphs(ctx, pCols);\n })\n\n .output('histogramPfPcols', (ctx): PColumnIdAndSpec[] | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined || pCols.length === 0) return undefined;\n return pCols.map((c) => ({ columnId: c.id, spec: c.spec }));\n })\n\n // --- Per-sample distribution (box / violin) --------------------------------\n // The humanness column is keyed by clonotypeKey only (sample-agnostic). To get\n // a per-sample view we join it with the input dataset's primary abundance\n // column, which carries the [sampleId, clonotypeKey] axes. graph-maker joins on\n // the shared clonotypeKey axis, so each (sample, clonotype) pair contributes the\n // clonotype's score — grouping by sampleId then yields a distribution per sample.\n // This is a box/violin (median + spread + tails) on purpose, not a per-sample\n // mean: the spread is exactly what a single mean would hide.\n // Degrades gracefully: if the dataset has no primary-abundance column the join\n // adds nothing, the sampleId axis is absent, and the page simply can't preselect\n // a grouping (the chart still opens). VDJ datasets almost always carry abundance.\n .outputWithStatus('perSamplePf', (ctx): PFrameHandle | undefined => {\n const humanness = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (humanness === undefined) return undefined;\n\n const ref = ctx.data.inputAnchor;\n if (ref === undefined) return undefined;\n\n const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{\n axes: [{ anchor: 'main', idx: 0 }, { anchor: 'main', idx: 1 }],\n annotations: {\n 'pl7.app/isAbundance': 'true',\n 'pl7.app/abundance/normalized': 'false',\n 'pl7.app/abundance/isPrimary': 'true',\n },\n }]);\n\n return createPFrameForGraphs(ctx, [...humanness, ...(abundance ?? [])]);\n })\n\n .output('perSamplePfPcols', (ctx): PColumnIdAndSpec[] | undefined => {\n const humanness = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (humanness === undefined || humanness.length === 0) return undefined;\n\n const ref = ctx.data.inputAnchor;\n if (ref === undefined) return undefined;\n\n const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{\n axes: [{ anchor: 'main', idx: 0 }, { anchor: 'main', idx: 1 }],\n annotations: {\n 'pl7.app/isAbundance': 'true',\n 'pl7.app/abundance/normalized': 'false',\n 'pl7.app/abundance/isPrimary': 'true',\n },\n }]);\n\n return [...humanness, ...(abundance ?? [])].map((c) => ({ columnId: c.id, spec: c.spec }));\n })\n\n .output('isRunning', (ctx) => ctx.outputs?.getIsReadyOrError() === false)\n\n .title(() => 'Humanization Score')\n\n .subtitle((ctx) => {\n if (ctx.data.customBlockLabel) return ctx.data.customBlockLabel;\n return 'Humanization Score';\n })\n\n .sections((_) => [\n { type: 'link', href: '/', label: 'Table' },\n { type: 'link', href: '/histogram', label: 'Score Distribution' },\n { type: 'link', href: '/by-sample', label: 'By Sample' },\n ])\n\n .done();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["DataModelBuilder","BlockModelV3"],"sources":["../src/index.ts"],"sourcesContent":["import type { GraphMakerState } from '@milaboratories/graph-maker';\nimport type {\n PColumnIdAndSpec,\n PFrameHandle,\n PlDataTableStateV2,\n PlRef,\n} from '@platforma-sdk/model';\nimport {\n BlockModelV3,\n DataModelBuilder, createPFrameForGraphs,\n createPlDataTableStateV2,\n createPlDataTableV3,\n} from '@platforma-sdk/model';\nexport type * from '@milaboratories/helpers';\n\ntype OldArgs = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n};\n\ntype OldUiState = {\n tableState: PlDataTableStateV2;\n graphStateHistogram?: GraphMakerState;\n};\n\nexport type BlockData = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n tableState: PlDataTableStateV2;\n // Distribution of the per-clonotype humanness score across the whole dataset.\n graphStateHistogram: GraphMakerState;\n};\n\n// Humanness score column name emitted by `clonotype-process.tpl.tengo`.\nexport const HUMANNESS_SCORE_COLUMN = 'pl7.app/humannessScore';\n\nexport const defaultGraphStateHistogram = (): GraphMakerState => ({\n title: 'Humanness Score Distribution',\n template: 'bins',\n currentTab: null,\n axesSettings: {\n other: { binsCount: 20 },\n },\n // Give the bars a solid fill instead of the default white — colour values\n // taken from graph-maker's fixed palette (\"Blue\").\n layersSettings: {\n bins: { fillColor: '#2D93FA' },\n },\n});\n\n// Selectors for the input dataset anchor — shared between `inputOptions`\n// (the dropdown) and `subtitle` (so the default label matches the dataset name).\nconst inputSelectors = [{\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/clonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}, {\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/scClonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}];\n\nconst dataModel = new DataModelBuilder()\n .from<BlockData>('v1')\n .upgradeLegacy<OldArgs, OldUiState>(({ args, uiState }) => ({\n ...args,\n tableState: uiState.tableState,\n graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram(),\n }))\n .init(() => ({\n customBlockLabel: '',\n tableState: createPlDataTableStateV2(),\n graphStateHistogram: defaultGraphStateHistogram(),\n }));\n\nexport const platforma = BlockModelV3.create(dataModel)\n\n .args((data) => {\n if (!data.inputAnchor) throw new Error('Input anchor is required');\n\n return {\n // Empty when unset; the workflow falls back to the input dataset name so\n // the provenance trace label matches the block subtitle.\n customBlockLabel: data.customBlockLabel || '',\n inputAnchor: data.inputAnchor,\n mem: data.mem,\n };\n })\n\n .output('inputOptions', (ctx) =>\n ctx.resultPool.getOptions(inputSelectors),\n )\n\n .outputWithStatus('pt', (ctx) => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) {\n return undefined;\n }\n\n const anchorCol = pCols[0];\n if (anchorCol === undefined) {\n return undefined;\n }\n\n return createPlDataTableV3(ctx, {\n tableState: ctx.data.tableState,\n columns: {\n anchors: { main: anchorCol.spec },\n selector: { mode: 'enrichment' },\n },\n });\n })\n\n .outputWithStatus('histogramPf', (ctx): PFrameHandle | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) return undefined;\n return createPFrameForGraphs(ctx, pCols);\n })\n\n .output('histogramPfPcols', (ctx): PColumnIdAndSpec[] | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined || pCols.length === 0) return undefined;\n return pCols.map((c) => ({ columnId: c.id, spec: c.spec }));\n })\n\n .output('isRunning', (ctx) => ctx.outputs?.getIsReadyOrError() === false)\n\n .title(() => 'Humanization Score')\n\n .subtitle((ctx) => {\n if (ctx.data.customBlockLabel) return ctx.data.customBlockLabel;\n return 'Humanization Score';\n })\n\n .sections((_) => [\n { type: 'link', href: '/', label: 'Table' },\n { type: 'link', href: '/histogram', label: 'Score Distribution' },\n ])\n\n .done();\n"],"mappings":";;;AAoCA,MAAa,yBAAyB;AAEtC,MAAa,oCAAqD;CAChE,OAAO;CACP,UAAU;CACV,YAAY;CACZ,cAAc,EACZ,OAAO,EAAE,WAAW,IAAI,EACzB;CAGD,gBAAgB,EACd,MAAM,EAAE,WAAW,WAAW,EAC/B;CACF;AAID,MAAM,iBAAiB,CAAC;CACtB,MAAM,CACJ,EAAE,MAAM,oBAAoB,EAC5B,EAAE,MAAM,4BAA4B,CACrC;CACD,aAAa,EAAE,oBAAoB,QAAQ;CAC5C,EAAE;CACD,MAAM,CACJ,EAAE,MAAM,oBAAoB,EAC5B,EAAE,MAAM,8BAA8B,CACvC;CACD,aAAa,EAAE,oBAAoB,QAAQ;CAC5C,CAAC;AAEF,MAAM,YAAY,IAAIA,qBAAAA,kBAAkB,CACrC,KAAgB,KAAK,CACrB,eAAoC,EAAE,MAAM,eAAe;CAC1D,GAAG;CACH,YAAY,QAAQ;CACpB,qBAAqB,QAAQ,uBAAuB,4BAA4B;CACjF,EAAE,CACF,YAAY;CACX,kBAAkB;CAClB,aAAA,GAAA,qBAAA,2BAAsC;CACtC,qBAAqB,4BAA4B;CAClD,EAAE;AAEL,MAAa,YAAYC,qBAAAA,aAAa,OAAO,UAAU,CAEpD,MAAM,SAAS;CACd,IAAI,CAAC,KAAK,aAAa,MAAM,IAAI,MAAM,2BAA2B;CAElE,OAAO;EAGL,kBAAkB,KAAK,oBAAoB;EAC3C,aAAa,KAAK;EAClB,KAAK,KAAK;EACX;EACD,CAED,OAAO,iBAAiB,QACvB,IAAI,WAAW,WAAW,eAAe,CAC1C,CAEA,iBAAiB,OAAO,QAAQ;CAC/B,MAAM,QAAQ,IAAI,SAAS,QAAQ,kBAAkB,EAAE,aAAa;CACpE,IAAI,UAAU,KAAA,GACZ;CAGF,MAAM,YAAY,MAAM;CACxB,IAAI,cAAc,KAAA,GAChB;CAGF,QAAA,GAAA,qBAAA,qBAA2B,KAAK;EAC9B,YAAY,IAAI,KAAK;EACrB,SAAS;GACP,SAAS,EAAE,MAAM,UAAU,MAAM;GACjC,UAAU,EAAE,MAAM,cAAc;GACjC;EACF,CAAC;EACF,CAED,iBAAiB,gBAAgB,QAAkC;CAClE,MAAM,QAAQ,IAAI,SAAS,QAAQ,kBAAkB,EAAE,aAAa;CACpE,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,QAAA,GAAA,qBAAA,uBAA6B,KAAK,MAAM;EACxC,CAED,OAAO,qBAAqB,QAAwC;CACnE,MAAM,QAAQ,IAAI,SAAS,QAAQ,kBAAkB,EAAE,aAAa;CACpE,IAAI,UAAU,KAAA,KAAa,MAAM,WAAW,GAAG,OAAO,KAAA;CACtD,OAAO,MAAM,KAAK,OAAO;EAAE,UAAU,EAAE;EAAI,MAAM,EAAE;EAAM,EAAE;EAC3D,CAED,OAAO,cAAc,QAAQ,IAAI,SAAS,mBAAmB,KAAK,MAAM,CAExE,YAAY,qBAAqB,CAEjC,UAAU,QAAQ;CACjB,IAAI,IAAI,KAAK,kBAAkB,OAAO,IAAI,KAAK;CAC/C,OAAO;EACP,CAED,UAAU,MAAM,CACf;CAAE,MAAM;CAAQ,MAAM;CAAK,OAAO;CAAS,EAC3C;CAAE,MAAM;CAAQ,MAAM;CAAc,OAAO;CAAsB,CAClE,CAAC,CAED,MAAM"}
package/dist/index.d.ts CHANGED
@@ -11,11 +11,9 @@ type BlockData = {
11
11
  mem?: number;
12
12
  tableState: PlDataTableStateV2;
13
13
  graphStateHistogram: GraphMakerState;
14
- graphStateBoxplot: GraphMakerState;
15
14
  };
16
15
  declare const HUMANNESS_SCORE_COLUMN = "pl7.app/humannessScore";
17
16
  declare const defaultGraphStateHistogram: () => GraphMakerState;
18
- declare const defaultGraphStateBoxplot: () => GraphMakerState;
19
17
  declare const platforma: _$_platforma_sdk_model0.PlatformaExtended<_$_platforma_sdk_model0.PlatformaV3<BlockData, {
20
18
  customBlockLabel: string;
21
19
  inputAnchor: Readonly<{
@@ -1722,46 +1720,9 @@ declare const platforma: _$_platforma_sdk_model0.PlatformaExtended<_$_platforma_
1722
1720
  }[];
1723
1721
  };
1724
1722
  }[] | undefined>;
1725
- } & {
1726
- perSamplePf: _$_platforma_sdk_model0.ConfigRenderLambda<PFrameHandle | undefined> & {
1727
- withStatus: true;
1728
- };
1729
- } & {
1730
- perSamplePfPcols: _$_platforma_sdk_model0.ConfigRenderLambda<{
1731
- readonly columnId: _$_platforma_sdk_model0.PObjectId;
1732
- readonly spec: {
1733
- readonly kind: "PColumn";
1734
- readonly name: string;
1735
- readonly domain?: {
1736
- [x: string]: string;
1737
- } | undefined;
1738
- readonly contextDomain?: {
1739
- [x: string]: string;
1740
- } | undefined;
1741
- readonly annotations?: {
1742
- [x: string]: string;
1743
- } | undefined;
1744
- readonly valueType: "Int" | "Long" | "Float" | "Double" | "String" | "Bytes";
1745
- readonly parentAxes?: number[] | undefined;
1746
- readonly axesSpec: {
1747
- readonly type: _$_platforma_sdk_model0.AxisValueType;
1748
- readonly name: string;
1749
- readonly domain?: {
1750
- [x: string]: string;
1751
- } | undefined;
1752
- readonly contextDomain?: {
1753
- [x: string]: string;
1754
- } | undefined;
1755
- readonly annotations?: {
1756
- [x: string]: string;
1757
- } | undefined;
1758
- readonly parentAxes?: number[] | undefined;
1759
- }[];
1760
- };
1761
- }[] | undefined>;
1762
1723
  } & {
1763
1724
  isRunning: _$_platforma_sdk_model0.ConfigRenderLambda<boolean>;
1764
- }>, "/" | "/histogram" | "/by-sample", {}, _$_platforma_sdk_model0.BlockDefaultUiServices>>;
1725
+ }>, "/" | "/histogram", {}, _$_platforma_sdk_model0.BlockDefaultUiServices>>;
1765
1726
  //#endregion
1766
- export { BlockData, HUMANNESS_SCORE_COLUMN, defaultGraphStateBoxplot, defaultGraphStateHistogram, platforma };
1727
+ export { BlockData, HUMANNESS_SCORE_COLUMN, defaultGraphStateHistogram, platforma };
1767
1728
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;KA6BY,SAAA;EACV,gBAAA;EACA,WAAA,GAAc,KAAA;EACd,GAAA;EACA,UAAA,EAAY,kBAAA;EAEZ,mBAAA,EAAqB,eAAA;EAErB,iBAAA,EAAmB,eAAA;AAAA;AAAA,cAIR,sBAAA;AAAA,cAEA,0BAAA,QAAiC,eAAA;AAAA,cASjC,wBAAA,QAA+B,eAAA;AAAA,cAqC/B,SAAA,EAAS,uBAAA,CAAA,iBAAA,yBAAA,WAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;gBArCsB;;kBAI1C,gBAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;KA0BY,SAAA;EACV,gBAAA;EACA,WAAA,GAAc,KAAA;EACd,GAAA;EACA,UAAA,EAAY,kBAAA;EAEZ,mBAAA,EAAqB,eAAA;AAAA;AAAA,cAIV,sBAAA;AAAA,cAEA,0BAAA,QAAiC,eAAA;AAAA,cA2CjC,SAAA,EAAS,uBAAA,CAAA,iBAAA,yBAAA,WAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAAA"}
package/dist/index.js CHANGED
@@ -1,16 +1,12 @@
1
- import { ArrayColumnProvider, BlockModelV3, DataModelBuilder, createPFrameForGraphs, createPlDataTableStateV2, createPlDataTableV3 } from "@platforma-sdk/model";
1
+ import { BlockModelV3, DataModelBuilder, createPFrameForGraphs, createPlDataTableStateV2, createPlDataTableV3 } from "@platforma-sdk/model";
2
2
  //#region src/index.ts
3
3
  const HUMANNESS_SCORE_COLUMN = "pl7.app/humannessScore";
4
4
  const defaultGraphStateHistogram = () => ({
5
5
  title: "Humanness Score Distribution",
6
6
  template: "bins",
7
7
  currentTab: null,
8
- axesSettings: { other: { binsCount: 20 } }
9
- });
10
- const defaultGraphStateBoxplot = () => ({
11
- title: "Humanness by Sample",
12
- template: "box",
13
- currentTab: null
8
+ axesSettings: { other: { binsCount: 20 } },
9
+ layersSettings: { bins: { fillColor: "#2D93FA" } }
14
10
  });
15
11
  const inputSelectors = [{
16
12
  axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/clonotypeKey" }],
@@ -22,13 +18,11 @@ const inputSelectors = [{
22
18
  const dataModel = new DataModelBuilder().from("v1").upgradeLegacy(({ args, uiState }) => ({
23
19
  ...args,
24
20
  tableState: uiState.tableState,
25
- graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram(),
26
- graphStateBoxplot: uiState.graphStateBoxplot ?? defaultGraphStateBoxplot()
21
+ graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram()
27
22
  })).init(() => ({
28
23
  customBlockLabel: "",
29
24
  tableState: createPlDataTableStateV2(),
30
- graphStateHistogram: defaultGraphStateHistogram(),
31
- graphStateBoxplot: defaultGraphStateBoxplot()
25
+ graphStateHistogram: defaultGraphStateHistogram()
32
26
  }));
33
27
  const platforma = BlockModelV3.create(dataModel).args((data) => {
34
28
  if (!data.inputAnchor) throw new Error("Input anchor is required");
@@ -40,12 +34,14 @@ const platforma = BlockModelV3.create(dataModel).args((data) => {
40
34
  }).output("inputOptions", (ctx) => ctx.resultPool.getOptions(inputSelectors)).outputWithStatus("pt", (ctx) => {
41
35
  const pCols = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
42
36
  if (pCols === void 0) return;
37
+ const anchorCol = pCols[0];
38
+ if (anchorCol === void 0) return;
43
39
  return createPlDataTableV3(ctx, {
44
40
  tableState: ctx.data.tableState,
45
- columns: new ArrayColumnProvider(pCols).getAllColumns().map((column) => ({
46
- column,
47
- isPrimary: true
48
- }))
41
+ columns: {
42
+ anchors: { main: anchorCol.spec },
43
+ selector: { mode: "enrichment" }
44
+ }
49
45
  });
50
46
  }).outputWithStatus("histogramPf", (ctx) => {
51
47
  const pCols = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
@@ -58,70 +54,19 @@ const platforma = BlockModelV3.create(dataModel).args((data) => {
58
54
  columnId: c.id,
59
55
  spec: c.spec
60
56
  }));
61
- }).outputWithStatus("perSamplePf", (ctx) => {
62
- const humanness = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
63
- if (humanness === void 0) return void 0;
64
- const ref = ctx.data.inputAnchor;
65
- if (ref === void 0) return void 0;
66
- const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{
67
- axes: [{
68
- anchor: "main",
69
- idx: 0
70
- }, {
71
- anchor: "main",
72
- idx: 1
73
- }],
74
- annotations: {
75
- "pl7.app/isAbundance": "true",
76
- "pl7.app/abundance/normalized": "false",
77
- "pl7.app/abundance/isPrimary": "true"
78
- }
79
- }]);
80
- return createPFrameForGraphs(ctx, [...humanness, ...abundance ?? []]);
81
- }).output("perSamplePfPcols", (ctx) => {
82
- const humanness = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
83
- if (humanness === void 0 || humanness.length === 0) return void 0;
84
- const ref = ctx.data.inputAnchor;
85
- if (ref === void 0) return void 0;
86
- const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{
87
- axes: [{
88
- anchor: "main",
89
- idx: 0
90
- }, {
91
- anchor: "main",
92
- idx: 1
93
- }],
94
- annotations: {
95
- "pl7.app/isAbundance": "true",
96
- "pl7.app/abundance/normalized": "false",
97
- "pl7.app/abundance/isPrimary": "true"
98
- }
99
- }]);
100
- return [...humanness, ...abundance ?? []].map((c) => ({
101
- columnId: c.id,
102
- spec: c.spec
103
- }));
104
57
  }).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).title(() => "Humanization Score").subtitle((ctx) => {
105
58
  if (ctx.data.customBlockLabel) return ctx.data.customBlockLabel;
106
59
  return "Humanization Score";
107
- }).sections((_) => [
108
- {
109
- type: "link",
110
- href: "/",
111
- label: "Table"
112
- },
113
- {
114
- type: "link",
115
- href: "/histogram",
116
- label: "Score Distribution"
117
- },
118
- {
119
- type: "link",
120
- href: "/by-sample",
121
- label: "By Sample"
122
- }
123
- ]).done();
60
+ }).sections((_) => [{
61
+ type: "link",
62
+ href: "/",
63
+ label: "Table"
64
+ }, {
65
+ type: "link",
66
+ href: "/histogram",
67
+ label: "Score Distribution"
68
+ }]).done();
124
69
  //#endregion
125
- export { HUMANNESS_SCORE_COLUMN, defaultGraphStateBoxplot, defaultGraphStateHistogram, platforma };
70
+ export { HUMANNESS_SCORE_COLUMN, defaultGraphStateHistogram, platforma };
126
71
 
127
72
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { GraphMakerState } from '@milaboratories/graph-maker';\nimport type {\n PColumnIdAndSpec,\n PFrameHandle,\n PlDataTableStateV2,\n PlRef,\n} from '@platforma-sdk/model';\nimport {\n ArrayColumnProvider,\n BlockModelV3,\n DataModelBuilder,\n createPFrameForGraphs,\n createPlDataTableStateV2,\n createPlDataTableV3,\n} from '@platforma-sdk/model';\nexport type * from '@milaboratories/helpers';\n\ntype OldArgs = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n};\n\ntype OldUiState = {\n tableState: PlDataTableStateV2;\n graphStateHistogram?: GraphMakerState;\n graphStateBoxplot?: GraphMakerState;\n};\n\nexport type BlockData = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n tableState: PlDataTableStateV2;\n // Distribution of the per-clonotype humanness score across the whole dataset.\n graphStateHistogram: GraphMakerState;\n // Per-sample distribution of humanness (box/violin), grouped by sampleId.\n graphStateBoxplot: GraphMakerState;\n};\n\n// Humanness score column name emitted by `clonotype-process.tpl.tengo`.\nexport const HUMANNESS_SCORE_COLUMN = 'pl7.app/humannessScore';\n\nexport const defaultGraphStateHistogram = (): GraphMakerState => ({\n title: 'Humanness Score Distribution',\n template: 'bins',\n currentTab: null,\n axesSettings: {\n other: { binsCount: 20 },\n },\n});\n\nexport const defaultGraphStateBoxplot = (): GraphMakerState => ({\n title: 'Humanness by Sample',\n template: 'box',\n currentTab: null,\n});\n\n// Selectors for the input dataset anchor — shared between `inputOptions`\n// (the dropdown) and `subtitle` (so the default label matches the dataset name).\nconst inputSelectors = [{\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/clonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}, {\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/scClonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}];\n\nconst dataModel = new DataModelBuilder()\n .from<BlockData>('v1')\n .upgradeLegacy<OldArgs, OldUiState>(({ args, uiState }) => ({\n ...args,\n tableState: uiState.tableState,\n graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram(),\n graphStateBoxplot: uiState.graphStateBoxplot ?? defaultGraphStateBoxplot(),\n }))\n .init(() => ({\n customBlockLabel: '',\n tableState: createPlDataTableStateV2(),\n graphStateHistogram: defaultGraphStateHistogram(),\n graphStateBoxplot: defaultGraphStateBoxplot(),\n }));\n\nexport const platforma = BlockModelV3.create(dataModel)\n\n .args((data) => {\n if (!data.inputAnchor) throw new Error('Input anchor is required');\n\n return {\n // Empty when unset; the workflow falls back to the input dataset name so\n // the provenance trace label matches the block subtitle.\n customBlockLabel: data.customBlockLabel || '',\n inputAnchor: data.inputAnchor,\n mem: data.mem,\n };\n })\n\n .output('inputOptions', (ctx) =>\n ctx.resultPool.getOptions(inputSelectors),\n )\n\n .outputWithStatus('pt', (ctx) => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) {\n return undefined;\n }\n return createPlDataTableV3(ctx, {\n tableState: ctx.data.tableState,\n columns: new ArrayColumnProvider(pCols)\n .getAllColumns()\n .map((column) => ({ column, isPrimary: true })),\n });\n })\n\n // --- Score distribution (histogram) ---------------------------------------\n // One row per clonotype, so the histogram counts UNIQUE clonotypes by humanness\n // score — it is deliberately NOT weighted by clonotype abundance. The question it\n // answers is \"how many distinct candidates sit below/above a humanness level\"\n // (i.e. how much humanization work is there), not \"how human is the repertoire by\n // read mass\". No human-like threshold line is drawn: this score is a 9-mer\n // fraction rescaled to 0..100, not a cutoff validated against therapeutic mAbs.\n .outputWithStatus('histogramPf', (ctx): PFrameHandle | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) return undefined;\n return createPFrameForGraphs(ctx, pCols);\n })\n\n .output('histogramPfPcols', (ctx): PColumnIdAndSpec[] | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined || pCols.length === 0) return undefined;\n return pCols.map((c) => ({ columnId: c.id, spec: c.spec }));\n })\n\n // --- Per-sample distribution (box / violin) --------------------------------\n // The humanness column is keyed by clonotypeKey only (sample-agnostic). To get\n // a per-sample view we join it with the input dataset's primary abundance\n // column, which carries the [sampleId, clonotypeKey] axes. graph-maker joins on\n // the shared clonotypeKey axis, so each (sample, clonotype) pair contributes the\n // clonotype's score — grouping by sampleId then yields a distribution per sample.\n // This is a box/violin (median + spread + tails) on purpose, not a per-sample\n // mean: the spread is exactly what a single mean would hide.\n // Degrades gracefully: if the dataset has no primary-abundance column the join\n // adds nothing, the sampleId axis is absent, and the page simply can't preselect\n // a grouping (the chart still opens). VDJ datasets almost always carry abundance.\n .outputWithStatus('perSamplePf', (ctx): PFrameHandle | undefined => {\n const humanness = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (humanness === undefined) return undefined;\n\n const ref = ctx.data.inputAnchor;\n if (ref === undefined) return undefined;\n\n const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{\n axes: [{ anchor: 'main', idx: 0 }, { anchor: 'main', idx: 1 }],\n annotations: {\n 'pl7.app/isAbundance': 'true',\n 'pl7.app/abundance/normalized': 'false',\n 'pl7.app/abundance/isPrimary': 'true',\n },\n }]);\n\n return createPFrameForGraphs(ctx, [...humanness, ...(abundance ?? [])]);\n })\n\n .output('perSamplePfPcols', (ctx): PColumnIdAndSpec[] | undefined => {\n const humanness = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (humanness === undefined || humanness.length === 0) return undefined;\n\n const ref = ctx.data.inputAnchor;\n if (ref === undefined) return undefined;\n\n const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{\n axes: [{ anchor: 'main', idx: 0 }, { anchor: 'main', idx: 1 }],\n annotations: {\n 'pl7.app/isAbundance': 'true',\n 'pl7.app/abundance/normalized': 'false',\n 'pl7.app/abundance/isPrimary': 'true',\n },\n }]);\n\n return [...humanness, ...(abundance ?? [])].map((c) => ({ columnId: c.id, spec: c.spec }));\n })\n\n .output('isRunning', (ctx) => ctx.outputs?.getIsReadyOrError() === false)\n\n .title(() => 'Humanization Score')\n\n .subtitle((ctx) => {\n if (ctx.data.customBlockLabel) return ctx.data.customBlockLabel;\n return 'Humanization Score';\n })\n\n .sections((_) => [\n { type: 'link', href: '/', label: 'Table' },\n { type: 'link', href: '/histogram', label: 'Score Distribution' },\n { type: 'link', href: '/by-sample', label: 'By Sample' },\n ])\n\n .done();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { GraphMakerState } from '@milaboratories/graph-maker';\nimport type {\n PColumnIdAndSpec,\n PFrameHandle,\n PlDataTableStateV2,\n PlRef,\n} from '@platforma-sdk/model';\nimport {\n BlockModelV3,\n DataModelBuilder, createPFrameForGraphs,\n createPlDataTableStateV2,\n createPlDataTableV3,\n} from '@platforma-sdk/model';\nexport type * from '@milaboratories/helpers';\n\ntype OldArgs = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n};\n\ntype OldUiState = {\n tableState: PlDataTableStateV2;\n graphStateHistogram?: GraphMakerState;\n};\n\nexport type BlockData = {\n customBlockLabel: string;\n inputAnchor?: PlRef;\n mem?: number;\n tableState: PlDataTableStateV2;\n // Distribution of the per-clonotype humanness score across the whole dataset.\n graphStateHistogram: GraphMakerState;\n};\n\n// Humanness score column name emitted by `clonotype-process.tpl.tengo`.\nexport const HUMANNESS_SCORE_COLUMN = 'pl7.app/humannessScore';\n\nexport const defaultGraphStateHistogram = (): GraphMakerState => ({\n title: 'Humanness Score Distribution',\n template: 'bins',\n currentTab: null,\n axesSettings: {\n other: { binsCount: 20 },\n },\n // Give the bars a solid fill instead of the default white — colour values\n // taken from graph-maker's fixed palette (\"Blue\").\n layersSettings: {\n bins: { fillColor: '#2D93FA' },\n },\n});\n\n// Selectors for the input dataset anchor — shared between `inputOptions`\n// (the dropdown) and `subtitle` (so the default label matches the dataset name).\nconst inputSelectors = [{\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/clonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}, {\n axes: [\n { name: 'pl7.app/sampleId' },\n { name: 'pl7.app/vdj/scClonotypeKey' },\n ],\n annotations: { 'pl7.app/isAnchor': 'true' },\n}];\n\nconst dataModel = new DataModelBuilder()\n .from<BlockData>('v1')\n .upgradeLegacy<OldArgs, OldUiState>(({ args, uiState }) => ({\n ...args,\n tableState: uiState.tableState,\n graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram(),\n }))\n .init(() => ({\n customBlockLabel: '',\n tableState: createPlDataTableStateV2(),\n graphStateHistogram: defaultGraphStateHistogram(),\n }));\n\nexport const platforma = BlockModelV3.create(dataModel)\n\n .args((data) => {\n if (!data.inputAnchor) throw new Error('Input anchor is required');\n\n return {\n // Empty when unset; the workflow falls back to the input dataset name so\n // the provenance trace label matches the block subtitle.\n customBlockLabel: data.customBlockLabel || '',\n inputAnchor: data.inputAnchor,\n mem: data.mem,\n };\n })\n\n .output('inputOptions', (ctx) =>\n ctx.resultPool.getOptions(inputSelectors),\n )\n\n .outputWithStatus('pt', (ctx) => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) {\n return undefined;\n }\n\n const anchorCol = pCols[0];\n if (anchorCol === undefined) {\n return undefined;\n }\n\n return createPlDataTableV3(ctx, {\n tableState: ctx.data.tableState,\n columns: {\n anchors: { main: anchorCol.spec },\n selector: { mode: 'enrichment' },\n },\n });\n })\n\n .outputWithStatus('histogramPf', (ctx): PFrameHandle | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined) return undefined;\n return createPFrameForGraphs(ctx, pCols);\n })\n\n .output('histogramPfPcols', (ctx): PColumnIdAndSpec[] | undefined => {\n const pCols = ctx.outputs?.resolve('outputHumanness')?.getPColumns();\n if (pCols === undefined || pCols.length === 0) return undefined;\n return pCols.map((c) => ({ columnId: c.id, spec: c.spec }));\n })\n\n .output('isRunning', (ctx) => ctx.outputs?.getIsReadyOrError() === false)\n\n .title(() => 'Humanization Score')\n\n .subtitle((ctx) => {\n if (ctx.data.customBlockLabel) return ctx.data.customBlockLabel;\n return 'Humanization Score';\n })\n\n .sections((_) => [\n { type: 'link', href: '/', label: 'Table' },\n { type: 'link', href: '/histogram', label: 'Score Distribution' },\n ])\n\n .done();\n"],"mappings":";;AAoCA,MAAa,yBAAyB;AAEtC,MAAa,oCAAqD;CAChE,OAAO;CACP,UAAU;CACV,YAAY;CACZ,cAAc,EACZ,OAAO,EAAE,WAAW,IAAI,EACzB;CAGD,gBAAgB,EACd,MAAM,EAAE,WAAW,WAAW,EAC/B;CACF;AAID,MAAM,iBAAiB,CAAC;CACtB,MAAM,CACJ,EAAE,MAAM,oBAAoB,EAC5B,EAAE,MAAM,4BAA4B,CACrC;CACD,aAAa,EAAE,oBAAoB,QAAQ;CAC5C,EAAE;CACD,MAAM,CACJ,EAAE,MAAM,oBAAoB,EAC5B,EAAE,MAAM,8BAA8B,CACvC;CACD,aAAa,EAAE,oBAAoB,QAAQ;CAC5C,CAAC;AAEF,MAAM,YAAY,IAAI,kBAAkB,CACrC,KAAgB,KAAK,CACrB,eAAoC,EAAE,MAAM,eAAe;CAC1D,GAAG;CACH,YAAY,QAAQ;CACpB,qBAAqB,QAAQ,uBAAuB,4BAA4B;CACjF,EAAE,CACF,YAAY;CACX,kBAAkB;CAClB,YAAY,0BAA0B;CACtC,qBAAqB,4BAA4B;CAClD,EAAE;AAEL,MAAa,YAAY,aAAa,OAAO,UAAU,CAEpD,MAAM,SAAS;CACd,IAAI,CAAC,KAAK,aAAa,MAAM,IAAI,MAAM,2BAA2B;CAElE,OAAO;EAGL,kBAAkB,KAAK,oBAAoB;EAC3C,aAAa,KAAK;EAClB,KAAK,KAAK;EACX;EACD,CAED,OAAO,iBAAiB,QACvB,IAAI,WAAW,WAAW,eAAe,CAC1C,CAEA,iBAAiB,OAAO,QAAQ;CAC/B,MAAM,QAAQ,IAAI,SAAS,QAAQ,kBAAkB,EAAE,aAAa;CACpE,IAAI,UAAU,KAAA,GACZ;CAGF,MAAM,YAAY,MAAM;CACxB,IAAI,cAAc,KAAA,GAChB;CAGF,OAAO,oBAAoB,KAAK;EAC9B,YAAY,IAAI,KAAK;EACrB,SAAS;GACP,SAAS,EAAE,MAAM,UAAU,MAAM;GACjC,UAAU,EAAE,MAAM,cAAc;GACjC;EACF,CAAC;EACF,CAED,iBAAiB,gBAAgB,QAAkC;CAClE,MAAM,QAAQ,IAAI,SAAS,QAAQ,kBAAkB,EAAE,aAAa;CACpE,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,OAAO,sBAAsB,KAAK,MAAM;EACxC,CAED,OAAO,qBAAqB,QAAwC;CACnE,MAAM,QAAQ,IAAI,SAAS,QAAQ,kBAAkB,EAAE,aAAa;CACpE,IAAI,UAAU,KAAA,KAAa,MAAM,WAAW,GAAG,OAAO,KAAA;CACtD,OAAO,MAAM,KAAK,OAAO;EAAE,UAAU,EAAE;EAAI,MAAM,EAAE;EAAM,EAAE;EAC3D,CAED,OAAO,cAAc,QAAQ,IAAI,SAAS,mBAAmB,KAAK,MAAM,CAExE,YAAY,qBAAqB,CAEjC,UAAU,QAAQ;CACjB,IAAI,IAAI,KAAK,kBAAkB,OAAO,IAAI,KAAK;CAC/C,OAAO;EACP,CAED,UAAU,MAAM,CACf;CAAE,MAAM;CAAQ,MAAM;CAAK,OAAO;CAAS,EAC3C;CAAE,MAAM;CAAQ,MAAM;CAAc,OAAO;CAAsB,CAClE,CAAC,CAED,MAAM"}