@platforma-open/milaboratories.mixcr-clonotyping-2.workflow 2.1.0 → 2.2.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.
@@ -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.2.0 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.2.0 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) 49261ms
9
+ ✓ checking preset for 'milab-human-dna-xcr-7genes-multiplex' 12586ms
10
+ ✓ checking preset for '10x-sc-xcr-vdj' 7814ms
11
+ ✓ checking preset for 'cellecta-human-rna-xcr-umi-drivermap-…' 7347ms
12
+ ✓ checking preset for 'takara-human-rna-bcr-umi-smartseq' 7319ms
13
+ ✓ checking preset for 'rna-seq' 6912ms
14
+ ✓ checking preset for 'generic-single-cell-gex' 7281ms
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  08:44:46
19
+  Duration  50.16s (transform 54ms, setup 0ms, collect 636ms, tests 49.26s, environment 0ms, prepare 69ms)
20
20
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @platforma-open/milaboratories.mixcr-clonotyping.workflow
2
2
 
3
+ ## 2.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 4b82d2d: Source domain for output columns changed from pl7.app/blockId to pl7.app/vdj/clonotypingRunId
8
+
9
+ ## 2.1.1
10
+
11
+ ### Patch Changes
12
+
13
+ - aed9be8: Fixes trace information propagation
14
+ Enhances export specifications by adding block and segment annotations
15
+ Updates abundance labels
16
+ Refines chain names in the model
17
+
3
18
  ## 2.1.0
4
19
 
5
20
  ### 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/vdj/clonotypingRunId": blockId
476
+ } } })
477
+
478
+
479
+
480
+
481
+
482
+
483
+ columnsSpecPerClonotype = addSpec(columnsSpecPerClonotype, { spec: {
484
+ domain: {
485
+ "pl7.app/vdj/clonotypingRunId": blockId
486
+ },
487
+ annotations: {
488
+ "pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
489
+ }
490
+ } })
491
+
467
492
  columnsSpec := columnsSpecPerSample + columnsSpecPerClonotype
468
493
 
469
494
 
@@ -542,7 +567,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
542
567
  type: "String",
543
568
  domain: {
544
569
  "pl7.app/vdj/cellTagId": tag,
545
- "pl7.app/blockId": blockId
570
+ "pl7.app/vdj/clonotypingRunId": blockId
546
571
  },
547
572
  annotations: a(orderP, true, {
548
573
  "pl7.app/label": label
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.2.0",
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/vdj/clonotypingRunId": 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/vdj/clonotypingRunId": blockId
486
+ },
487
+ annotations: {
488
+ "pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
489
+ }
490
+ } })
491
+
467
492
  columnsSpec := columnsSpecPerSample + columnsSpecPerClonotype
468
493
 
469
494
  // Creating a column map for fast search
@@ -542,7 +567,7 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
542
567
  type: "String",
543
568
  domain: {
544
569
  "pl7.app/vdj/cellTagId": tag,
545
- "pl7.app/blockId": blockId
570
+ "pl7.app/vdj/clonotypingRunId": blockId
546
571
  },
547
572
  annotations: a(orderP, true, {
548
573
  "pl7.app/label": label
@@ -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) {
@@ -131,7 +132,7 @@ self.body(func(inputs) {
131
132
  valueType: "File",
132
133
  name: "mixcr.com/qc",
133
134
  domain: {
134
- "pl7.app/blockId": blockId
135
+ "pl7.app/vdj/clonotypingRunId": blockId
135
136
  }
136
137
  },
137
138
  name: "qc"
@@ -141,7 +142,7 @@ self.body(func(inputs) {
141
142
  kind: "PColumn",
142
143
  name: "pl7.app/log",
143
144
  domain: {
144
- "pl7.app/blockId": blockId
145
+ "pl7.app/vdj/clonotypingRunId": blockId
145
146
  },
146
147
  valueType: "Log"
147
148
  },
@@ -152,7 +153,7 @@ self.body(func(inputs) {
152
153
  kind: "PColumn",
153
154
  name: "mixcr.com/clns",
154
155
  domain: {
155
- "pl7.app/blockId": blockId
156
+ "pl7.app/vdj/clonotypingRunId": blockId
156
157
  },
157
158
  annotations: clnsAnnotations,
158
159
  valueType: "File"
@@ -165,7 +166,7 @@ self.body(func(inputs) {
165
166
  kind: "PColumn",
166
167
  name: "mixcr.com/report",
167
168
  domain: {
168
- "pl7.app/blockId": blockId
169
+ "pl7.app/vdj/clonotypingRunId": blockId
169
170
  },
170
171
  valueType: "File",
171
172
  axesSpec: [ {
@@ -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: {
@@ -264,7 +266,7 @@ self.body(func(inputs) {
264
266
  kind: "PColumn",
265
267
  name: "mixcr.com/clonotypeTable",
266
268
  domain: {
267
- "pl7.app/blockId": blockId
269
+ "pl7.app/vdj/clonotypingRunId": blockId
268
270
  },
269
271
  valueType: "File"
270
272
  },