@platforma-open/milaboratories.mixcr-clonotyping-2.workflow 2.1.0 → 2.1.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,5 +1,5 @@
1
1
 
2
- > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.1.0 build /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
2
+ > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.1.1 build /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
3
3
  > rm -rf dist && pl-tengo check && pl-tengo build
4
4
 
5
5
  Processing "src/aggregate-by-clonotype-key.tpl.tengo"...
@@ -1,20 +1,20 @@
1
1
 
2
- > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.1.0 test /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
2
+ > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@2.1.1 test /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
3
3
  > vitest
4
4
 
5
5
 
6
6
   RUN  v2.1.8 /home/runner/work/mixcr-clonotyping-2/mixcr-clonotyping-2/workflow
7
7
 
8
- ✓ src/test/columns.test.ts (6 tests) 48155ms
9
- ✓ checking preset for 'milab-human-dna-xcr-7genes-multiplex' 11939ms
10
- ✓ checking preset for '10x-sc-xcr-vdj' 7604ms
11
- ✓ checking preset for 'cellecta-human-rna-xcr-umi-drivermap-…' 7330ms
12
- ✓ checking preset for 'takara-human-rna-bcr-umi-smartseq' 7316ms
13
- ✓ checking preset for 'rna-seq' 6894ms
14
- ✓ checking preset for 'generic-single-cell-gex' 7071ms
8
+ ✓ src/test/columns.test.ts (6 tests) 49169ms
9
+ ✓ checking preset for 'milab-human-dna-xcr-7genes-multiplex' 13728ms
10
+ ✓ checking preset for '10x-sc-xcr-vdj' 7394ms
11
+ ✓ checking preset for 'cellecta-human-rna-xcr-umi-drivermap-…' 7337ms
12
+ ✓ checking preset for 'takara-human-rna-bcr-umi-smartseq' 7115ms
13
+ ✓ checking preset for 'rna-seq' 6700ms
14
+ ✓ checking preset for 'generic-single-cell-gex' 6894ms
15
15
 
16
16
   Test Files  1 passed (1)
17
17
   Tests  6 passed (6)
18
-  Start at  20:11:15
19
-  Duration  48.92s (transform 45ms, setup 0ms, collect 537ms, tests 48.16s, environment 0ms, prepare 61ms)
18
+  Start at  18:50:45
19
+  Duration  49.93s (transform 43ms, setup 0ms, collect 537ms, tests 49.17s, environment 0ms, prepare 56ms)
20
20
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @platforma-open/milaboratories.mixcr-clonotyping.workflow
2
2
 
3
+ ## 2.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - aed9be8: Fixes trace information propagation
8
+ Enhances export specifications by adding block and segment annotations
9
+ Updates abundance labels
10
+ Refines chain names in the model
11
+
3
12
  ## 2.1.0
4
13
 
5
14
  ### Minor Changes
@@ -1,4 +1,5 @@
1
1
  maps := import("@platforma-sdk/workflow-tengo:maps")
2
+ slices := import("@platforma-sdk/workflow-tengo:slices")
2
3
  ll := import("@platforma-sdk/workflow-tengo:ll")
3
4
  text := import("text")
4
5
  json := import("json")
@@ -118,7 +119,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
118
119
  "pl7.app/isAbundance": "true",
119
120
  "pl7.app/abundance/unit": "reads",
120
121
  "pl7.app/abundance/normalized": "false",
121
- "pl7.app/abundance/isPrimary": string(!hasUmi),
122
+ "pl7.app/abundance/isPrimary": !hasUmi ? "true" : undefined,
123
+ "pl7.app/isAnchor": !hasUmi ? "true" : undefined,
122
124
  "pl7.app/label": "Number Of Reads"
123
125
  })
124
126
  }
@@ -135,7 +137,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
135
137
  "pl7.app/isAbundance": "true",
136
138
  "pl7.app/abundance/unit": "reads",
137
139
  "pl7.app/abundance/normalized": "true",
138
- "pl7.app/abundance/isPrimary": string(!hasUmi),
140
+ "pl7.app/abundance/isPrimary": !hasUmi ? "true" : undefined,
139
141
  "pl7.app/label": "Fraction of reads"
140
142
  })
141
143
  }
@@ -160,7 +162,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
160
162
  "pl7.app/abundance/unit": "molecules",
161
163
  "pl7.app/abundance/normalized": "false",
162
164
  "pl7.app/abundance/isPrimary": "true",
163
- "pl7.app/label": "Number of UMI"
165
+ "pl7.app/isAnchor": "true",
166
+ "pl7.app/label": "Number of UMIs"
164
167
  })
165
168
  }
166
169
  }, {
@@ -177,7 +180,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
177
180
  "pl7.app/abundance/unit": "molecules",
178
181
  "pl7.app/abundance/normalized": "true",
179
182
  "pl7.app/abundance/isPrimary": "true",
180
- "pl7.app/label": "Fraction of UMI"
183
+ "pl7.app/label": "Fraction of UMIs"
181
184
  })
182
185
  }
183
186
  } ]
@@ -258,13 +261,6 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
258
261
  alphabetShort := isAminoAcid ? "aa" : "nt"
259
262
  alphabetShortMixcr := isAminoAcid ? "aa" : "n"
260
263
  visibility := (featureU == "CDR3") || (featureU == assemblingFeature)
261
- annotations := {
262
- "pl7.app/vdj/imputed": string(isImputed),
263
- "pl7.app/label": featureU + " " + alphabetShort
264
- }
265
- if featureU == anchorFeature && !isImputed && !isAminoAcid {
266
- annotations["pl7.app/isAnchor"] = "true"
267
- }
268
264
  columnsSpecPerClonotype += [ {
269
265
  column: alphabetShortMixcr + "Seq" + imputedU + featureU,
270
266
  id: alphabetShortMixcr + "-seq-" + featureL + (isImputed ? "-imputed" : ""),
@@ -276,7 +272,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
276
272
  "pl7.app/vdj/feature": featureU,
277
273
  "pl7.app/alphabet": alphabet
278
274
  },
279
- annotations: a(orderP, visibility, annotations)
275
+ annotations: a(orderP, visibility, {
276
+ "pl7.app/vdj/imputed": string(isImputed),
277
+ "pl7.app/label": featureU + " " + alphabetShort
278
+ })
280
279
  }
281
280
  } ]
282
281
  exportArgs += [ [ "-" + alphabetShortMixcr + "Feature" + imputedU, featureU ] ]
@@ -464,6 +463,32 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
464
463
 
465
464
 
466
465
 
466
+
467
+
468
+ addSpec := func(columns, additionalSpec) {
469
+ return slices.map(columns, func(columnSpec) {
470
+ return maps.deepMerge(columnSpec, additionalSpec)
471
+ })
472
+ }
473
+
474
+ columnsSpecPerSample = addSpec(columnsSpecPerSample, { spec: { domain: {
475
+ "pl7.app/blockId": blockId
476
+ } } })
477
+
478
+
479
+
480
+
481
+
482
+
483
+ columnsSpecPerClonotype = addSpec(columnsSpecPerClonotype, { spec: {
484
+ domain: {
485
+ "pl7.app/blockId": blockId
486
+ },
487
+ annotations: {
488
+ "pl7.app/segmentedBy": string(json.encode(["pl7.app/blockId"]))
489
+ }
490
+ } })
491
+
467
492
  columnsSpec := columnsSpecPerSample + columnsSpecPerClonotype
468
493
 
469
494
 
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-open/milaboratories.mixcr-clonotyping-2.workflow",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Tengo-based template",
5
5
  "dependencies": {
6
6
  "@platforma-open/milaboratories.mixcr-clonotyping-2.sc-clonotype-builder": "1.0.1"
@@ -9,16 +9,17 @@
9
9
  "@platforma-sdk/tengo-builder": "^1.19.2",
10
10
  "@platforma-sdk/workflow-tengo": "^2.15.6",
11
11
  "@milaboratories/software-pframes-conv": "2.1.16",
12
- "@platforma-open/milaboratories.software-small-binaries": "^1.15.15",
12
+ "@platforma-open/milaboratories.software-small-binaries": "^1.15.16",
13
13
  "@platforma-open/milaboratories.software-mixcr": "4.7.0-147-develop",
14
14
  "@platforma-open/milaboratories.software-ptransform": "^1.3.1",
15
- "@platforma-sdk/test": "^1.22.87",
15
+ "@platforma-sdk/test": "^1.22.100",
16
16
  "vitest": "^2.1.8",
17
17
  "typescript": "~5.5.4"
18
18
  },
19
19
  "scripts": {
20
20
  "build": "rm -rf dist && pl-tengo check && pl-tengo build",
21
21
  "format": "/usr/bin/env emacs --script ./format.el",
22
- "test": "vitest"
22
+ "test": "vitest",
23
+ "do-pack": "rm -f *.tgz && pnpm pack && mv *.tgz package.tgz"
23
24
  }
24
25
  }
@@ -1,4 +1,5 @@
1
1
  maps := import("@platforma-sdk/workflow-tengo:maps")
2
+ slices := import("@platforma-sdk/workflow-tengo:slices")
2
3
  ll := import("@platforma-sdk/workflow-tengo:ll")
3
4
  text := import("text")
4
5
  json := import("json")
@@ -118,7 +119,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
118
119
  "pl7.app/isAbundance": "true",
119
120
  "pl7.app/abundance/unit": "reads",
120
121
  "pl7.app/abundance/normalized": "false",
121
- "pl7.app/abundance/isPrimary": string(!hasUmi),
122
+ "pl7.app/abundance/isPrimary": !hasUmi ? "true" : undefined,
123
+ "pl7.app/isAnchor": !hasUmi ? "true" : undefined,
122
124
  "pl7.app/label": "Number Of Reads"
123
125
  })
124
126
  }
@@ -135,7 +137,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
135
137
  "pl7.app/isAbundance": "true",
136
138
  "pl7.app/abundance/unit": "reads",
137
139
  "pl7.app/abundance/normalized": "true",
138
- "pl7.app/abundance/isPrimary": string(!hasUmi),
140
+ "pl7.app/abundance/isPrimary": !hasUmi ? "true" : undefined,
139
141
  "pl7.app/label": "Fraction of reads"
140
142
  })
141
143
  }
@@ -160,7 +162,8 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
160
162
  "pl7.app/abundance/unit": "molecules",
161
163
  "pl7.app/abundance/normalized": "false",
162
164
  "pl7.app/abundance/isPrimary": "true",
163
- "pl7.app/label": "Number of UMI"
165
+ "pl7.app/isAnchor": "true",
166
+ "pl7.app/label": "Number of UMIs"
164
167
  })
165
168
  }
166
169
  }, {
@@ -177,7 +180,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
177
180
  "pl7.app/abundance/unit": "molecules",
178
181
  "pl7.app/abundance/normalized": "true",
179
182
  "pl7.app/abundance/isPrimary": "true",
180
- "pl7.app/label": "Fraction of UMI"
183
+ "pl7.app/label": "Fraction of UMIs"
181
184
  })
182
185
  }
183
186
  } ]
@@ -258,13 +261,6 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
258
261
  alphabetShort := isAminoAcid ? "aa" : "nt"
259
262
  alphabetShortMixcr := isAminoAcid ? "aa" : "n"
260
263
  visibility := (featureU == "CDR3") || (featureU == assemblingFeature)
261
- annotations := {
262
- "pl7.app/vdj/imputed": string(isImputed),
263
- "pl7.app/label": featureU + " " + alphabetShort
264
- }
265
- if featureU == anchorFeature && !isImputed && !isAminoAcid {
266
- annotations["pl7.app/isAnchor"] = "true"
267
- }
268
264
  columnsSpecPerClonotype += [ {
269
265
  column: alphabetShortMixcr + "Seq" + imputedU + featureU,
270
266
  id: alphabetShortMixcr + "-seq-" + featureL + (isImputed ? "-imputed" : ""),
@@ -276,7 +272,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
276
272
  "pl7.app/vdj/feature": featureU,
277
273
  "pl7.app/alphabet": alphabet
278
274
  },
279
- annotations: a(orderP, visibility, annotations)
275
+ annotations: a(orderP, visibility, {
276
+ "pl7.app/vdj/imputed": string(isImputed),
277
+ "pl7.app/label": featureU + " " + alphabetShort
278
+ })
280
279
  }
281
280
  } ]
282
281
  exportArgs += [ [ "-" + alphabetShortMixcr + "Feature" + imputedU, featureU ] ]
@@ -464,6 +463,32 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
464
463
 
465
464
  // All columns are added
466
465
 
466
+ // Adding block and segment annotations
467
+
468
+ addSpec := func(columns, additionalSpec) {
469
+ return slices.map(columns, func(columnSpec) {
470
+ return maps.deepMerge(columnSpec, additionalSpec)
471
+ })
472
+ }
473
+
474
+ columnsSpecPerSample = addSpec(columnsSpecPerSample, { spec: { domain: {
475
+ "pl7.app/blockId": blockId
476
+ } } })
477
+
478
+ // "pl7.app/segmentedBy" annotation indicates columns that can be meaningfully merged across
479
+ // different runs (given they have the same name and axes signature).
480
+ // Its absence indicates that merging would be semantically meaningless (e.g., abundance
481
+ // measurements specific to each analysis)
482
+
483
+ columnsSpecPerClonotype = addSpec(columnsSpecPerClonotype, { spec: {
484
+ domain: {
485
+ "pl7.app/blockId": blockId
486
+ },
487
+ annotations: {
488
+ "pl7.app/segmentedBy": string(json.encode(["pl7.app/blockId"]))
489
+ }
490
+ } })
491
+
467
492
  columnsSpec := columnsSpecPerSample + columnsSpecPerClonotype
468
493
 
469
494
  // Creating a column map for fast search
@@ -93,7 +93,7 @@ wf.body(func(args) {
93
93
  presetSpecForBack := presetInfoResult.output("presetSpecForBack", 24 * 60 * 60 * 1000)
94
94
 
95
95
  // calculating chains
96
- chains := ["IGHeavy", "IGLight", "TRA", "TRB", "TRD", "TRG"]
96
+ chains := ["IGHeavy", "IGLight", "TRAlpha", "TRBeta", "TRGamma", "TRDelta"]
97
97
  if !is_undefined(args.chains) {
98
98
  chains = args.chains
99
99
  }
@@ -32,16 +32,17 @@ self.awaitState("presetContent", "ResourceReady")
32
32
  chainInfos := {
33
33
  "IGHeavy": { mixcrFilter: "IGH", name: "IG Heavy" },
34
34
  "IGLight": { mixcrFilter: "IGK,IGL", name: "IG Light" },
35
- "TRA": { mixcrFilter: "TRA", name: "TRA" },
36
- "TRB": { mixcrFilter: "TRB", name: "TRB" },
37
- "TRD": { mixcrFilter: "TRD", name: "TRD" },
38
- "TRG": { mixcrFilter: "TRG", name: "TRG" }
35
+ "TRAlpha": { mixcrFilter: "TRA", name: "TR Alpha" },
36
+ "TRBeta": { mixcrFilter: "TRB", name: "TR Beta" },
37
+ "TRGamma": { mixcrFilter: "TRD", name: "TR Gamma" },
38
+ "TRDelta": { mixcrFilter: "TRG", name: "TR Delta" }
39
39
  }
40
40
 
41
+ // TODO better naming
41
42
  receptorInfo := {
42
43
  "IG": { chains: ["IGHeavy", "IGLight"], name: "IG" },
43
- "TRAB": { chains: ["TRB", "TRA"], name: "TRAB" },
44
- "TRGD": { chains: ["TRD", "TRG"], name: "TRGD" }
44
+ "TRAB": { chains: ["TRAlpha", "TRBeta"], name: "TRAB" },
45
+ "TRGD": { chains: ["TRGamma", "TRDelta"], name: "TRGD" }
45
46
  }
46
47
 
47
48
  self.body(func(inputs) {
@@ -243,6 +244,7 @@ self.body(func(inputs) {
243
244
 
244
245
  for chain in chains {
245
246
  chainInfo := chainInfos[chain]
247
+ ll.assert(!is_undefined(chainInfo), "chainInfo not found for chain %v", chain)
246
248
  additionalSpec := {
247
249
  spec: {
248
250
  domain: {