@platforma-open/milaboratories.top-antibodies.workflow 1.17.4 → 1.17.6
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 +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/tengo/lib/sampled-cols-conv.lib.tengo +4 -3
- package/dist/tengo/lib/utils.lib.tengo +87 -1
- package/dist/tengo/tpl/assembling-fasta.plj.gz +0 -0
- package/dist/tengo/tpl/filter-and-sample.plj.gz +0 -0
- package/dist/tengo/tpl/main.plj.gz +0 -0
- package/package.json +6 -6
- package/src/filter-and-sample.tpl.tengo +16 -1
- package/src/main.tpl.tengo +8 -3
- package/src/sampled-cols-conv.lib.tengo +4 -3
- package/src/utils.lib.tengo +87 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/work/antibody-tcr-lead-selection/antibody-tcr-lead-selection/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-open/milaboratories.top-antibodies.workflow@1.17.
|
|
3
|
+
> @platforma-open/milaboratories.top-antibodies.workflow@1.17.6 build /home/runner/work/antibody-tcr-lead-selection/antibody-tcr-lead-selection/workflow
|
|
4
4
|
> shx rm -rf dist && pl-tengo check && pl-tengo build
|
|
5
5
|
|
|
6
6
|
Processing "src/assembling-fasta.tpl.tengo"...
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @platforma-open/milaboratories.top-antibodies.workflow
|
|
2
2
|
|
|
3
|
+
## 1.17.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 65cbdd5: Minor fix to prevent leads spec multiple match
|
|
8
|
+
|
|
9
|
+
## 1.17.5
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- ff606b5: Implement multi-selection filters
|
|
14
|
+
- Updated dependencies [ff606b5]
|
|
15
|
+
- @platforma-open/milaboratories.top-antibodies.sample-clonotypes@1.9.3
|
|
16
|
+
|
|
3
17
|
## 1.17.4
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -6,13 +6,14 @@ getColumns := func(datasetSpec, addRanking) {
|
|
|
6
6
|
id: "link",
|
|
7
7
|
allowNA: false,
|
|
8
8
|
spec: {
|
|
9
|
-
name: "pl7.app/vdj/
|
|
9
|
+
name: "pl7.app/vdj/lead-selection",
|
|
10
10
|
valueType: "Int",
|
|
11
11
|
domain: {},
|
|
12
12
|
annotations: {
|
|
13
|
-
"pl7.app/label": "
|
|
13
|
+
"pl7.app/label": "Selected Leads",
|
|
14
14
|
"pl7.app/table/visibility": "hidden",
|
|
15
|
-
"pl7.app/isSubset": "true"
|
|
15
|
+
"pl7.app/isSubset": "true",
|
|
16
|
+
"pl7.app/toPlot": "true"
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
}]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
4
|
+
json := import("json")
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
|
|
@@ -545,6 +546,89 @@ initializeAssemSeqTable := func(pframes, columns, datasetSpec, isSingleCell) {
|
|
|
545
546
|
}
|
|
546
547
|
}
|
|
547
548
|
|
|
549
|
+
|
|
550
|
+
filterOperatorMap := {
|
|
551
|
+
"number_greaterThan": ">",
|
|
552
|
+
"number_greaterThanOrEqualTo": ">=",
|
|
553
|
+
"number_lessThan": "<",
|
|
554
|
+
"number_lessThanOrEqualTo": "<=",
|
|
555
|
+
"number_equals": "=",
|
|
556
|
+
"number_notEquals": "!=",
|
|
557
|
+
"string_equals": "=",
|
|
558
|
+
"string_notEquals": "!=",
|
|
559
|
+
"string_contains": "contains",
|
|
560
|
+
"string_doesNotContain": "not contains",
|
|
561
|
+
"string_in": "in",
|
|
562
|
+
"string_notIn": "not in"
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
formatFilterDescription := func(columnLabel, filter) {
|
|
574
|
+
if is_undefined(filter) || is_undefined(filter.type) {
|
|
575
|
+
return columnLabel
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
op := filterOperatorMap[filter.type]
|
|
580
|
+
if is_undefined(op) {
|
|
581
|
+
op = filter.type
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
ref := filter.reference
|
|
585
|
+
|
|
586
|
+
if filter.type == "string_in" || filter.type == "string_notIn" {
|
|
587
|
+
values := json.decode(string(ref))
|
|
588
|
+
valStr := "["
|
|
589
|
+
for i, v in values {
|
|
590
|
+
if i > 0 {
|
|
591
|
+
valStr = valStr + ", "
|
|
592
|
+
}
|
|
593
|
+
valStr = valStr + string(v)
|
|
594
|
+
}
|
|
595
|
+
ref = valStr + "]"
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return columnLabel + " " + op + " " + string(ref)
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
buildFilterTraceLabel := func(filters, columns) {
|
|
610
|
+
result := ""
|
|
611
|
+
count := 0
|
|
612
|
+
for filter in filters {
|
|
613
|
+
if !is_undefined(filter.value) {
|
|
614
|
+
colSpec := columns.getSpec(filter.value.column)
|
|
615
|
+
if !is_undefined(colSpec) {
|
|
616
|
+
colLabel := colSpec.annotations["pl7.app/label"]
|
|
617
|
+
if is_undefined(colLabel) {
|
|
618
|
+
colLabel = colSpec.name
|
|
619
|
+
}
|
|
620
|
+
desc := formatFilterDescription(colLabel, filter.filter)
|
|
621
|
+
if count > 0 {
|
|
622
|
+
result = result + ", "
|
|
623
|
+
}
|
|
624
|
+
result = result + desc
|
|
625
|
+
count = count + 1
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return result
|
|
630
|
+
}
|
|
631
|
+
|
|
548
632
|
export {
|
|
549
633
|
clusterAxisDomainsMatch: clusterAxisDomainsMatch,
|
|
550
634
|
findMatchingLinkerIndex: findMatchingLinkerIndex,
|
|
@@ -555,5 +639,7 @@ export {
|
|
|
555
639
|
makeHeaderName: makeHeaderName,
|
|
556
640
|
initializeCdr3SeqTable: initializeCdr3SeqTable,
|
|
557
641
|
detectBulkChain: detectBulkChain,
|
|
558
|
-
initializeAssemSeqTable: initializeAssemSeqTable
|
|
642
|
+
initializeAssemSeqTable: initializeAssemSeqTable,
|
|
643
|
+
formatFilterDescription: formatFilterDescription,
|
|
644
|
+
buildFilterTraceLabel: buildFilterTraceLabel
|
|
559
645
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-open/milaboratories.top-antibodies.workflow",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Block Workflow",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@platforma-sdk/workflow-tengo": "5.8.
|
|
7
|
+
"@platforma-sdk/workflow-tengo": "5.8.2",
|
|
8
8
|
"@platforma-open/milaboratories.software-anarci": "^0.0.3",
|
|
9
|
-
"@platforma-open/milaboratories.top-antibodies.sample-clonotypes": "1.9.
|
|
9
|
+
"@platforma-open/milaboratories.top-antibodies.sample-clonotypes": "1.9.3",
|
|
10
10
|
"@platforma-open/milaboratories.top-antibodies.spectratype": "1.8.1",
|
|
11
11
|
"@platforma-open/milaboratories.top-antibodies.assembling-fasta": "1.3.0",
|
|
12
|
-
"@platforma-open/milaboratories.top-antibodies.
|
|
13
|
-
"@platforma-open/milaboratories.top-antibodies.
|
|
12
|
+
"@platforma-open/milaboratories.top-antibodies.anarci-kabat": "1.3.0",
|
|
13
|
+
"@platforma-open/milaboratories.top-antibodies.umap": "1.2.1"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@platforma-sdk/tengo-builder": "2.4.
|
|
16
|
+
"@platforma-sdk/tengo-builder": "2.4.18"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "shx rm -rf dist && pl-tengo check && pl-tengo build",
|
|
@@ -4,6 +4,7 @@ exec := import("@platforma-sdk/workflow-tengo:exec")
|
|
|
4
4
|
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
5
5
|
pframes := import("@platforma-sdk/workflow-tengo:pframes")
|
|
6
6
|
xsv := import("@platforma-sdk/workflow-tengo:pframes.xsv")
|
|
7
|
+
pSpec := import("@platforma-sdk/workflow-tengo:pframes.spec")
|
|
7
8
|
render := import("@platforma-sdk/workflow-tengo:render")
|
|
8
9
|
sampledColsConv := import(":sampled-cols-conv")
|
|
9
10
|
sampledExportConv := import(":sampled-export-conv")
|
|
@@ -93,7 +94,21 @@ self.body(func(inputs) {
|
|
|
93
94
|
rankingMap, inputs.disableClusterRanking, inputs.rawClusterColumn, topClonotypes)
|
|
94
95
|
sampledColumnsOnlyPf := xsv.importFile(finalClonotypes, "parquet", sampledExportsParams,
|
|
95
96
|
{cpu: 1, mem: "16GiB"})
|
|
96
|
-
|
|
97
|
+
|
|
98
|
+
// Create trace with filter descriptions and inject into exported column
|
|
99
|
+
traceLabel := inputs.filterTraceLabel
|
|
100
|
+
if is_undefined(traceLabel) || traceLabel == "" {
|
|
101
|
+
traceLabel = "Selected Leads"
|
|
102
|
+
}
|
|
103
|
+
trace := pSpec.makeTrace(datasetSpec,
|
|
104
|
+
{
|
|
105
|
+
type: "milaboratories.antibody-tcr-lead-selection",
|
|
106
|
+
importance: 30,
|
|
107
|
+
label: traceLabel
|
|
108
|
+
})
|
|
109
|
+
exportPf := pframes.pFrameBuilder()
|
|
110
|
+
exportPf.add("link", trace.inject(sampledColumnsOnlyPf["link.spec"]), sampledColumnsOnlyPf["link.data"])
|
|
111
|
+
outputs["sampledColumnsExport"] = exportPf.build()
|
|
97
112
|
|
|
98
113
|
return outputs
|
|
99
114
|
})
|
package/src/main.tpl.tengo
CHANGED
|
@@ -6,6 +6,7 @@ xsv := import("@platforma-sdk/workflow-tengo:pframes.xsv")
|
|
|
6
6
|
pframes := import("@platforma-sdk/workflow-tengo:pframes")
|
|
7
7
|
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
8
8
|
render := import("@platforma-sdk/workflow-tengo:render")
|
|
9
|
+
pSpec := import("@platforma-sdk/workflow-tengo:pframes.spec")
|
|
9
10
|
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
10
11
|
kabatConv := import(":pf-kabat-conv")
|
|
11
12
|
|
|
@@ -132,10 +133,13 @@ wf.body(func(args) {
|
|
|
132
133
|
addedCols := tableInit.addedCols
|
|
133
134
|
|
|
134
135
|
// Continue only if we have at least a column
|
|
135
|
-
// This condition prevents temporal intermittent error while filters are
|
|
136
|
+
// This condition prevents temporal intermittent error while filters are
|
|
136
137
|
// being processed and possibly in other situations too
|
|
137
138
|
if addedCols {
|
|
138
139
|
|
|
140
|
+
// Build trace label from filter descriptions
|
|
141
|
+
filterTraceLabel := utils.buildFilterTraceLabel(args.filters, columns)
|
|
142
|
+
|
|
139
143
|
// Use ender.create to call the filter-clonotypes template
|
|
140
144
|
filterSampleResult := render.create(filterAndSampleTpl, {
|
|
141
145
|
inputAnchor: args.inputAnchor,
|
|
@@ -148,9 +152,10 @@ wf.body(func(args) {
|
|
|
148
152
|
topClonotypes: args.topClonotypes,
|
|
149
153
|
disableClusterRanking: args.disableClusterRanking,
|
|
150
154
|
clusterColumn: clusterColumnHeader,
|
|
151
|
-
rawClusterColumn: args.clusterColumn
|
|
155
|
+
rawClusterColumn: args.clusterColumn,
|
|
156
|
+
filterTraceLabel: filterTraceLabel
|
|
152
157
|
})
|
|
153
|
-
|
|
158
|
+
|
|
154
159
|
// Get the filtered clonotypes from the template result
|
|
155
160
|
outputs["sampledRows"] = filterSampleResult.output("sampledRows", 24 * 60 * 60 * 1000)
|
|
156
161
|
|
|
@@ -6,13 +6,14 @@ getColumns := func(datasetSpec, addRanking) {
|
|
|
6
6
|
id: "link",
|
|
7
7
|
allowNA: false,
|
|
8
8
|
spec: {
|
|
9
|
-
name: "pl7.app/vdj/
|
|
9
|
+
name: "pl7.app/vdj/lead-selection",
|
|
10
10
|
valueType: "Int",
|
|
11
11
|
domain: {},
|
|
12
12
|
annotations: {
|
|
13
|
-
"pl7.app/label": "
|
|
13
|
+
"pl7.app/label": "Selected Leads",
|
|
14
14
|
"pl7.app/table/visibility": "hidden",
|
|
15
|
-
"pl7.app/isSubset": "true"
|
|
15
|
+
"pl7.app/isSubset": "true",
|
|
16
|
+
"pl7.app/toPlot": "true"
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
}]
|
package/src/utils.lib.tengo
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Utility functions for antibody-tcr-lead-selection workflow
|
|
2
2
|
|
|
3
3
|
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
4
|
+
json := import("json")
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Checks if two clusterId axes have matching domains.
|
|
@@ -545,6 +546,89 @@ initializeAssemSeqTable := func(pframes, columns, datasetSpec, isSingleCell) {
|
|
|
545
546
|
}
|
|
546
547
|
}
|
|
547
548
|
|
|
549
|
+
// Maps filter type to short operator symbol for trace labels.
|
|
550
|
+
filterOperatorMap := {
|
|
551
|
+
"number_greaterThan": ">",
|
|
552
|
+
"number_greaterThanOrEqualTo": ">=",
|
|
553
|
+
"number_lessThan": "<",
|
|
554
|
+
"number_lessThanOrEqualTo": "<=",
|
|
555
|
+
"number_equals": "=",
|
|
556
|
+
"number_notEquals": "!=",
|
|
557
|
+
"string_equals": "=",
|
|
558
|
+
"string_notEquals": "!=",
|
|
559
|
+
"string_contains": "contains",
|
|
560
|
+
"string_doesNotContain": "not contains",
|
|
561
|
+
"string_in": "in",
|
|
562
|
+
"string_notIn": "not in"
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Formats a single filter as a short description for trace labels.
|
|
567
|
+
* e.g. "Min quality FR1 > 0", "Productive = true", "Chain in Heavy, Light"
|
|
568
|
+
*
|
|
569
|
+
* @param columnLabel - Human-readable column name
|
|
570
|
+
* @param filter - Filter object with type and reference fields
|
|
571
|
+
* @return Formatted filter description string
|
|
572
|
+
*/
|
|
573
|
+
formatFilterDescription := func(columnLabel, filter) {
|
|
574
|
+
if is_undefined(filter) || is_undefined(filter.type) {
|
|
575
|
+
return columnLabel
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Return filter.type if short operator is not found
|
|
579
|
+
op := filterOperatorMap[filter.type]
|
|
580
|
+
if is_undefined(op) {
|
|
581
|
+
op = filter.type
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
ref := filter.reference
|
|
585
|
+
// In multiple select filters, parse JSON array and join values
|
|
586
|
+
if filter.type == "string_in" || filter.type == "string_notIn" {
|
|
587
|
+
values := json.decode(string(ref))
|
|
588
|
+
valStr := "["
|
|
589
|
+
for i, v in values {
|
|
590
|
+
if i > 0 {
|
|
591
|
+
valStr = valStr + ", "
|
|
592
|
+
}
|
|
593
|
+
valStr = valStr + string(v)
|
|
594
|
+
}
|
|
595
|
+
ref = valStr + "]"
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return columnLabel + " " + op + " " + string(ref)
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Builds a comma-separated filter description string for use in trace labels.
|
|
603
|
+
* e.g. "Min quality FR1 > 0, Productive = true, Chain in Heavy, Light"
|
|
604
|
+
*
|
|
605
|
+
* @param filters - Array of filter objects from block args
|
|
606
|
+
* @param columns - PBundle to look up column specs for labels
|
|
607
|
+
* @return Filter description string, or empty string if no valid filters
|
|
608
|
+
*/
|
|
609
|
+
buildFilterTraceLabel := func(filters, columns) {
|
|
610
|
+
result := ""
|
|
611
|
+
count := 0
|
|
612
|
+
for filter in filters {
|
|
613
|
+
if !is_undefined(filter.value) {
|
|
614
|
+
colSpec := columns.getSpec(filter.value.column)
|
|
615
|
+
if !is_undefined(colSpec) {
|
|
616
|
+
colLabel := colSpec.annotations["pl7.app/label"]
|
|
617
|
+
if is_undefined(colLabel) {
|
|
618
|
+
colLabel = colSpec.name
|
|
619
|
+
}
|
|
620
|
+
desc := formatFilterDescription(colLabel, filter.filter)
|
|
621
|
+
if count > 0 {
|
|
622
|
+
result = result + ", "
|
|
623
|
+
}
|
|
624
|
+
result = result + desc
|
|
625
|
+
count = count + 1
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return result
|
|
630
|
+
}
|
|
631
|
+
|
|
548
632
|
export {
|
|
549
633
|
clusterAxisDomainsMatch: clusterAxisDomainsMatch,
|
|
550
634
|
findMatchingLinkerIndex: findMatchingLinkerIndex,
|
|
@@ -555,5 +639,7 @@ export {
|
|
|
555
639
|
makeHeaderName: makeHeaderName,
|
|
556
640
|
initializeCdr3SeqTable: initializeCdr3SeqTable,
|
|
557
641
|
detectBulkChain: detectBulkChain,
|
|
558
|
-
initializeAssemSeqTable: initializeAssemSeqTable
|
|
642
|
+
initializeAssemSeqTable: initializeAssemSeqTable,
|
|
643
|
+
formatFilterDescription: formatFilterDescription,
|
|
644
|
+
buildFilterTraceLabel: buildFilterTraceLabel
|
|
559
645
|
}
|