@platforma-open/milaboratories.mixcr-clonotyping-2.workflow 2.24.0 → 2.26.0
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 +12 -0
- package/dist/tengo/lib/calculate-export-specs.lib.tengo +126 -36
- package/dist/tengo/tpl/aggregate-by-clonotype-key.plj.gz +0 -0
- package/dist/tengo/tpl/calculate-preset-info.plj.gz +0 -0
- package/dist/tengo/tpl/list-presets.plj.gz +0 -0
- package/dist/tengo/tpl/main.plj.gz +0 -0
- package/dist/tengo/tpl/mixcr-analyze.plj.gz +0 -0
- package/dist/tengo/tpl/mixcr-export.plj.gz +0 -0
- package/dist/tengo/tpl/prerun.plj.gz +0 -0
- package/dist/tengo/tpl/process-single-cell.plj.gz +0 -0
- package/dist/tengo/tpl/process.plj.gz +0 -0
- package/dist/tengo/tpl/test.columns-calculate.plj.gz +0 -0
- package/dist/tengo/tpl/test.columns.test.plj.gz +0 -0
- package/package.json +4 -4
- package/src/aggregate-by-clonotype-key.tpl.tengo +9 -1
- package/src/calculate-export-specs.lib.tengo +126 -36
- package/src/mixcr-export.tpl.tengo +7 -2
- package/src/process-single-cell.tpl.tengo +12 -2
- package/src/process.tpl.tengo +30 -24
- package/src/test/columns-calculate.tpl.tengo +7 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/work/mixcr-clonotyping/mixcr-clonotyping/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.
|
|
3
|
+
> @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.26.0 build /home/runner/work/mixcr-clonotyping/mixcr-clonotyping/workflow
|
|
4
4
|
> rm -rf dist && pl-tengo check && pl-tengo build
|
|
5
5
|
|
|
6
6
|
info: Skipping unknown file type: test/columns.test.ts
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @platforma-open/milaboratories.mixcr-clonotyping.workflow
|
|
2
2
|
|
|
3
|
+
## 2.26.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4d7746d: Cell Linker Column & SDK Upgrade
|
|
8
|
+
|
|
9
|
+
## 2.25.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 427ffa6: Include junction lengths and total number of added nt
|
|
14
|
+
|
|
3
15
|
## 2.24.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -116,7 +116,7 @@ addSpec := func(columns, additionalSpec) {
|
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
119
|
+
calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
|
|
120
120
|
ops := exportSpecOpsFromPreset(presetSpecForBack)
|
|
121
121
|
|
|
122
122
|
assemblingFeature := ops.assemblingFeature
|
|
@@ -125,6 +125,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
125
125
|
splitByC := ops.splitByC
|
|
126
126
|
|
|
127
127
|
isSingleCell := !is_undefined(cellTags) && len(cellTags) > 0
|
|
128
|
+
hashCellKey := isSingleCell && len(cellTags) == 1
|
|
128
129
|
|
|
129
130
|
assemblingFeatureInfo := assemblingFeatureInfo(assemblingFeature)
|
|
130
131
|
productiveFeature := assemblingFeatureInfo.productiveFeature
|
|
@@ -541,6 +542,52 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
541
542
|
}
|
|
542
543
|
|
|
543
544
|
|
|
545
|
+
junctionTypes := [ "VJ", "VD", "DJ" ]
|
|
546
|
+
for junctionType in junctionTypes {
|
|
547
|
+
feature := junctionType + "Junction"
|
|
548
|
+
naRegex := junctionType == "VJ" ? "region_not_covered" : "no_d_gene"
|
|
549
|
+
|
|
550
|
+
columnsSpecPerClonotypeNoAggregates += [ {
|
|
551
|
+
column: "nLength" + feature,
|
|
552
|
+
id: "n-length-" + text.to_lower(junctionType) + "-junction",
|
|
553
|
+
naRegex: naRegex,
|
|
554
|
+
allowNA: true,
|
|
555
|
+
spec: {
|
|
556
|
+
name: "pl7.app/vdj/sequenceLength",
|
|
557
|
+
valueType: "Int",
|
|
558
|
+
domain: {
|
|
559
|
+
"pl7.app/vdj/feature": feature,
|
|
560
|
+
"pl7.app/alphabet": "nucleotide"
|
|
561
|
+
},
|
|
562
|
+
annotations: a(orderP, false, {
|
|
563
|
+
"pl7.app/label": "Length of " + junctionType + " Junction nt"
|
|
564
|
+
})
|
|
565
|
+
}
|
|
566
|
+
} ]
|
|
567
|
+
exportArgs += [ [ "-nLength", feature ] ]
|
|
568
|
+
orderP -= 100
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
columnsSpecPerClonotypeNoAggregates += [ {
|
|
573
|
+
column: "nLengthTotalAdded",
|
|
574
|
+
id: "n-length-total-added",
|
|
575
|
+
naRegex: "region_not_covered|no_d_gene",
|
|
576
|
+
allowNA: true,
|
|
577
|
+
spec: {
|
|
578
|
+
name: "pl7.app/vdj/sequenceLength",
|
|
579
|
+
valueType: "Int",
|
|
580
|
+
domain: {
|
|
581
|
+
"pl7.app/alphabet": "nucleotide"
|
|
582
|
+
},
|
|
583
|
+
annotations: a(orderP, false, {
|
|
584
|
+
"pl7.app/label": "Total number of added nt"
|
|
585
|
+
})
|
|
586
|
+
}
|
|
587
|
+
} ]
|
|
588
|
+
orderP -= 100
|
|
589
|
+
|
|
590
|
+
|
|
544
591
|
|
|
545
592
|
geneHitColumnVariants := [ {
|
|
546
593
|
name: "pl7.app/vdj/geneHitWithAllele",
|
|
@@ -765,9 +812,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
765
812
|
|
|
766
813
|
|
|
767
814
|
|
|
768
|
-
|
|
769
|
-
|
|
815
|
+
axisByClonotypeKeyGen := undefined
|
|
816
|
+
axisByScClonotypeKeyGen := undefined
|
|
770
817
|
cellTagColumns := undefined
|
|
818
|
+
cellLinkerColumnSettingsGen := undefined
|
|
771
819
|
|
|
772
820
|
if !is_undefined(clonotypeKeyColumns) {
|
|
773
821
|
|
|
@@ -785,39 +833,16 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
785
833
|
|
|
786
834
|
|
|
787
835
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
spec: {
|
|
792
|
-
name: "pl7.app/vdj/clonotypeKey",
|
|
793
|
-
type: "String",
|
|
794
|
-
domain: {
|
|
795
|
-
"pl7.app/vdj/clonotypeKey/structure": string(json.encode(keyStrincture)),
|
|
796
|
-
"pl7.app/vdj/clonotypingRunId": blockId
|
|
797
|
-
},
|
|
798
|
-
annotations: {
|
|
799
|
-
"pl7.app/label": "Clonotype ID",
|
|
800
|
-
"pl7.app/table/fontFamily": "monospace",
|
|
801
|
-
"pl7.app/table/visibility": "default",
|
|
802
|
-
"pl7.app/table/orderPriority": "110000",
|
|
803
|
-
"pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
} ]
|
|
807
|
-
|
|
808
|
-
if isSingleCell {
|
|
809
|
-
cellTagColumns = slices.map(cellTags, func(cellTag) {
|
|
810
|
-
return "tagValue" + cellTag
|
|
811
|
-
})
|
|
812
|
-
|
|
813
|
-
axesByScClonotypeKey = [ {
|
|
814
|
-
column: "scClonotypeKey",
|
|
836
|
+
axisByClonotypeKeyGen = func(chain) {
|
|
837
|
+
return {
|
|
838
|
+
column: "clonotypeKey",
|
|
815
839
|
naRegex: "",
|
|
816
840
|
spec: {
|
|
817
|
-
name: "pl7.app/vdj/
|
|
841
|
+
name: "pl7.app/vdj/clonotypeKey",
|
|
818
842
|
type: "String",
|
|
819
843
|
domain: {
|
|
820
|
-
"pl7.app/vdj/
|
|
844
|
+
"pl7.app/vdj/chain": chain,
|
|
845
|
+
"pl7.app/vdj/clonotypeKey/structure": string(json.encode(keyStrincture)),
|
|
821
846
|
"pl7.app/vdj/clonotypingRunId": blockId
|
|
822
847
|
},
|
|
823
848
|
annotations: {
|
|
@@ -828,7 +853,69 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
828
853
|
"pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
|
|
829
854
|
}
|
|
830
855
|
}
|
|
831
|
-
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if isSingleCell {
|
|
860
|
+
cellTagColumns = slices.map(cellTags, func(cellTag) {
|
|
861
|
+
return "tagValue" + cellTag
|
|
862
|
+
})
|
|
863
|
+
|
|
864
|
+
axisByScClonotypeKeyGen = func(receptor) {
|
|
865
|
+
return {
|
|
866
|
+
column: "scClonotypeKey",
|
|
867
|
+
naRegex: "",
|
|
868
|
+
spec: {
|
|
869
|
+
name: "pl7.app/vdj/scClonotypeKey",
|
|
870
|
+
type: "String",
|
|
871
|
+
domain: {
|
|
872
|
+
"pl7.app/vdj/receptor": receptor,
|
|
873
|
+
"pl7.app/vdj/scClonotypeKey/structure": string(json.encode(keyStrincture)),
|
|
874
|
+
"pl7.app/vdj/clonotypingRunId": blockId
|
|
875
|
+
},
|
|
876
|
+
annotations: {
|
|
877
|
+
"pl7.app/label": "Clonotype ID",
|
|
878
|
+
"pl7.app/table/fontFamily": "monospace",
|
|
879
|
+
"pl7.app/table/visibility": "default",
|
|
880
|
+
"pl7.app/table/orderPriority": "110000",
|
|
881
|
+
"pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
cellLinkerColumnSettingsGen = func(receptor) {
|
|
888
|
+
return {
|
|
889
|
+
axes: [ {
|
|
890
|
+
column: "sampleId",
|
|
891
|
+
spec: sampleIdAxisSpec
|
|
892
|
+
}, {
|
|
893
|
+
column: "cellKey",
|
|
894
|
+
spec: {
|
|
895
|
+
name: "pl7.app/sc/cellId",
|
|
896
|
+
type: "String",
|
|
897
|
+
annotations: a(110000, true, {
|
|
898
|
+
"pl7.app/label": "Cell ID",
|
|
899
|
+
"pl7.app/table/fontFamily": "monospace",
|
|
900
|
+
"pl7.app/parents": string(json.encode([sampleIdAxisSpec.name]))
|
|
901
|
+
})
|
|
902
|
+
}
|
|
903
|
+
}, axisByScClonotypeKeyGen(receptor) ],
|
|
904
|
+
columns: [ {
|
|
905
|
+
column: "1",
|
|
906
|
+
spec: {
|
|
907
|
+
name: "pl7.app/sc/cellLinker",
|
|
908
|
+
valueType: "Int",
|
|
909
|
+
annotations: a(0, undefined, {
|
|
910
|
+
"pl7.app/label": "Cell Linker",
|
|
911
|
+
"pl7.app/isLinkerColumn": "true"
|
|
912
|
+
})
|
|
913
|
+
}
|
|
914
|
+
} ],
|
|
915
|
+
storageFormat: "Binary",
|
|
916
|
+
partitionKeyLength: 1
|
|
917
|
+
}
|
|
918
|
+
}
|
|
832
919
|
|
|
833
920
|
|
|
834
921
|
|
|
@@ -851,8 +938,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
851
938
|
|
|
852
939
|
cellTagColumns: cellTagColumns,
|
|
853
940
|
|
|
854
|
-
|
|
855
|
-
|
|
941
|
+
axisByClonotypeKeyGen: axisByClonotypeKeyGen,
|
|
942
|
+
axisByScClonotypeKeyGen: axisByScClonotypeKeyGen,
|
|
856
943
|
|
|
857
944
|
columnsSpecPerSample: columnsSpecPerSample,
|
|
858
945
|
columnsSpecPerSampleSc: columnsSpecPerSampleSc,
|
|
@@ -870,7 +957,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
870
957
|
mainIsProductiveColumn: mainIsProductiveColumn,
|
|
871
958
|
mainIsProductiveArgs: mainIsProductiveArgs,
|
|
872
959
|
|
|
873
|
-
exportArgs: exportArgs
|
|
960
|
+
exportArgs: exportArgs,
|
|
961
|
+
|
|
962
|
+
hashCellKey: hashCellKey,
|
|
963
|
+
cellLinkerColumnSettingsGen: cellLinkerColumnSettingsGen
|
|
874
964
|
}
|
|
875
965
|
}
|
|
876
966
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-open/milaboratories.mixcr-clonotyping-2.workflow",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.26.0",
|
|
4
4
|
"description": "Tengo-based template",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@platforma-sdk/workflow-tengo": "^4.
|
|
6
|
+
"@platforma-sdk/workflow-tengo": "^4.14.0",
|
|
7
7
|
"@platforma-open/milaboratories.software-mixcr": "4.7.0-190-develop"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@platforma-sdk/tengo-builder": "^2.1.
|
|
11
|
-
"@platforma-sdk/test": "^1.
|
|
10
|
+
"@platforma-sdk/tengo-builder": "^2.1.13",
|
|
11
|
+
"@platforma-sdk/test": "^1.41.16",
|
|
12
12
|
"vitest": "~2.1.9",
|
|
13
13
|
"typescript": "~5.5.4"
|
|
14
14
|
},
|
|
@@ -75,7 +75,7 @@ self.body(func(inputs) {
|
|
|
75
75
|
aggExpressions := []
|
|
76
76
|
|
|
77
77
|
for colDef in schemaPerClonotypeNoAggregates {
|
|
78
|
-
if colDef.column == "clonotypeLabel" {
|
|
78
|
+
if colDef.column == "clonotypeLabel" || colDef.column == "nLengthTotalAdded" {
|
|
79
79
|
continue
|
|
80
80
|
}
|
|
81
81
|
aggExpressions = append(aggExpressions,
|
|
@@ -91,6 +91,14 @@ self.body(func(inputs) {
|
|
|
91
91
|
|
|
92
92
|
aggregatedDf := currentDf.groupBy("clonotypeKey").agg(aggExpressions...)
|
|
93
93
|
|
|
94
|
+
// Calculate total added nucleotides: VDJunction + DJJunction for chains with D genes, VJJunction for chains without D genes
|
|
95
|
+
aggregatedDf = aggregatedDf.withColumns(
|
|
96
|
+
pt.when(pt.col("nLengthVDJunction").isNotNull().and(pt.col("nLengthVDJunction").neq("no_d_gene"))).
|
|
97
|
+
then(pt.col("nLengthVDJunction").cast("Int").plus(pt.col("nLengthDJJunction").cast("Int"))).
|
|
98
|
+
otherwise(pt.col("nLengthVJJunction").cast("Int")).
|
|
99
|
+
alias("nLengthTotalAdded")
|
|
100
|
+
)
|
|
101
|
+
|
|
94
102
|
aggregatedDf = clonotypeLabel.addClonotypeLabelColumnsPt(aggregatedDf, "clonotypeKey", "clonotypeLabel", pt)
|
|
95
103
|
|
|
96
104
|
aggregatedDf.save("output.tsv")
|
|
@@ -116,7 +116,7 @@ addSpec := func(columns, additionalSpec) {
|
|
|
116
116
|
// Ordering rules
|
|
117
117
|
// AA Sequences
|
|
118
118
|
|
|
119
|
-
calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
119
|
+
calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
|
|
120
120
|
ops := exportSpecOpsFromPreset(presetSpecForBack)
|
|
121
121
|
|
|
122
122
|
assemblingFeature := ops.assemblingFeature
|
|
@@ -125,6 +125,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
125
125
|
splitByC := ops.splitByC
|
|
126
126
|
|
|
127
127
|
isSingleCell := !is_undefined(cellTags) && len(cellTags) > 0
|
|
128
|
+
hashCellKey := isSingleCell && len(cellTags) == 1
|
|
128
129
|
|
|
129
130
|
assemblingFeatureInfo := assemblingFeatureInfo(assemblingFeature)
|
|
130
131
|
productiveFeature := assemblingFeatureInfo.productiveFeature
|
|
@@ -540,6 +541,52 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
540
541
|
}
|
|
541
542
|
}
|
|
542
543
|
|
|
544
|
+
// Include junction lengths for calculation of total added nucleotides
|
|
545
|
+
junctionTypes := [ "VJ", "VD", "DJ" ]
|
|
546
|
+
for junctionType in junctionTypes {
|
|
547
|
+
feature := junctionType + "Junction"
|
|
548
|
+
naRegex := junctionType == "VJ" ? "region_not_covered" : "no_d_gene"
|
|
549
|
+
|
|
550
|
+
columnsSpecPerClonotypeNoAggregates += [ {
|
|
551
|
+
column: "nLength" + feature,
|
|
552
|
+
id: "n-length-" + text.to_lower(junctionType) + "-junction",
|
|
553
|
+
naRegex: naRegex,
|
|
554
|
+
allowNA: true,
|
|
555
|
+
spec: {
|
|
556
|
+
name: "pl7.app/vdj/sequenceLength",
|
|
557
|
+
valueType: "Int",
|
|
558
|
+
domain: {
|
|
559
|
+
"pl7.app/vdj/feature": feature,
|
|
560
|
+
"pl7.app/alphabet": "nucleotide"
|
|
561
|
+
},
|
|
562
|
+
annotations: a(orderP, false, {
|
|
563
|
+
"pl7.app/label": "Length of " + junctionType + " Junction nt"
|
|
564
|
+
})
|
|
565
|
+
}
|
|
566
|
+
} ]
|
|
567
|
+
exportArgs += [ [ "-nLength", feature ] ]
|
|
568
|
+
orderP -= 100
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Spec for total added length (calculated by pt in aggregate-by-clonotype-key, no flag)
|
|
572
|
+
columnsSpecPerClonotypeNoAggregates += [ {
|
|
573
|
+
column: "nLengthTotalAdded",
|
|
574
|
+
id: "n-length-total-added",
|
|
575
|
+
naRegex: "region_not_covered|no_d_gene",
|
|
576
|
+
allowNA: true,
|
|
577
|
+
spec: {
|
|
578
|
+
name: "pl7.app/vdj/sequenceLength",
|
|
579
|
+
valueType: "Int",
|
|
580
|
+
domain: {
|
|
581
|
+
"pl7.app/alphabet": "nucleotide"
|
|
582
|
+
},
|
|
583
|
+
annotations: a(orderP, false, {
|
|
584
|
+
"pl7.app/label": "Total number of added nt"
|
|
585
|
+
})
|
|
586
|
+
}
|
|
587
|
+
} ]
|
|
588
|
+
orderP -= 100
|
|
589
|
+
|
|
543
590
|
// VDJC Hits
|
|
544
591
|
|
|
545
592
|
geneHitColumnVariants := [ {
|
|
@@ -765,9 +812,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
765
812
|
|
|
766
813
|
// Axes
|
|
767
814
|
|
|
768
|
-
|
|
769
|
-
|
|
815
|
+
axisByClonotypeKeyGen := undefined
|
|
816
|
+
axisByScClonotypeKeyGen := undefined
|
|
770
817
|
cellTagColumns := undefined
|
|
818
|
+
cellLinkerColumnSettingsGen := undefined
|
|
771
819
|
|
|
772
820
|
if !is_undefined(clonotypeKeyColumns) {
|
|
773
821
|
// checking that corresponding columns exist in export
|
|
@@ -785,39 +833,16 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
785
833
|
// Its absence indicates that merging would be semantically meaningless (e.g., abundance
|
|
786
834
|
// measurements specific to each analysis)
|
|
787
835
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
spec: {
|
|
792
|
-
name: "pl7.app/vdj/clonotypeKey",
|
|
793
|
-
type: "String",
|
|
794
|
-
domain: {
|
|
795
|
-
"pl7.app/vdj/clonotypeKey/structure": string(json.encode(keyStrincture)),
|
|
796
|
-
"pl7.app/vdj/clonotypingRunId": blockId
|
|
797
|
-
},
|
|
798
|
-
annotations: {
|
|
799
|
-
"pl7.app/label": "Clonotype ID",
|
|
800
|
-
"pl7.app/table/fontFamily": "monospace",
|
|
801
|
-
"pl7.app/table/visibility": "default",
|
|
802
|
-
"pl7.app/table/orderPriority": "110000",
|
|
803
|
-
"pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
} ]
|
|
807
|
-
|
|
808
|
-
if isSingleCell {
|
|
809
|
-
cellTagColumns = slices.map(cellTags, func(cellTag) {
|
|
810
|
-
return "tagValue" + cellTag
|
|
811
|
-
})
|
|
812
|
-
|
|
813
|
-
axesByScClonotypeKey = [ {
|
|
814
|
-
column: "scClonotypeKey",
|
|
836
|
+
axisByClonotypeKeyGen = func(chain) {
|
|
837
|
+
return {
|
|
838
|
+
column: "clonotypeKey",
|
|
815
839
|
naRegex: "",
|
|
816
840
|
spec: {
|
|
817
|
-
name: "pl7.app/vdj/
|
|
841
|
+
name: "pl7.app/vdj/clonotypeKey",
|
|
818
842
|
type: "String",
|
|
819
843
|
domain: {
|
|
820
|
-
"pl7.app/vdj/
|
|
844
|
+
"pl7.app/vdj/chain": chain,
|
|
845
|
+
"pl7.app/vdj/clonotypeKey/structure": string(json.encode(keyStrincture)),
|
|
821
846
|
"pl7.app/vdj/clonotypingRunId": blockId
|
|
822
847
|
},
|
|
823
848
|
annotations: {
|
|
@@ -828,7 +853,69 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
828
853
|
"pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
|
|
829
854
|
}
|
|
830
855
|
}
|
|
831
|
-
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if isSingleCell {
|
|
860
|
+
cellTagColumns = slices.map(cellTags, func(cellTag) {
|
|
861
|
+
return "tagValue" + cellTag
|
|
862
|
+
})
|
|
863
|
+
|
|
864
|
+
axisByScClonotypeKeyGen = func(receptor) {
|
|
865
|
+
return {
|
|
866
|
+
column: "scClonotypeKey",
|
|
867
|
+
naRegex: "",
|
|
868
|
+
spec: {
|
|
869
|
+
name: "pl7.app/vdj/scClonotypeKey",
|
|
870
|
+
type: "String",
|
|
871
|
+
domain: {
|
|
872
|
+
"pl7.app/vdj/receptor": receptor,
|
|
873
|
+
"pl7.app/vdj/scClonotypeKey/structure": string(json.encode(keyStrincture)),
|
|
874
|
+
"pl7.app/vdj/clonotypingRunId": blockId
|
|
875
|
+
},
|
|
876
|
+
annotations: {
|
|
877
|
+
"pl7.app/label": "Clonotype ID",
|
|
878
|
+
"pl7.app/table/fontFamily": "monospace",
|
|
879
|
+
"pl7.app/table/visibility": "default",
|
|
880
|
+
"pl7.app/table/orderPriority": "110000",
|
|
881
|
+
"pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
cellLinkerColumnSettingsGen = func(receptor) {
|
|
888
|
+
return {
|
|
889
|
+
axes: [ {
|
|
890
|
+
column: "sampleId",
|
|
891
|
+
spec: sampleIdAxisSpec
|
|
892
|
+
}, {
|
|
893
|
+
column: "cellKey",
|
|
894
|
+
spec: {
|
|
895
|
+
name: "pl7.app/sc/cellId",
|
|
896
|
+
type: "String",
|
|
897
|
+
annotations: a(110000, true, {
|
|
898
|
+
"pl7.app/label": "Cell ID",
|
|
899
|
+
"pl7.app/table/fontFamily": "monospace",
|
|
900
|
+
"pl7.app/parents": string(json.encode([sampleIdAxisSpec.name]))
|
|
901
|
+
})
|
|
902
|
+
}
|
|
903
|
+
}, axisByScClonotypeKeyGen(receptor) ],
|
|
904
|
+
columns: [ {
|
|
905
|
+
column: "1",
|
|
906
|
+
spec: {
|
|
907
|
+
name: "pl7.app/sc/cellLinker",
|
|
908
|
+
valueType: "Int",
|
|
909
|
+
annotations: a(0, undefined, {
|
|
910
|
+
"pl7.app/label": "Cell Linker",
|
|
911
|
+
"pl7.app/isLinkerColumn": "true"
|
|
912
|
+
})
|
|
913
|
+
}
|
|
914
|
+
} ],
|
|
915
|
+
storageFormat: "Binary",
|
|
916
|
+
partitionKeyLength: 1
|
|
917
|
+
}
|
|
918
|
+
}
|
|
832
919
|
|
|
833
920
|
// exportArgs += [ [ "-tags", "Cell" ] ]
|
|
834
921
|
// axesByClonotypeKeyAndCellTag = axesByClonotypeKey + [ {
|
|
@@ -851,8 +938,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
851
938
|
|
|
852
939
|
cellTagColumns: cellTagColumns,
|
|
853
940
|
|
|
854
|
-
|
|
855
|
-
|
|
941
|
+
axisByClonotypeKeyGen: axisByClonotypeKeyGen,
|
|
942
|
+
axisByScClonotypeKeyGen: axisByScClonotypeKeyGen,
|
|
856
943
|
|
|
857
944
|
columnsSpecPerSample: columnsSpecPerSample,
|
|
858
945
|
columnsSpecPerSampleSc: columnsSpecPerSampleSc,
|
|
@@ -870,7 +957,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
|
|
|
870
957
|
mainIsProductiveColumn: mainIsProductiveColumn,
|
|
871
958
|
mainIsProductiveArgs: mainIsProductiveArgs,
|
|
872
959
|
|
|
873
|
-
exportArgs: exportArgs
|
|
960
|
+
exportArgs: exportArgs,
|
|
961
|
+
|
|
962
|
+
hashCellKey: hashCellKey,
|
|
963
|
+
cellLinkerColumnSettingsGen: cellLinkerColumnSettingsGen
|
|
874
964
|
}
|
|
875
965
|
}
|
|
876
966
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//tengo:hash_override
|
|
1
|
+
//tengo:hash_override E5C1AD4C-B44D-4DE1-BBF1-4CB42ED7579A
|
|
2
2
|
|
|
3
3
|
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
4
4
|
self := import("@platforma-sdk/workflow-tengo:tpl.light")
|
|
@@ -28,6 +28,11 @@ self.body(func(inputs) {
|
|
|
28
28
|
clonotypeKeyArgs := params.clonotypeKeyArgs
|
|
29
29
|
|
|
30
30
|
cellTagColumns := params.cellTagColumns
|
|
31
|
+
// if false cell key will not be hashed
|
|
32
|
+
hashCellKey := params.hashCellKey
|
|
33
|
+
if !hashCellKey && !is_undefined(cellTagColumns) {
|
|
34
|
+
ll.assert(len(cellTagColumns) == 1, "cellTagColumns must be a single column when hashCellKey is false")
|
|
35
|
+
}
|
|
31
36
|
|
|
32
37
|
mainAbundanceColumnUnnormalizedArgs := params.mainAbundanceColumnUnnormalizedArgs
|
|
33
38
|
mainIsProductiveArgs := params.mainIsProductiveArgs
|
|
@@ -144,7 +149,7 @@ self.body(func(inputs) {
|
|
|
144
149
|
|
|
145
150
|
dfSingleCell.addColumns(
|
|
146
151
|
hashKeyDerivationExpressionPt(clonotypeKeyColumns).alias("clonotypeKey"),
|
|
147
|
-
hashKeyDerivationExpressionPt(cellTagColumns).alias("cellKey")
|
|
152
|
+
hashCellKey ? hashKeyDerivationExpressionPt(cellTagColumns).alias("cellKey") : pt.col(cellTagColumns[0]).alias("cellKey")
|
|
148
153
|
)
|
|
149
154
|
|
|
150
155
|
dfSingleCell.save("output.tsv")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//tengo:hash_override
|
|
1
|
+
//tengo:hash_override AB9AC8BA-5FFC-40C5-B2F7-AC42181524F5
|
|
2
2
|
|
|
3
3
|
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
4
4
|
self := import("@platforma-sdk/workflow-tengo:tpl.light")
|
|
@@ -15,7 +15,9 @@ clonotypeLabel := import(":clonotype-label")
|
|
|
15
15
|
json := import("json")
|
|
16
16
|
math := import("math")
|
|
17
17
|
|
|
18
|
-
self.defineOutputs("abundanceTsv", "clonotypeTsv",
|
|
18
|
+
self.defineOutputs("abundanceTsv", "clonotypeTsv",
|
|
19
|
+
"propertiesAPrimaryTsv", "propertiesASecondaryTsv", "propertiesBPrimaryTsv", "propertiesBSecondaryTsv",
|
|
20
|
+
"cellsTsv")
|
|
19
21
|
|
|
20
22
|
ptablerSw := assets.importSoftware("@platforma-open/milaboratories.software-ptabler:main")
|
|
21
23
|
|
|
@@ -184,6 +186,10 @@ self.body(func(inputs) {
|
|
|
184
186
|
)
|
|
185
187
|
allChainsFilteredDf := allChainsMergedWithScKeyDf.filter(filterCondition)
|
|
186
188
|
|
|
189
|
+
allChainsFilteredDf.
|
|
190
|
+
withColumns(pt.lit(1).alias("1")).
|
|
191
|
+
save("cells.tsv", {columns: ["sampleId", "cellKey", "scClonotypeKey", "1"]})
|
|
192
|
+
|
|
187
193
|
clonotypeTableDf := allChainsFilteredDf.groupBy(
|
|
188
194
|
"scClonotypeKey", "clonotypeKeyA1", "clonotypeKeyA2", "clonotypeKeyB1", "clonotypeKeyB2"
|
|
189
195
|
).agg(
|
|
@@ -210,6 +216,7 @@ self.body(func(inputs) {
|
|
|
210
216
|
|
|
211
217
|
clonotypeTsv := cellGroupingRunResult.getFile("clonotype.tsv")
|
|
212
218
|
abundanceTsv := cellGroupingRunResult.getFile("abundance.tsv")
|
|
219
|
+
cellsTsv := cellGroupingRunResult.getFile("cells.tsv")
|
|
213
220
|
|
|
214
221
|
//
|
|
215
222
|
// Output processing - Reimplemented with PTabler pt API
|
|
@@ -303,6 +310,9 @@ self.body(func(inputs) {
|
|
|
303
310
|
// used for aggregates (i.e. sampleCount and clonotypeLabel)
|
|
304
311
|
clonotypeTsv: clonotypeTsv,
|
|
305
312
|
|
|
313
|
+
// used to build cell <-> clonotype linker column
|
|
314
|
+
cellsTsv: cellsTsv,
|
|
315
|
+
|
|
306
316
|
// must have scClonotypeKey columns
|
|
307
317
|
propertiesAPrimaryTsv: outputProcessingRunResult.getFile(chainMappings[0].finalOutFile),
|
|
308
318
|
propertiesASecondaryTsv: outputProcessingRunResult.getFile(chainMappings[1].finalOutFile),
|
package/src/process.tpl.tengo
CHANGED
|
@@ -71,6 +71,7 @@ self.body(func(inputs) {
|
|
|
71
71
|
presetCommonName := params.presetCommonName
|
|
72
72
|
isLibraryFileGzipped := params.isLibraryFileGzipped
|
|
73
73
|
|
|
74
|
+
sampleIdAxisSpec := inputSpec.axesSpec[0]
|
|
74
75
|
|
|
75
76
|
if is_undefined(presetSpecForBack) {
|
|
76
77
|
ll.panic("no presetSpecForBack")
|
|
@@ -201,7 +202,7 @@ self.body(func(inputs) {
|
|
|
201
202
|
}
|
|
202
203
|
} ]
|
|
203
204
|
|
|
204
|
-
exportSpecs := calculateExportSpecs(presetSpecForBack, blockId)
|
|
205
|
+
exportSpecs := calculateExportSpecs(presetSpecForBack, sampleIdAxisSpec, blockId)
|
|
205
206
|
|
|
206
207
|
columnsSpecPerSample := exportSpecs.columnsSpecPerSample
|
|
207
208
|
columnsSpecPerSampleSc := exportSpecs.columnsSpecPerSampleSc
|
|
@@ -214,8 +215,11 @@ self.body(func(inputs) {
|
|
|
214
215
|
cellTagColumns := exportSpecs.cellTagColumns
|
|
215
216
|
|
|
216
217
|
// axesByClonotypeId := exportSpecs.axesByClonotypeId
|
|
217
|
-
|
|
218
|
-
|
|
218
|
+
|
|
219
|
+
// function with chain argument
|
|
220
|
+
axisByClonotypeKeyGen := exportSpecs.axisByClonotypeKeyGen
|
|
221
|
+
// function with receptor argument
|
|
222
|
+
axisByScClonotypeKeyGen := exportSpecs.axisByScClonotypeKeyGen
|
|
219
223
|
|
|
220
224
|
exportArgs := exportSpecs.exportArgs
|
|
221
225
|
|
|
@@ -227,13 +231,9 @@ self.body(func(inputs) {
|
|
|
227
231
|
mainAbundanceColumnNormalizedArgs := exportSpecs.mainAbundanceColumnNormalizedArgs
|
|
228
232
|
mainAbundanceColumnUnnormalizedArgs := exportSpecs.mainAbundanceColumnUnnormalizedArgs
|
|
229
233
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if len(axesByClonotypeKey) != 1 || (!is_undefined(axesByScClonotypeKey) && len(axesByScClonotypeKey) != 1) {
|
|
235
|
-
ll.panic("Assertion error: expected exactly one clonotype key axis")
|
|
236
|
-
}
|
|
234
|
+
hashCellKey := exportSpecs.hashCellKey
|
|
235
|
+
// function with receptor argument
|
|
236
|
+
cellLinkerColumnSettingsGen := exportSpecs.cellLinkerColumnSettingsGen
|
|
237
237
|
|
|
238
238
|
mixcrResults := pframes.processColumn(
|
|
239
239
|
{ spec: inputSpec, data: inputs.inputData },
|
|
@@ -324,10 +324,6 @@ self.body(func(inputs) {
|
|
|
324
324
|
chainInfo := chainInfos[chain]
|
|
325
325
|
ll.assert(!is_undefined(chainInfo), "chainInfo not found for chain %v", chain)
|
|
326
326
|
|
|
327
|
-
axesByClonotypeKeyWithChain := [ maps.deepTransform(axesByClonotypeKey[0], {
|
|
328
|
-
spec: { domain: { "pl7.app/vdj/chain": chain } }
|
|
329
|
-
}) ]
|
|
330
|
-
|
|
331
327
|
//
|
|
332
328
|
// Exporting CLNS -> TSV
|
|
333
329
|
//
|
|
@@ -352,7 +348,7 @@ self.body(func(inputs) {
|
|
|
352
348
|
type: "Xsv",
|
|
353
349
|
xsvType: "tsv",
|
|
354
350
|
settings: {
|
|
355
|
-
axes:
|
|
351
|
+
axes: [ axisByClonotypeKeyGen(chain) ],
|
|
356
352
|
columns: columnsSpecPerSample,
|
|
357
353
|
storageFormat: "Binary",
|
|
358
354
|
partitionKeyLength: 0
|
|
@@ -407,6 +403,8 @@ self.body(func(inputs) {
|
|
|
407
403
|
mainAbundanceColumnUnnormalizedArgs: mainAbundanceColumnUnnormalizedArgs,
|
|
408
404
|
|
|
409
405
|
cellTagColumns: cellTagColumns,
|
|
406
|
+
hashCellKey: hashCellKey,
|
|
407
|
+
|
|
410
408
|
exportArgs: exportArgs,
|
|
411
409
|
isLibraryFileGzipped: isLibraryFileGzipped
|
|
412
410
|
},
|
|
@@ -441,7 +439,7 @@ self.body(func(inputs) {
|
|
|
441
439
|
type: "Xsv",
|
|
442
440
|
xsvType: "tsv",
|
|
443
441
|
settings: {
|
|
444
|
-
axes:
|
|
442
|
+
axes: [ axisByClonotypeKeyGen(chain) ],
|
|
445
443
|
columns: columnsSpecPerClonotypeNoAggregates + columnsSpecPerClonotypeAggregates,
|
|
446
444
|
storageFormat: "Binary",
|
|
447
445
|
partitionKeyLength: 0
|
|
@@ -502,10 +500,6 @@ self.body(func(inputs) {
|
|
|
502
500
|
for receptor in receptors {
|
|
503
501
|
receptorInfo := receptorInfos[receptor]
|
|
504
502
|
|
|
505
|
-
axesByScClonotypeKeyWithReceptor := [ maps.deepTransform(axesByScClonotypeKey[0], {
|
|
506
|
-
spec: { domain: { "pl7.app/vdj/receptor": receptor } }
|
|
507
|
-
}) ]
|
|
508
|
-
|
|
509
503
|
singleCellOutputs := [ {
|
|
510
504
|
type: "Resource",
|
|
511
505
|
spec: {
|
|
@@ -524,8 +518,8 @@ self.body(func(inputs) {
|
|
|
524
518
|
settings: {
|
|
525
519
|
axes: [ {
|
|
526
520
|
column: "sampleId",
|
|
527
|
-
spec:
|
|
528
|
-
} ]
|
|
521
|
+
spec: sampleIdAxisSpec
|
|
522
|
+
}, axisByScClonotypeKeyGen(receptor) ],
|
|
529
523
|
columns: columnsSpecPerSampleSc,
|
|
530
524
|
storageFormat: "Binary",
|
|
531
525
|
partitionKeyLength: 1
|
|
@@ -538,7 +532,7 @@ self.body(func(inputs) {
|
|
|
538
532
|
type: "Xsv",
|
|
539
533
|
xsvType: "tsv",
|
|
540
534
|
settings: {
|
|
541
|
-
axes:
|
|
535
|
+
axes: [ axisByScClonotypeKeyGen(receptor) ],
|
|
542
536
|
columns: columnsSpecPerClonotypeSc,
|
|
543
537
|
storageFormat: "Binary"
|
|
544
538
|
},
|
|
@@ -599,7 +593,7 @@ self.body(func(inputs) {
|
|
|
599
593
|
type: "Xsv",
|
|
600
594
|
xsvType: "tsv",
|
|
601
595
|
settings: {
|
|
602
|
-
axes:
|
|
596
|
+
axes: [ axisByScClonotypeKeyGen(receptor) ],
|
|
603
597
|
columns: transformSpecs(isPrimary ? columnsSpecPerClonotypeNoAggregates : columnsSpecPerClonotypeSecondary, {
|
|
604
598
|
spec: {
|
|
605
599
|
domain: {
|
|
@@ -620,6 +614,16 @@ self.body(func(inputs) {
|
|
|
620
614
|
}
|
|
621
615
|
}
|
|
622
616
|
|
|
617
|
+
singleCellOutputs += [ {
|
|
618
|
+
type: "Xsv",
|
|
619
|
+
xsvType: "tsv",
|
|
620
|
+
settings: cellLinkerColumnSettingsGen(receptor),
|
|
621
|
+
mem: "16GiB",
|
|
622
|
+
cpu: 2,
|
|
623
|
+
name: "cellsLinkerTable",
|
|
624
|
+
path: ["cellsTsv"]
|
|
625
|
+
} ]
|
|
626
|
+
|
|
623
627
|
chainA := receptorInfo.chains[0]
|
|
624
628
|
chainB := receptorInfo.chains[1]
|
|
625
629
|
|
|
@@ -669,6 +673,8 @@ self.body(func(inputs) {
|
|
|
669
673
|
singleCellResult.addXsvOutputToBuilder(clonotypes, "propertiesASecondary", "clonotypeProperties/" + receptor + "/aSecondary/")
|
|
670
674
|
singleCellResult.addXsvOutputToBuilder(clonotypes, "propertiesBPrimary", "clonotypeProperties/" + receptor + "/bPrimary/")
|
|
671
675
|
singleCellResult.addXsvOutputToBuilder(clonotypes, "propertiesBSecondary", "clonotypeProperties/" + receptor + "/bSecondary/")
|
|
676
|
+
|
|
677
|
+
singleCellResult.addXsvOutputToBuilder(clonotypes, "cellsLinkerTable", "clonotypeProperties/" + receptor + "/cellsLinkerTable/")
|
|
672
678
|
}
|
|
673
679
|
}
|
|
674
680
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
self := import("@platforma-sdk/workflow-tengo:tpl.light")
|
|
2
2
|
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
3
|
+
maps := import("@platforma-sdk/workflow-tengo:maps")
|
|
3
4
|
|
|
4
5
|
calculateExportSpecs := import(":calculate-export-specs")
|
|
5
6
|
|
|
@@ -8,7 +9,12 @@ self.defineOutputs("exportSpecs")
|
|
|
8
9
|
self.body(func(inputs) {
|
|
9
10
|
presetSpecForBack := inputs.presetSpecForBack.getDataAsJson()
|
|
10
11
|
|
|
11
|
-
exportSpecs := calculateExportSpecs(presetSpecForBack, "test")
|
|
12
|
+
exportSpecs := calculateExportSpecs(presetSpecForBack, {}, "test")
|
|
13
|
+
exportSpecs = maps.deepMerge(exportSpecs, {
|
|
14
|
+
axisByClonotypeKeyGen: undefined,
|
|
15
|
+
axisByScClonotypeKeyGen: undefined,
|
|
16
|
+
cellLinkerColumnSettingsGen: undefined
|
|
17
|
+
})
|
|
12
18
|
|
|
13
19
|
return {
|
|
14
20
|
exportSpecs: exportSpecs
|