@platforma-open/milaboratories.top-antibodies.workflow 1.1.1 → 1.2.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.
- package/.turbo/turbo-build.log +9 -1
- package/CHANGELOG.md +18 -0
- package/dist/tengo/lib/pf-spectratype-conv.lib.tengo +59 -0
- package/dist/tengo/lib/pf-umap-conv.lib.tengo +43 -0
- package/dist/tengo/lib/pf-vj-usage-conv.lib.tengo +54 -0
- package/dist/tengo/lib/sampled-cols-conv.lib.tengo +7 -8
- package/dist/tengo/lib/sampled-cols-umap-conv.lib.tengo +38 -0
- package/dist/tengo/tpl/main.plj.gz +0 -0
- package/package.json +6 -4
- package/src/main.tpl.tengo +209 -28
- package/src/pf-spectratype-conv.lib.tengo +59 -0
- package/src/pf-umap-conv.lib.tengo +43 -0
- package/src/pf-vj-usage-conv.lib.tengo +54 -0
- package/src/sampled-cols-conv.lib.tengo +7 -8
- package/src/sampled-cols-umap-conv.lib.tengo +38 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/work/top-antibodies/top-antibodies/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-open/milaboratories.top-antibodies.workflow@1.
|
|
3
|
+
> @platforma-open/milaboratories.top-antibodies.workflow@1.2.1 build /home/runner/work/top-antibodies/top-antibodies/workflow
|
|
4
4
|
> rm -rf dist && pl-tengo check && pl-tengo build
|
|
5
5
|
|
|
6
6
|
Processing "src/main.tpl.tengo"...
|
|
7
|
+
Processing "src/pf-spectratype-conv.lib.tengo"...
|
|
8
|
+
Processing "src/pf-umap-conv.lib.tengo"...
|
|
9
|
+
Processing "src/pf-vj-usage-conv.lib.tengo"...
|
|
7
10
|
Processing "src/sampled-cols-conv.lib.tengo"...
|
|
11
|
+
Processing "src/sampled-cols-umap-conv.lib.tengo"...
|
|
8
12
|
No syntax errors found.
|
|
9
13
|
info: Compiling 'dist'...
|
|
14
|
+
info: - writing /home/runner/work/top-antibodies/top-antibodies/workflow/dist/tengo/lib/pf-spectratype-conv.lib.tengo
|
|
15
|
+
info: - writing /home/runner/work/top-antibodies/top-antibodies/workflow/dist/tengo/lib/pf-umap-conv.lib.tengo
|
|
16
|
+
info: - writing /home/runner/work/top-antibodies/top-antibodies/workflow/dist/tengo/lib/pf-vj-usage-conv.lib.tengo
|
|
10
17
|
info: - writing /home/runner/work/top-antibodies/top-antibodies/workflow/dist/tengo/lib/sampled-cols-conv.lib.tengo
|
|
18
|
+
info: - writing /home/runner/work/top-antibodies/top-antibodies/workflow/dist/tengo/lib/sampled-cols-umap-conv.lib.tengo
|
|
11
19
|
info: - writing /home/runner/work/top-antibodies/top-antibodies/workflow/dist/tengo/tpl/main.plj.gz
|
|
12
20
|
info: Template Pack build done.
|
|
13
21
|
info: Template Pack build done.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @platforma-open/milaboratories.top-antibodies.workflow
|
|
2
2
|
|
|
3
|
+
## 1.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [6443da1]
|
|
8
|
+
- @platforma-open/milaboratories.top-antibodies.spectratype@1.2.0
|
|
9
|
+
|
|
10
|
+
## 1.2.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- 5ee90ac: Add CDR3 spectratype
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [5ee90ac]
|
|
19
|
+
- @platforma-open/milaboratories.top-antibodies.spectratype@1.1.0
|
|
20
|
+
|
|
3
21
|
## 1.1.1
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
getColumns := func() {
|
|
4
|
+
return {
|
|
5
|
+
"axes": [
|
|
6
|
+
{
|
|
7
|
+
"column": "chain",
|
|
8
|
+
"spec": {
|
|
9
|
+
"name": "pl7.app/vdj/chain",
|
|
10
|
+
"type": "String",
|
|
11
|
+
"annotations": { "pl7.app/label": "CDR3 chain" }
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"column": "cdr3Length",
|
|
16
|
+
"spec": {
|
|
17
|
+
"name": "pl7.app/vdj/sequenceLength",
|
|
18
|
+
"type": "Int",
|
|
19
|
+
"domain": {
|
|
20
|
+
"pl7.app/vdj/feature": "CDR3",
|
|
21
|
+
"pl7.app/alphabet": "aminoacid"
|
|
22
|
+
},
|
|
23
|
+
"annotations": { "pl7.app/label": "CDR3 aa Length" }
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"column": "vGene",
|
|
28
|
+
"spec": {
|
|
29
|
+
"name": "pl7.app/vdj/geneHit",
|
|
30
|
+
"type": "String",
|
|
31
|
+
"domain": { "pl7.app/vdj/reference": "VGene" },
|
|
32
|
+
"annotations": {
|
|
33
|
+
"pl7.app/label": "Best V gene"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"columns": [
|
|
39
|
+
{
|
|
40
|
+
"column": "count",
|
|
41
|
+
"spec": {
|
|
42
|
+
"name": "pl7.app/vdj/vSpectratype",
|
|
43
|
+
"valueType": "Int",
|
|
44
|
+
"domain": {
|
|
45
|
+
"pl7.app/vdj/feature": "CDR3",
|
|
46
|
+
"pl7.app/alphabet": "aminoacid"
|
|
47
|
+
},
|
|
48
|
+
"annotations": { "pl7.app/label": "CDR3 V Spectratype" }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"storageFormat": "Binary",
|
|
53
|
+
"partitionKeyLength": 0
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export ll.toStrict({
|
|
58
|
+
getColumns: getColumns
|
|
59
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
getColumns := func(datasetSpec) {
|
|
4
|
+
return {
|
|
5
|
+
"axes": [
|
|
6
|
+
{
|
|
7
|
+
"column": "clonotypeKey",
|
|
8
|
+
"spec": datasetSpec.axesSpec[1]
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"columns": [
|
|
12
|
+
{
|
|
13
|
+
"column": "UMAP1",
|
|
14
|
+
"id": "umap1",
|
|
15
|
+
"allowNA": false,
|
|
16
|
+
"spec": {
|
|
17
|
+
"name": "pl7.app/vdj/umap1",
|
|
18
|
+
"valueType": "Double",
|
|
19
|
+
"annotations": {
|
|
20
|
+
"pl7.app/label": "UMAP Dim1"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"column": "UMAP2",
|
|
26
|
+
"id": "umap2",
|
|
27
|
+
"allowNA": false,
|
|
28
|
+
"spec": {
|
|
29
|
+
"name": "pl7.app/vdj/umap2",
|
|
30
|
+
"valueType": "Double",
|
|
31
|
+
"annotations": {
|
|
32
|
+
"pl7.app/label": "UMAP Dim2"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}],
|
|
36
|
+
"storageFormat": "Binary",
|
|
37
|
+
"partitionKeyLength": 0
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export ll.toStrict({
|
|
42
|
+
getColumns: getColumns
|
|
43
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
getColumns := func() {
|
|
4
|
+
return {
|
|
5
|
+
"axes": [
|
|
6
|
+
{
|
|
7
|
+
"column": "chain",
|
|
8
|
+
"spec": {
|
|
9
|
+
"name": "pl7.app/vdj/chain",
|
|
10
|
+
"type": "String",
|
|
11
|
+
"annotations": { "pl7.app/label": "CDR3 chain" }
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"column": "vGene",
|
|
16
|
+
"spec": {
|
|
17
|
+
"name": "pl7.app/vdj/geneHit",
|
|
18
|
+
"type": "String",
|
|
19
|
+
"domain": { "pl7.app/vdj/reference": "VGene" },
|
|
20
|
+
"annotations": {
|
|
21
|
+
"pl7.app/label": "Best V gene"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"column": "jGene",
|
|
27
|
+
"spec": {
|
|
28
|
+
"name": "pl7.app/vdj/geneHit",
|
|
29
|
+
"type": "String",
|
|
30
|
+
"domain": { "pl7.app/vdj/reference": "JGene" },
|
|
31
|
+
"annotations": {
|
|
32
|
+
"pl7.app/label": "Best J gene"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"columns": [
|
|
38
|
+
{
|
|
39
|
+
"column": "count",
|
|
40
|
+
"spec": {
|
|
41
|
+
"name": "pl7.app/vdj/vjGeneUsage",
|
|
42
|
+
"valueType": "Int",
|
|
43
|
+
"annotations": { "pl7.app/label": "V/J usage" }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"storageFormat": "Binary",
|
|
48
|
+
"partitionKeyLength": 0
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export ll.toStrict({
|
|
53
|
+
getColumns: getColumns
|
|
54
|
+
})
|
|
@@ -9,11 +9,11 @@ getColumns := func(datasetSpec, linkerAxisSpec) {
|
|
|
9
9
|
|
|
10
10
|
if len(linkerAxisSpec) > 0 {
|
|
11
11
|
for key, val in linkerAxisSpec {
|
|
12
|
-
axes
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
axes = axes + [
|
|
13
|
+
{
|
|
14
|
+
"column": key,
|
|
15
|
+
"spec": val
|
|
16
|
+
}]
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
}
|
|
@@ -25,12 +25,11 @@ getColumns := func(datasetSpec, linkerAxisSpec) {
|
|
|
25
25
|
"id": "link",
|
|
26
26
|
"allowNA": false,
|
|
27
27
|
"spec": {
|
|
28
|
-
"name": "pl7.app/vdj/
|
|
28
|
+
"name": "pl7.app/vdj/sampling-column",
|
|
29
29
|
"valueType": "Int",
|
|
30
30
|
"domain": {},
|
|
31
31
|
"annotations": {
|
|
32
|
-
"pl7.app/
|
|
33
|
-
"pl7.app/label": "Linker column",
|
|
32
|
+
"pl7.app/label": "Sampling column",
|
|
34
33
|
"pl7.app/table/visibility": "optional"
|
|
35
34
|
}
|
|
36
35
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
getColumns := func(datasetSpec) {
|
|
6
|
+
axes := [
|
|
7
|
+
{
|
|
8
|
+
"column": "clonotypeKey",
|
|
9
|
+
"spec": datasetSpec.axesSpec[1]
|
|
10
|
+
}]
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
"axes": axes,
|
|
14
|
+
"columns": [
|
|
15
|
+
{
|
|
16
|
+
"column": "top",
|
|
17
|
+
"id": "link2", // temporal change
|
|
18
|
+
"allowNA": false,
|
|
19
|
+
"spec": {
|
|
20
|
+
"name": "pl7.app/vdj/sampling-column-umap",
|
|
21
|
+
"valueType": "Int",
|
|
22
|
+
"domain": {},
|
|
23
|
+
"annotations": {
|
|
24
|
+
"pl7.app/label": "Top clonotypes",
|
|
25
|
+
"pl7.app/table/visibility": "optional",
|
|
26
|
+
"pl7.app/isSubset": "true"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"storageFormat": "Binary",
|
|
32
|
+
"partitionKeyLength": 0
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export ll.toStrict({
|
|
37
|
+
getColumns: getColumns
|
|
38
|
+
})
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-open/milaboratories.top-antibodies.workflow",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Block Workflow",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@platforma-sdk/workflow-tengo": "^4.
|
|
8
|
-
"@platforma-open/milaboratories.top-antibodies.
|
|
7
|
+
"@platforma-sdk/workflow-tengo": "^4.5.1",
|
|
8
|
+
"@platforma-open/milaboratories.top-antibodies.sample-clonotypes": "1.0.1",
|
|
9
|
+
"@platforma-open/milaboratories.top-antibodies.umap": "1.0.1",
|
|
10
|
+
"@platforma-open/milaboratories.top-antibodies.spectratype": "1.2.0"
|
|
9
11
|
},
|
|
10
12
|
"devDependencies": {
|
|
11
13
|
"@platforma-sdk/tengo-builder": "^2.1.3",
|
|
12
|
-
"@platforma-sdk/test": "^1.30.
|
|
14
|
+
"@platforma-sdk/test": "^1.30.39",
|
|
13
15
|
"vitest": "^2.1.8"
|
|
14
16
|
},
|
|
15
17
|
"scripts": {
|
package/src/main.tpl.tengo
CHANGED
|
@@ -5,7 +5,11 @@ assets:= import("@platforma-sdk/workflow-tengo:assets")
|
|
|
5
5
|
xsv := import("@platforma-sdk/workflow-tengo:pframes.xsv")
|
|
6
6
|
pframes := import("@platforma-sdk/workflow-tengo:pframes")
|
|
7
7
|
sampledColsConv := import(":sampled-cols-conv")
|
|
8
|
-
|
|
8
|
+
sampledColsUmapConv := import(":sampled-cols-umap-conv")
|
|
9
|
+
spectratypeConv := import(":pf-spectratype-conv")
|
|
10
|
+
vjUsageConv := import(":pf-vj-usage-conv")
|
|
11
|
+
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
12
|
+
umapConv := import(":pf-umap-conv")
|
|
9
13
|
|
|
10
14
|
wf.prepare(func(args){
|
|
11
15
|
// We need a table with cluster ID (optional) | clonotype id | selected ranking columns
|
|
@@ -18,12 +22,52 @@ wf.prepare(func(args){
|
|
|
18
22
|
bundleBuilder.addSingle(col)
|
|
19
23
|
}
|
|
20
24
|
|
|
25
|
+
// Add linker column
|
|
26
|
+
bundleBuilder.addMulti({
|
|
27
|
+
axes: [{ anchor: "main", idx: 1 }], // this will do partial axes match (unlike in the model)
|
|
28
|
+
annotations: { "pl7.app/isLinkerColumn": "true" },
|
|
29
|
+
partialAxesMatch: true
|
|
30
|
+
}, "linkers")
|
|
31
|
+
|
|
32
|
+
// Add full aa sequence column
|
|
21
33
|
bundleBuilder.addMulti({
|
|
22
34
|
axes: [{ anchor: "main", idx: 1 }],
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
annotations: {
|
|
36
|
+
"pl7.app/vdj/isAssemblingFeature": "true",
|
|
37
|
+
"pl7.app/vdj/isMainSequence": "true"
|
|
25
38
|
},
|
|
26
|
-
|
|
39
|
+
domain: {
|
|
40
|
+
"pl7.app/alphabet": "aminoacid"
|
|
41
|
+
}
|
|
42
|
+
}, "aaSequence")
|
|
43
|
+
|
|
44
|
+
// Add CDR3 sequences
|
|
45
|
+
bundleBuilder.addMulti({
|
|
46
|
+
axes: [{ anchor: "main", idx: 1 }], // Clonotype axis
|
|
47
|
+
name: "pl7.app/vdj/sequence",
|
|
48
|
+
domain: {
|
|
49
|
+
"pl7.app/alphabet": "aminoacid",
|
|
50
|
+
"pl7.app/vdj/feature": "CDR3" // Specify CDR3 feature
|
|
51
|
+
}
|
|
52
|
+
}, "cdr3Sequences") // New collection name for CDR3 sequences
|
|
53
|
+
|
|
54
|
+
// Add V gene
|
|
55
|
+
bundleBuilder.addMulti({
|
|
56
|
+
axes: [{ anchor: "main", idx: 1 }], // Clonotype axis
|
|
57
|
+
name: "pl7.app/vdj/geneHit",
|
|
58
|
+
domain: {
|
|
59
|
+
"pl7.app/vdj/reference": "VGene"
|
|
60
|
+
}
|
|
61
|
+
}, "VGenes")
|
|
62
|
+
|
|
63
|
+
// Add J gene
|
|
64
|
+
bundleBuilder.addMulti({
|
|
65
|
+
axes: [{ anchor: "main", idx: 1 }], // Clonotype axis
|
|
66
|
+
name: "pl7.app/vdj/geneHit",
|
|
67
|
+
domain: {
|
|
68
|
+
"pl7.app/vdj/reference": "JGene"
|
|
69
|
+
}
|
|
70
|
+
}, "JGenes")
|
|
27
71
|
|
|
28
72
|
return {
|
|
29
73
|
columns: bundleBuilder.build()
|
|
@@ -32,57 +76,194 @@ wf.prepare(func(args){
|
|
|
32
76
|
|
|
33
77
|
wf.body(func(args) {
|
|
34
78
|
|
|
79
|
+
// Input arguments
|
|
35
80
|
columns := args.columns
|
|
36
81
|
datasetSpec := columns.getSpec(args.inputAnchor)
|
|
82
|
+
|
|
37
83
|
topClonotypes := args.topClonotypes
|
|
84
|
+
|
|
85
|
+
// Needed conditional variables
|
|
86
|
+
isSingleCell := datasetSpec.axesSpec[1].name == "pl7.app/vdj/scClonotypeKey"
|
|
38
87
|
|
|
88
|
+
// output containers
|
|
89
|
+
outputs := {}
|
|
39
90
|
|
|
40
|
-
|
|
41
|
-
|
|
91
|
+
////////// Clonotype Filtering //////////
|
|
92
|
+
|
|
93
|
+
// Build clonotype table
|
|
94
|
+
cloneTable := columns.xsvTableBuilder()
|
|
95
|
+
cloneTable.setAxisHeader(datasetSpec.axesSpec[1].name, "clonotypeKey")
|
|
42
96
|
|
|
43
97
|
for i, col in args.rankingOrder {
|
|
44
|
-
|
|
98
|
+
cloneTable.add(col, {header: "Col" + string(i)})
|
|
99
|
+
|
|
100
|
+
// If column does not have main anchor axis we have to include theirs
|
|
101
|
+
colsSpec := columns.getSpec(col)
|
|
102
|
+
axesNames := slices.map(colsSpec.axesSpec, func (a) { return a.name})
|
|
103
|
+
if !slices.hasElement(axesNames, datasetSpec.axesSpec[1].name) {
|
|
104
|
+
for na, ax in colsSpec.axesSpec {
|
|
105
|
+
if ax.name != datasetSpec.axesSpec[1].name {
|
|
106
|
+
cloneTable.setAxisHeader(ax.name, "cluster_" + string(i) + string(na))
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
45
110
|
}
|
|
46
111
|
|
|
47
112
|
// Columns gotten by query require .key
|
|
48
113
|
linkerAxisSpec := {}
|
|
49
|
-
for i, col in columns.getColumns("
|
|
114
|
+
for i, col in columns.getColumns("linkers") {
|
|
50
115
|
if datasetSpec.axesSpec[1].name == col.spec.axesSpec[1].name {
|
|
51
|
-
|
|
52
|
-
|
|
116
|
+
cloneTable.add(col.key, {header: "linker." + string(i)})
|
|
117
|
+
cloneTable.setAxisHeader(col.spec.axesSpec[0].name, "cluster_" + string(i))
|
|
53
118
|
linkerAxisSpec["cluster_" + string(i)] = col.spec.axesSpec[0]
|
|
54
119
|
} else if datasetSpec.axesSpec[1].name == col.spec.axesSpec[0].name {
|
|
55
|
-
|
|
56
|
-
|
|
120
|
+
cloneTable.add(col.key, {header: "linker." + string(i)})
|
|
121
|
+
cloneTable.setAxisHeader(col.spec.axesSpec[1].name, "cluster_" + string(i))
|
|
57
122
|
linkerAxisSpec["cluster_" + string(i)] = col.spec.axesSpec[1]
|
|
58
123
|
}
|
|
59
|
-
|
|
60
124
|
}
|
|
125
|
+
cloneTable = cloneTable.build("csv")
|
|
61
126
|
|
|
62
|
-
|
|
127
|
+
if topClonotypes != undefined {
|
|
128
|
+
// Run sampling script
|
|
129
|
+
sampleClones := exec.builder().
|
|
130
|
+
software(assets.importSoftware("@platforma-open/milaboratories.top-antibodies.sample-clonotypes:main")).
|
|
131
|
+
addFile("filteredClonotypes.csv", cloneTable).
|
|
132
|
+
arg("--csv").arg("filteredClonotypes.csv").
|
|
133
|
+
arg("--n").arg(string(topClonotypes)).
|
|
134
|
+
arg("--out").arg("sampledClonotypes.csv").
|
|
135
|
+
saveFile("sampledClonotypes_top.csv").
|
|
136
|
+
printErrStreamToStdout().
|
|
137
|
+
saveStdoutContent().
|
|
138
|
+
cache(24 * 60 * 60 * 1000).
|
|
139
|
+
run()
|
|
140
|
+
|
|
141
|
+
// Store outputs
|
|
142
|
+
sampledColsParams := sampledColsConv.getColumns(datasetSpec, linkerAxisSpec)
|
|
143
|
+
sampledColumnsPf := xsv.importFile(sampleClones.getFile("sampledClonotypes_top.csv"), "csv", sampledColsParams)
|
|
144
|
+
outputs["sampledRows"] = pframes.exportFrame(sampledColumnsPf)
|
|
63
145
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
146
|
+
// Prepare filter col subset for UMAP
|
|
147
|
+
// Avoid taking cluster axis using other params
|
|
148
|
+
sampledColsUmapParams := sampledColsUmapConv.getColumns(datasetSpec)
|
|
149
|
+
sampledColsUmapPf := xsv.importFile(sampleClones.getFile("sampledClonotypes_top.csv"), "csv", sampledColsUmapParams)
|
|
150
|
+
outputs["sampledRowsUmap"] = pframes.exportFrame(sampledColsUmapPf)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
////////// UMAP //////////
|
|
154
|
+
// Generate input TSV with Clonotype ID and aa sequence
|
|
155
|
+
umapTable := columns.xsvTableBuilder()
|
|
156
|
+
umapTable.setAxisHeader(datasetSpec.axesSpec[1].name, "clonotypeKey")
|
|
157
|
+
for col in columns.getColumns("aaSequence") {
|
|
158
|
+
if isSingleCell {
|
|
159
|
+
chainLabel := col.spec.domain["pl7.app/vdj/scClonotypeChain"]
|
|
160
|
+
umapTable.add(col.key, {header: "aaSequence." + chainLabel})
|
|
161
|
+
} else {
|
|
162
|
+
chainLabel := col.spec.axesSpec[0].domain["pl7.app/vdj/chain"]
|
|
163
|
+
umapTable.add(col.key, {header: "aaSequence." + chainLabel})
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
umapTable = umapTable.build("tsv")
|
|
167
|
+
|
|
168
|
+
// UMAP script should go here
|
|
169
|
+
umapClones := exec.builder().
|
|
170
|
+
software(assets.importSoftware("@platforma-open/milaboratories.top-antibodies.umap:main")).
|
|
171
|
+
addFile("sequences.tsv", umapTable).
|
|
172
|
+
arg("-i").arg("sequences.tsv").
|
|
173
|
+
arg("-u").arg("umap.tsv").
|
|
174
|
+
saveFile("umap.tsv").
|
|
71
175
|
printErrStreamToStdout().
|
|
72
176
|
saveStdoutContent().
|
|
73
177
|
cache(24 * 60 * 60 * 1000).
|
|
74
178
|
run()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
umapPf := xsv.importFile(umapClones.getFile("umap.tsv"), "tsv", umapConv.getColumns(datasetSpec))
|
|
182
|
+
outputs["umap"] = pframes.exportFrame(umapPf)
|
|
183
|
+
|
|
184
|
+
////////// CDR3 Length Calculation //////////
|
|
75
185
|
|
|
76
|
-
|
|
77
|
-
|
|
186
|
+
cdr3SeqTable := columns.xsvTableBuilder()
|
|
187
|
+
cdr3SeqTable.setAxisHeader(datasetSpec.axesSpec[1].name, "clonotypeKey")
|
|
188
|
+
|
|
189
|
+
// Must deal with multiple CDR3 sequences (two for each cell in single cell data)
|
|
190
|
+
// Chain will be added in the header as cdr3Sequence.chain and used in python script
|
|
191
|
+
// Notice chain is in spec.domain for single cell data and spec.axesSpec[0].domain for bulk data
|
|
192
|
+
|
|
193
|
+
// Helper function to add chain information to the headers dynamically
|
|
194
|
+
chainMapping := {
|
|
195
|
+
"IG": { "A": "Heavy", "B": "Light" },
|
|
196
|
+
"TCRAB": { "A": "TRA", "B": "TRB" },
|
|
197
|
+
"TCRGD": { "A": "TRG", "B": "TRD" }
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
makeHeaderName := func(col, baseHeaderName, isSingleCell) {
|
|
201
|
+
if isSingleCell {
|
|
202
|
+
chain := col.spec.domain["pl7.app/vdj/scClonotypeChain"] // e.g., "A", "B"
|
|
203
|
+
receptor := col.spec.axesSpec[0].domain["pl7.app/vdj/receptor"] // e.g., "IG", "TCRAB", "TCRGD"
|
|
204
|
+
chainLabel := chainMapping[receptor][chain]
|
|
205
|
+
return baseHeaderName + "." + chainLabel
|
|
206
|
+
} else {
|
|
207
|
+
// For bulk, if chain info is available (e.g. IGH, IGK, IGL)
|
|
208
|
+
chainFromDomain := col.spec.axesSpec[0].domain["pl7.app/vdj/chain"] // e.g. "IGH", "IGK"
|
|
209
|
+
if chainFromDomain != undefined {
|
|
210
|
+
return baseHeaderName + "." + chainFromDomain
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return baseHeaderName // Default header for bulk
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// Process CDR3 sequences
|
|
217
|
+
cdr3Sequences := columns.getColumns("cdr3Sequences")
|
|
218
|
+
|
|
219
|
+
for col in cdr3Sequences {
|
|
220
|
+
headerName := makeHeaderName(col, "cdr3Sequence", isSingleCell)
|
|
221
|
+
cdr3SeqTable.add(col.key, {header: headerName})
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Process V genes
|
|
225
|
+
vGenes := columns.getColumns("VGenes")
|
|
226
|
+
|
|
227
|
+
for col in vGenes {
|
|
228
|
+
headerName := makeHeaderName(col, "vGene", isSingleCell)
|
|
229
|
+
cdr3SeqTable.add(col.key, {header: headerName})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Process J genes
|
|
233
|
+
jGenes := columns.getColumns("JGenes")
|
|
78
234
|
|
|
79
|
-
|
|
235
|
+
for col in jGenes {
|
|
236
|
+
headerName := makeHeaderName(col, "jGene", isSingleCell)
|
|
237
|
+
cdr3SeqTable.add(col.key, {header: headerName})
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
cdr3SeqTableBuilt := cdr3SeqTable.build("tsv")
|
|
241
|
+
|
|
242
|
+
cdr3VspectratypeCmd := exec.builder().
|
|
243
|
+
software(assets.importSoftware("@platforma-open/milaboratories.top-antibodies.spectratype:main")).
|
|
244
|
+
addFile("cdr3_sequences_input.tsv", cdr3SeqTableBuilt).
|
|
245
|
+
arg("--input_tsv").arg("cdr3_sequences_input.tsv").
|
|
246
|
+
arg("--spectratype_tsv").arg("spectratype.tsv").
|
|
247
|
+
arg("--vj_usage_tsv").arg("vj_usage.tsv").
|
|
248
|
+
saveFile("spectratype.tsv").
|
|
249
|
+
saveFile("vj_usage.tsv").
|
|
250
|
+
printErrStreamToStdout().
|
|
251
|
+
saveStdoutContent().
|
|
252
|
+
cache(24 * 60 * 60 * 1000).
|
|
253
|
+
run()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
// For spectratype structure is [chain][cdr3Length][vGene] -> count
|
|
257
|
+
|
|
258
|
+
cdr3VspectratypePf := xsv.importFile(cdr3VspectratypeCmd.getFile("spectratype.tsv"), "tsv", spectratypeConv.getColumns())
|
|
259
|
+
outputs["cdr3VspectratypePf"] = pframes.exportFrame(cdr3VspectratypePf)
|
|
260
|
+
|
|
261
|
+
// For vjUsage structure is [chain][vGene][jGene] -> count
|
|
262
|
+
vjUsagePf := xsv.importFile(cdr3VspectratypeCmd.getFile("vj_usage.tsv"), "tsv", vjUsageConv.getColumns())
|
|
263
|
+
outputs["vjUsagePf"] = pframes.exportFrame(vjUsagePf)
|
|
80
264
|
|
|
81
265
|
return {
|
|
82
|
-
outputs:
|
|
83
|
-
"sampledColumns": pframes.exportFrame(sampledColumnsPf)
|
|
84
|
-
},
|
|
266
|
+
outputs: outputs,
|
|
85
267
|
exports: {}
|
|
86
268
|
}
|
|
87
269
|
})
|
|
88
|
-
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
getColumns := func() {
|
|
4
|
+
return {
|
|
5
|
+
"axes": [
|
|
6
|
+
{
|
|
7
|
+
"column": "chain",
|
|
8
|
+
"spec": {
|
|
9
|
+
"name": "pl7.app/vdj/chain",
|
|
10
|
+
"type": "String",
|
|
11
|
+
"annotations": { "pl7.app/label": "CDR3 chain" }
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"column": "cdr3Length",
|
|
16
|
+
"spec": {
|
|
17
|
+
"name": "pl7.app/vdj/sequenceLength",
|
|
18
|
+
"type": "Int",
|
|
19
|
+
"domain": {
|
|
20
|
+
"pl7.app/vdj/feature": "CDR3",
|
|
21
|
+
"pl7.app/alphabet": "aminoacid"
|
|
22
|
+
},
|
|
23
|
+
"annotations": { "pl7.app/label": "CDR3 aa Length" }
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"column": "vGene",
|
|
28
|
+
"spec": {
|
|
29
|
+
"name": "pl7.app/vdj/geneHit",
|
|
30
|
+
"type": "String",
|
|
31
|
+
"domain": { "pl7.app/vdj/reference": "VGene" },
|
|
32
|
+
"annotations": {
|
|
33
|
+
"pl7.app/label": "Best V gene"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"columns": [
|
|
39
|
+
{
|
|
40
|
+
"column": "count",
|
|
41
|
+
"spec": {
|
|
42
|
+
"name": "pl7.app/vdj/vSpectratype",
|
|
43
|
+
"valueType": "Int",
|
|
44
|
+
"domain": {
|
|
45
|
+
"pl7.app/vdj/feature": "CDR3",
|
|
46
|
+
"pl7.app/alphabet": "aminoacid"
|
|
47
|
+
},
|
|
48
|
+
"annotations": { "pl7.app/label": "CDR3 V Spectratype" }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"storageFormat": "Binary",
|
|
53
|
+
"partitionKeyLength": 0
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export ll.toStrict({
|
|
58
|
+
getColumns: getColumns
|
|
59
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
getColumns := func(datasetSpec) {
|
|
4
|
+
return {
|
|
5
|
+
"axes": [
|
|
6
|
+
{
|
|
7
|
+
"column": "clonotypeKey",
|
|
8
|
+
"spec": datasetSpec.axesSpec[1]
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"columns": [
|
|
12
|
+
{
|
|
13
|
+
"column": "UMAP1",
|
|
14
|
+
"id": "umap1",
|
|
15
|
+
"allowNA": false,
|
|
16
|
+
"spec": {
|
|
17
|
+
"name": "pl7.app/vdj/umap1",
|
|
18
|
+
"valueType": "Double",
|
|
19
|
+
"annotations": {
|
|
20
|
+
"pl7.app/label": "UMAP Dim1"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"column": "UMAP2",
|
|
26
|
+
"id": "umap2",
|
|
27
|
+
"allowNA": false,
|
|
28
|
+
"spec": {
|
|
29
|
+
"name": "pl7.app/vdj/umap2",
|
|
30
|
+
"valueType": "Double",
|
|
31
|
+
"annotations": {
|
|
32
|
+
"pl7.app/label": "UMAP Dim2"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}],
|
|
36
|
+
"storageFormat": "Binary",
|
|
37
|
+
"partitionKeyLength": 0
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export ll.toStrict({
|
|
42
|
+
getColumns: getColumns
|
|
43
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
getColumns := func() {
|
|
4
|
+
return {
|
|
5
|
+
"axes": [
|
|
6
|
+
{
|
|
7
|
+
"column": "chain",
|
|
8
|
+
"spec": {
|
|
9
|
+
"name": "pl7.app/vdj/chain",
|
|
10
|
+
"type": "String",
|
|
11
|
+
"annotations": { "pl7.app/label": "CDR3 chain" }
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"column": "vGene",
|
|
16
|
+
"spec": {
|
|
17
|
+
"name": "pl7.app/vdj/geneHit",
|
|
18
|
+
"type": "String",
|
|
19
|
+
"domain": { "pl7.app/vdj/reference": "VGene" },
|
|
20
|
+
"annotations": {
|
|
21
|
+
"pl7.app/label": "Best V gene"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"column": "jGene",
|
|
27
|
+
"spec": {
|
|
28
|
+
"name": "pl7.app/vdj/geneHit",
|
|
29
|
+
"type": "String",
|
|
30
|
+
"domain": { "pl7.app/vdj/reference": "JGene" },
|
|
31
|
+
"annotations": {
|
|
32
|
+
"pl7.app/label": "Best J gene"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"columns": [
|
|
38
|
+
{
|
|
39
|
+
"column": "count",
|
|
40
|
+
"spec": {
|
|
41
|
+
"name": "pl7.app/vdj/vjGeneUsage",
|
|
42
|
+
"valueType": "Int",
|
|
43
|
+
"annotations": { "pl7.app/label": "V/J usage" }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"storageFormat": "Binary",
|
|
48
|
+
"partitionKeyLength": 0
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export ll.toStrict({
|
|
53
|
+
getColumns: getColumns
|
|
54
|
+
})
|
|
@@ -9,11 +9,11 @@ getColumns := func(datasetSpec, linkerAxisSpec) {
|
|
|
9
9
|
|
|
10
10
|
if len(linkerAxisSpec) > 0 {
|
|
11
11
|
for key, val in linkerAxisSpec {
|
|
12
|
-
axes
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
axes = axes + [
|
|
13
|
+
{
|
|
14
|
+
"column": key,
|
|
15
|
+
"spec": val
|
|
16
|
+
}]
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
}
|
|
@@ -25,12 +25,11 @@ getColumns := func(datasetSpec, linkerAxisSpec) {
|
|
|
25
25
|
"id": "link",
|
|
26
26
|
"allowNA": false,
|
|
27
27
|
"spec": {
|
|
28
|
-
"name": "pl7.app/vdj/
|
|
28
|
+
"name": "pl7.app/vdj/sampling-column",
|
|
29
29
|
"valueType": "Int",
|
|
30
30
|
"domain": {},
|
|
31
31
|
"annotations": {
|
|
32
|
-
"pl7.app/
|
|
33
|
-
"pl7.app/label": "Linker column",
|
|
32
|
+
"pl7.app/label": "Sampling column",
|
|
34
33
|
"pl7.app/table/visibility": "optional"
|
|
35
34
|
}
|
|
36
35
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
3
|
+
// modified from sampled-cols-conv.lib.tengo
|
|
4
|
+
|
|
5
|
+
getColumns := func(datasetSpec) {
|
|
6
|
+
axes := [
|
|
7
|
+
{
|
|
8
|
+
"column": "clonotypeKey",
|
|
9
|
+
"spec": datasetSpec.axesSpec[1]
|
|
10
|
+
}]
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
"axes": axes,
|
|
14
|
+
"columns": [
|
|
15
|
+
{
|
|
16
|
+
"column": "top",
|
|
17
|
+
"id": "link2", // temporal change
|
|
18
|
+
"allowNA": false,
|
|
19
|
+
"spec": {
|
|
20
|
+
"name": "pl7.app/vdj/sampling-column-umap",
|
|
21
|
+
"valueType": "Int",
|
|
22
|
+
"domain": {},
|
|
23
|
+
"annotations": {
|
|
24
|
+
"pl7.app/label": "Top clonotypes",
|
|
25
|
+
"pl7.app/table/visibility": "optional",
|
|
26
|
+
"pl7.app/isSubset": "true"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"storageFormat": "Binary",
|
|
32
|
+
"partitionKeyLength": 0
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export ll.toStrict({
|
|
37
|
+
getColumns: getColumns
|
|
38
|
+
})
|