@platforma-open/milaboratories.mixcr-clonotyping-2.workflow 2.9.0 → 2.10.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.
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.9.0 build /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
3
+ > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.10.1 build /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/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
@@ -31,5 +31,5 @@ No syntax errors found.
31
31
  info: - writing /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow/dist/tengo/tpl/test.columns-calculate.plj.gz
32
32
  info: - writing /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow/dist/tengo/tpl/test.columns.test.plj.gz
33
33
  info: - writing /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow/dist/tengo/tpl/main.plj.gz
34
- info:
34
+ info: Template Pack build done.
35
35
  info: Template Pack build done.
@@ -1,21 +1,21 @@
1
1
   WARN  Issue while reading "/home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.9.0 test /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
3
+ > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.10.1 test /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
4
4
  > vitest
5
5
 
6
6
 
7
7
   RUN  v2.1.8 /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
8
8
 
9
- ✓ src/test/columns.test.ts (6 tests) 56823ms
10
- ✓ checking preset for 'milab-human-dna-xcr-7genes-multiplex' 15346ms
11
- ✓ checking preset for '10x-sc-xcr-vdj' 8722ms
12
- ✓ checking preset for 'cellecta-human-rna-xcr-umi-drivermap-…' 8542ms
13
- ✓ checking preset for 'takara-human-rna-bcr-umi-smartseq' 8212ms
14
- ✓ checking preset for 'rna-seq' 8009ms
15
- ✓ checking preset for 'generic-single-cell-gex' 7990ms
9
+ ✓ src/test/columns.test.ts (6 tests) 53265ms
10
+ ✓ checking preset for 'milab-human-dna-xcr-7genes-multiplex' 12934ms
11
+ ✓ checking preset for '10x-sc-xcr-vdj' 8419ms
12
+ ✓ checking preset for 'cellecta-human-rna-xcr-umi-drivermap-…' 8256ms
13
+ ✓ checking preset for 'takara-human-rna-bcr-umi-smartseq' 8191ms
14
+ ✓ checking preset for 'rna-seq' 7730ms
15
+ ✓ checking preset for 'generic-single-cell-gex' 7734ms
16
16
 
17
17
   Test Files  1 passed (1)
18
18
   Tests  6 passed (6)
19
-  Start at  06:28:06
20
-  Duration  57.72s (transform 53ms, setup 0ms, collect 631ms, tests 56.82s, environment 0ms, prepare 67ms)
19
+  Start at  15:22:19
20
+  Duration  54.10s (transform 42ms, setup 0ms, collect 592ms, tests 53.27s, environment 0ms, prepare 65ms)
21
21
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @platforma-open/milaboratories.mixcr-clonotyping.workflow
2
2
 
3
+ ## 2.10.1
4
+
5
+ ### Patch Changes
6
+
7
+ - e03cacd: updating dependencies and republish software
8
+ - Updated dependencies [e03cacd]
9
+ - @platforma-open/milaboratories.mixcr-clonotyping-2.single-cell-scripts@1.1.2
10
+
11
+ ## 2.10.0
12
+
13
+ ### Minor Changes
14
+
15
+ - b334fd0: Aggregated column "Number Of Samples" added to per-clonotype output
16
+ Exported clonotypes are limited only to productive & full-receptor
17
+
3
18
  ## 2.9.0
4
19
 
5
20
  ### Minor Changes
@@ -121,6 +121,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
121
121
  columnsSpecPerSample := []
122
122
  columnsSpecPerSampleSc := undefined
123
123
  columnsSpecPerClonotype := []
124
+ columnsSpecPerClonotypeSc := undefined
124
125
 
125
126
 
126
127
  exportArgs := []
@@ -211,6 +212,23 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
211
212
  mainAbundanceColumn = "uniqueMoleculeFraction"
212
213
  }
213
214
 
215
+ sampleCountColumn := {
216
+ column: "sampleCount",
217
+ id: "sample-count",
218
+ allowNA: false,
219
+ spec: {
220
+ name: "pl7.app/vdj/sampleCount",
221
+ valueType: "Int",
222
+ annotations: a(87110, true, {
223
+ "pl7.app/min": "1",
224
+ "pl7.app/isAbundance": "true",
225
+ "pl7.app/abundance/unit": "samples",
226
+ "pl7.app/abundance/normalized": "false",
227
+ "pl7.app/label": "Number of Samples"
228
+ })
229
+ }
230
+ }
231
+
214
232
  if isSingleCell {
215
233
 
216
234
  columnsSpecPerSample = addSpec(columnsSpecPerSample, {
@@ -247,6 +265,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
247
265
  valueType: "Double",
248
266
  annotations: a(20000, false, {
249
267
  "pl7.app/min": "0",
268
+ "pl7.app/max": "1",
250
269
  "pl7.app/isAbundance": "true",
251
270
  "pl7.app/abundance/unit": "cells",
252
271
  "pl7.app/abundance/normalized": "true",
@@ -255,6 +274,9 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
255
274
  })
256
275
  }
257
276
  } ]
277
+ columnsSpecPerClonotypeSc = [ sampleCountColumn ]
278
+ } else {
279
+ columnsSpecPerClonotype += [ sampleCountColumn ]
258
280
  }
259
281
 
260
282
  orderP := 80000
@@ -478,6 +500,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
478
500
 
479
501
 
480
502
  ]
503
+ mainProductiveColumn := flagColumnVariants[0].columnPrefix + productiveFeature
504
+ mainProductiveArgs := [ flagColumnVariants[0].arg, productiveFeature ]
481
505
  for variant in flagColumnVariants {
482
506
  columnsSpecPerClonotype += [ {
483
507
  column: variant.columnPrefix + productiveFeature,
@@ -658,10 +682,13 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
658
682
  columnsSpecPerSample: columnsSpecPerSample,
659
683
  columnsSpecPerSampleSc: columnsSpecPerSampleSc,
660
684
  columnsSpecPerClonotype: columnsSpecPerClonotype,
685
+ columnsSpecPerClonotypeSc: columnsSpecPerClonotypeSc,
661
686
 
662
687
  columnsSpec: columnsSpec,
663
688
 
664
689
  mainAbundanceColumn: mainAbundanceColumn,
690
+ mainProductiveColumn: mainProductiveColumn,
691
+ mainProductiveArgs: mainProductiveArgs,
665
692
 
666
693
  exportArgs: exportArgs
667
694
  }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@platforma-open/milaboratories.mixcr-clonotyping-2.workflow",
3
- "version": "2.9.0",
3
+ "version": "2.10.1",
4
4
  "description": "Tengo-based template",
5
5
  "dependencies": {
6
- "@platforma-sdk/workflow-tengo": "^4.0.8",
7
- "@platforma-open/milaboratories.mixcr-clonotyping-2.single-cell-scripts": "1.1.1"
6
+ "@platforma-sdk/workflow-tengo": "^4.1.0",
7
+ "@platforma-open/milaboratories.mixcr-clonotyping-2.single-cell-scripts": "1.1.2"
8
8
  },
9
9
  "devDependencies": {
10
- "@platforma-sdk/tengo-builder": "^2.0.3",
10
+ "@platforma-sdk/tengo-builder": "^2.1.0",
11
11
  "@platforma-open/milaboratories.software-mixcr": "4.7.0-150-develop",
12
12
  "@platforma-open/milaboratories.software-ptransform": "^1.3.1",
13
- "@platforma-sdk/test": "^1.29.3",
13
+ "@platforma-sdk/test": "^1.29.8",
14
14
  "vitest": "^2.1.8",
15
15
  "typescript": "~5.5.4"
16
16
  },
@@ -4,6 +4,7 @@ pConstants := import("@platforma-sdk/workflow-tengo:pframes.constants")
4
4
  slices := import("@platforma-sdk/workflow-tengo:slices")
5
5
  assets := import("@platforma-sdk/workflow-tengo:assets")
6
6
  exec := import("@platforma-sdk/workflow-tengo:exec")
7
+ maps := import("@platforma-sdk/workflow-tengo:maps")
7
8
 
8
9
  json := import("json")
9
10
 
@@ -21,6 +22,14 @@ self.body(func(inputs) {
21
22
  mainAbundanceColumn := params.mainAbundanceColumn
22
23
  clonotypeColumns := params.clonotypeColumns
23
24
 
25
+ pickCols := []
26
+ for col in clonotypeColumns {
27
+ if col == "sampleCount" {
28
+ continue
29
+ }
30
+ pickCols = append(pickCols, [col, col])
31
+ }
32
+
24
33
  // Adding clonotypeKey column
25
34
  pWorkflow := {
26
35
  steps: [ {
@@ -29,9 +38,11 @@ self.body(func(inputs) {
29
38
  aggregations: [ {
30
39
  type: "max_by",
31
40
  rankingCol: mainAbundanceColumn,
32
- pickCols: slices.map(clonotypeColumns, func(col) {
33
- return [col, col]
34
- })
41
+ pickCols: pickCols
42
+ }, {
43
+ type: "count",
44
+ src: mainAbundanceColumn,
45
+ dst: "sampleCount"
35
46
  } ]
36
47
  } ]
37
48
  }
@@ -42,7 +53,9 @@ self.body(func(inputs) {
42
53
  arg("--workflow").arg("wf.json").
43
54
  writeFile("wf.json", json.encode(pWorkflow))
44
55
 
45
- for sKey, inputFile in inputData.inputs() {
56
+ inputMap := inputData.inputs()
57
+ for sKey in maps.getKeys(inputMap) {
58
+ inputFile := inputMap[sKey]
46
59
  key := json.decode(sKey)
47
60
  if len(key) != 1 {
48
61
  ll.panic("malformed key: %v", sKey)
@@ -121,6 +121,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
121
121
  columnsSpecPerSample := []
122
122
  columnsSpecPerSampleSc := undefined
123
123
  columnsSpecPerClonotype := []
124
+ columnsSpecPerClonotypeSc := undefined
124
125
 
125
126
  // array of array of arg groups
126
127
  exportArgs := []
@@ -211,6 +212,23 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
211
212
  mainAbundanceColumn = "uniqueMoleculeFraction"
212
213
  }
213
214
 
215
+ sampleCountColumn := {
216
+ column: "sampleCount",
217
+ id: "sample-count",
218
+ allowNA: false,
219
+ spec: {
220
+ name: "pl7.app/vdj/sampleCount",
221
+ valueType: "Int",
222
+ annotations: a(87110, true, {
223
+ "pl7.app/min": "1",
224
+ "pl7.app/isAbundance": "true",
225
+ "pl7.app/abundance/unit": "samples",
226
+ "pl7.app/abundance/normalized": "false",
227
+ "pl7.app/label": "Number of Samples"
228
+ })
229
+ }
230
+ }
231
+
214
232
  if isSingleCell {
215
233
  // copying reads and umi counts and fraction removing isPrimary and isAnchor
216
234
  columnsSpecPerSample = addSpec(columnsSpecPerSample, {
@@ -247,6 +265,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
247
265
  valueType: "Double",
248
266
  annotations: a(20000, false, {
249
267
  "pl7.app/min": "0",
268
+ "pl7.app/max": "1",
250
269
  "pl7.app/isAbundance": "true",
251
270
  "pl7.app/abundance/unit": "cells",
252
271
  "pl7.app/abundance/normalized": "true",
@@ -255,6 +274,9 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
255
274
  })
256
275
  }
257
276
  } ]
277
+ columnsSpecPerClonotypeSc = [ sampleCountColumn ]
278
+ } else {
279
+ columnsSpecPerClonotype += [ sampleCountColumn ]
258
280
  }
259
281
 
260
282
  orderP := 80000
@@ -478,6 +500,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
478
500
  // visibility: false
479
501
  // }
480
502
  ]
503
+ mainProductiveColumn := flagColumnVariants[0].columnPrefix + productiveFeature
504
+ mainProductiveArgs := [ flagColumnVariants[0].arg, productiveFeature ]
481
505
  for variant in flagColumnVariants {
482
506
  columnsSpecPerClonotype += [ {
483
507
  column: variant.columnPrefix + productiveFeature,
@@ -658,10 +682,13 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
658
682
  columnsSpecPerSample: columnsSpecPerSample,
659
683
  columnsSpecPerSampleSc: columnsSpecPerSampleSc,
660
684
  columnsSpecPerClonotype: columnsSpecPerClonotype,
685
+ columnsSpecPerClonotypeSc: columnsSpecPerClonotypeSc,
661
686
 
662
687
  columnsSpec: columnsSpec,
663
688
 
664
689
  mainAbundanceColumn: mainAbundanceColumn,
690
+ mainProductiveColumn: mainProductiveColumn,
691
+ mainProductiveArgs: mainProductiveArgs,
665
692
 
666
693
  exportArgs: exportArgs
667
694
  }
@@ -8,6 +8,7 @@ exec := import("@platforma-sdk/workflow-tengo:exec")
8
8
  assets := import("@platforma-sdk/workflow-tengo:assets")
9
9
  pcolumn := import("@platforma-sdk/workflow-tengo:pframes.pcolumn")
10
10
  times := import("times")
11
+ maps := import("@platforma-sdk/workflow-tengo:maps")
11
12
 
12
13
  json := import("json")
13
14
 
@@ -92,16 +93,19 @@ self.body(func(inputs) {
92
93
  arg(preset.name)
93
94
  }
94
95
 
96
+ inputMap := inputData.inputs()
95
97
  if inputDataMeta.keyLength == 0 {
96
98
  ll.assert(aggregationAxesNames == [], "unexpected aggregation axes names")
97
- inputFile := inputData.inputs()["[]"]
99
+ // Assuming only one key "[]" exists here, no need for sorted iteration
100
+ inputFile := inputMap["[]"]
98
101
  ll.assert(!is_undefined(inputFile), "unexpected agg group structure")
99
102
  inputFileName := "input." + fileExtension
100
103
  mixcrCmdBuilder.addFile(inputFileName, inputFile)
101
104
  mixcrCmdBuilder.arg(inputFileName)
102
105
  } else if inputDataMeta.keyLength == 1 {
103
106
  ll.assert(aggregationAxesNames == ["pl7.app/sequencing/readIndex"], "unexpected aggregation axes names")
104
- for sKey, inputFile in inputData.inputs() {
107
+ for sKey in maps.getKeys(inputMap) {
108
+ inputFile := inputMap[sKey]
105
109
  key := json.decode(sKey)
106
110
  if len(key) != 1 {
107
111
  ll.panic("malformed key: %v", sKey)
@@ -115,7 +119,8 @@ self.body(func(inputs) {
115
119
  mixcrCmdBuilder.arg("input_{{R}}." + fileExtension)
116
120
  } else if inputDataMeta.keyLength == 2 {
117
121
  ll.assert(aggregationAxesNames == ["pl7.app/sequencing/lane", "pl7.app/sequencing/readIndex"], "unexpected aggregation axes names")
118
- for sKey, inputFile in inputData.inputs() {
122
+ for sKey in maps.getKeys(inputMap) {
123
+ inputFile := inputMap[sKey]
119
124
  key := json.decode(sKey)
120
125
  if len(key) != 2 {
121
126
  ll.panic("malformed key: %v", sKey)
@@ -37,6 +37,7 @@ self.body(func(inputs) {
37
37
  arg("--dont-split-files").
38
38
  arg("--drop-default-fields").
39
39
  arg("--reset-export-clone-table-splitting").
40
+ arg("--export-productive-clones-only").
40
41
  arg("--chains").arg(chains)
41
42
 
42
43
  if library {
@@ -3,10 +3,11 @@ self := import("@platforma-sdk/workflow-tengo:tpl.light")
3
3
  pConstants := import("@platforma-sdk/workflow-tengo:pframes.constants")
4
4
  assets := import("@platforma-sdk/workflow-tengo:assets")
5
5
  exec := import("@platforma-sdk/workflow-tengo:exec")
6
+ maps := import("@platforma-sdk/workflow-tengo:maps")
6
7
 
7
8
  json := import("json")
8
9
 
9
- self.defineOutputs("abundanceTsv", "propertiesAPrimaryTsv", "propertiesASecondaryTsv", "propertiesBPrimaryTsv", "propertiesBSecondaryTsv")
10
+ self.defineOutputs("abundanceTsv", "clonotypeTsv", "propertiesAPrimaryTsv", "propertiesASecondaryTsv", "propertiesBPrimaryTsv", "propertiesBSecondaryTsv")
10
11
 
11
12
  scGroupBuilderSw := assets.importSoftware("@platforma-open/milaboratories.mixcr-clonotyping-2.single-cell-scripts:sc-group-builder")
12
13
  scPreprocessingSw := assets.importSoftware("@platforma-open/milaboratories.mixcr-clonotyping-2.single-cell-scripts:preprocessing")
@@ -23,13 +24,17 @@ self.body(func(inputs) {
23
24
 
24
25
  // Creating files map
25
26
  filesMap := {}
26
- for k, v in byCellTagA.inputs() {
27
+ inputMapA := byCellTagA.inputs()
28
+ for k in maps.getKeys(inputMapA) {
29
+ v := inputMapA[k]
27
30
  key := json.decode(k)
28
31
  fileName := "by_cell_a_" + key[0] + ".tsv"
29
32
  filesMap[fileName] = v
30
33
  }
31
34
 
32
- for k, v in byCellTagB.inputs() {
35
+ inputMapB := byCellTagB.inputs()
36
+ for k in maps.getKeys(inputMapB) {
37
+ v := inputMapB[k]
33
38
  key := json.decode(k)
34
39
  fileName := "by_cell_b_" + key[0] + ".tsv"
35
40
  filesMap[fileName] = v
@@ -37,11 +42,10 @@ self.body(func(inputs) {
37
42
 
38
43
  scPreprocessingCmd := exec.builder().
39
44
  printErrStreamToStdout().
40
- software(scPreprocessingSw).
41
- addFiles(filesMap)
45
+ software(scPreprocessingSw)
42
46
 
43
- for name, f in filesMap {
44
- scPreprocessingCmd = scPreprocessingCmd.arg(name)
47
+ for name in maps.getKeys(filesMap) {
48
+ scPreprocessingCmd.addFile(name, filesMap[name]).arg(name)
45
49
  }
46
50
 
47
51
  // Data preprocessing
@@ -60,6 +64,7 @@ self.body(func(inputs) {
60
64
  software(scGroupBuilderSw).
61
65
  addFile("chain_a_output.tsv", chainAoutput).
62
66
  addFile("chain_b_output.tsv", chainBoutput).
67
+ arg("--only_full_clonotypes").
63
68
  arg("--chainA").arg("chain_a_output.tsv").
64
69
  arg("--chainB").arg("chain_b_output.tsv").
65
70
  arg("--output_clonotype").arg("clonotype.tsv").
@@ -97,6 +102,8 @@ self.body(func(inputs) {
97
102
  return {
98
103
  // must have sampleId and scClonotypeKey columns
99
104
  abundanceTsv: abundanceTsv,
105
+ // used for aggregates (i.e. sampleCount)
106
+ clonotypeTsv: clonotypeTsv,
100
107
 
101
108
  // must have scClonotypeKey columns
102
109
  propertiesAPrimaryTsv: scOutputCmd.getFile("properties_a_primary.tsv"),
@@ -197,7 +197,8 @@ self.body(func(inputs) {
197
197
  columnsSpecPerSample := exportSpecs.columnsSpecPerSample
198
198
  columnsSpecPerSampleSc := exportSpecs.columnsSpecPerSampleSc
199
199
  columnsSpecPerClonotype := exportSpecs.columnsSpecPerClonotype
200
- columnsSpec := exportSpecs.columnsSpec
200
+ columnsSpecPerClonotypeSc := exportSpecs.columnsSpecPerClonotypeSc
201
+ // columnsSpec := exportSpecs.columnsSpec
201
202
 
202
203
  clonotypeKeyColumns := exportSpecs.clonotypeKeyColumns
203
204
  clonotypeKeyArgs := exportSpecs.clonotypeKeyArgs
@@ -459,6 +460,16 @@ self.body(func(inputs) {
459
460
  },
460
461
  name: "abundanceTable",
461
462
  path: ["abundanceTsv"]
463
+ }, {
464
+ type: "Xsv",
465
+ xsvType: "tsv",
466
+ settings: {
467
+ axes: axesByScClonotypeKeyWithReceptor,
468
+ columns: columnsSpecPerClonotypeSc,
469
+ storageFormat: "Binary"
470
+ },
471
+ name: "aggregates",
472
+ path: ["clonotypeTsv"]
462
473
  } ]
463
474
 
464
475
  for chainIdx in [0, 1] {
@@ -545,6 +556,7 @@ self.body(func(inputs) {
545
556
  )
546
557
 
547
558
  singleCellResult.addXsvOutputToBuilder(clonotypes, "abundanceTable", "clonotypeProperties/abundance/" + receptor + "/")
559
+ singleCellResult.addXsvOutputToBuilder(clonotypes, "aggregates", "clonotypeProperties/aggregates/" + receptor + "/")
548
560
 
549
561
  singleCellResult.addXsvOutputToBuilder(clonotypes, "propertiesAPrimary", "clonotypeProperties/" + receptor + "/aPrimary/")
550
562
  singleCellResult.addXsvOutputToBuilder(clonotypes, "propertiesASecondary", "clonotypeProperties/" + receptor + "/aSecondary/")