@platforma-open/milaboratories.mixcr-clonotyping-2.workflow 3.17.0 → 3.18.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,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@3.17.0 build /home/runner/work/mixcr-clonotyping/mixcr-clonotyping/workflow
3
+ > @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@3.18.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
+ ## 3.18.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 070fc0b: Min quality checkbox, refactored error correction, dep updates
8
+
9
+ ## 3.17.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 5d90233: Hide non-relevant columns
14
+
3
15
  ## 3.17.0
4
16
 
5
17
  ### Minor Changes
@@ -129,13 +129,18 @@ addSpec := func(columns, additionalSpec) {
129
129
 
130
130
 
131
131
 
132
- calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
132
+ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, exportMinQuality) {
133
133
  ops := exportSpecOpsFromPreset(presetSpecForBack)
134
134
 
135
135
  assemblingFeature := ops.assemblingFeature
136
136
  cellTags := ops.cellTags
137
137
  hasUmi := ops.hasUmi
138
138
  splitByC := ops.splitByC
139
+
140
+
141
+ if is_undefined(exportMinQuality) {
142
+ exportMinQuality = false
143
+ }
139
144
 
140
145
  isSingleCell := !is_undefined(cellTags) && len(cellTags) > 0
141
146
  hashCellKey := isSingleCell && len(cellTags) > 1
@@ -260,13 +265,14 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
260
265
  spec: {
261
266
  name: "pl7.app/vdj/readFractionMean",
262
267
  valueType: "Double",
263
- annotations: a(87130, true, {
268
+ annotations: a(87130, false, {
264
269
  "pl7.app/min": "0",
265
270
  "pl7.app/max": "1",
266
271
  "pl7.app/isAbundance": "true",
267
272
  "pl7.app/abundance/unit": "reads",
268
273
  "pl7.app/abundance/normalized": "true",
269
274
  "pl7.app/label": "Mean Fraction of Reads",
275
+ "pl7.app/description": "The average read fraction of a clonotype across all samples where it is present.",
270
276
  "pl7.app/format": ".2p"
271
277
  })
272
278
  }
@@ -341,13 +347,14 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
341
347
  spec: {
342
348
  name: "pl7.app/vdj/uniqueMoleculeFractionMean",
343
349
  valueType: "Double",
344
- annotations: a(87130, true, {
350
+ annotations: a(87130, false, {
345
351
  "pl7.app/min": "0",
346
352
  "pl7.app/max": "1",
347
353
  "pl7.app/isAbundance": "true",
348
354
  "pl7.app/abundance/unit": "molecules",
349
355
  "pl7.app/abundance/normalized": "true",
350
356
  "pl7.app/label": "Mean Fraction of UMIs",
357
+ "pl7.app/description": "The average UMI fraction of a clonotype across all samples where it is present.",
351
358
  "pl7.app/format": ".2p"
352
359
  })
353
360
  }
@@ -480,7 +487,7 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
480
487
  }
481
488
  } ]
482
489
  exportArgs += [ [ "-" + alphabetShortMixcr + "Feature" + imputedU, featureInFrameU ] ]
483
- if !isImputed && !isAminoAcid {
490
+ if !isImputed && !isAminoAcid && exportMinQuality {
484
491
  columnsSpecPerClonotypeNoAggregates += [ {
485
492
  column: "minQual" + featureU,
486
493
  id: "min-qual-" + featureL,
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@platforma-open/milaboratories.mixcr-clonotyping-2.workflow",
3
- "version": "3.17.0",
3
+ "version": "3.18.0",
4
4
  "description": "Tengo-based template",
5
5
  "dependencies": {
6
- "@platforma-sdk/workflow-tengo": "^5.6.5",
6
+ "@platforma-sdk/workflow-tengo": "^5.6.6",
7
7
  "@platforma-open/milaboratories.software-mixcr": "4.7.0-254-develop"
8
8
  },
9
9
  "devDependencies": {
10
- "@milaboratories/ts-configs": "^1.0.6",
11
- "@platforma-sdk/tengo-builder": "^2.3.14",
12
- "@platforma-sdk/test": "^1.46.5",
10
+ "@milaboratories/ts-configs": "^1.1.0",
11
+ "@platforma-sdk/tengo-builder": "^2.4.1",
12
+ "@platforma-sdk/test": "^1.47.6",
13
13
  "vitest": "~4.0.15",
14
14
  "typescript": "~5.6.3"
15
15
  },
@@ -129,13 +129,18 @@ addSpec := func(columns, additionalSpec) {
129
129
  // Ordering rules
130
130
  // AA Sequences
131
131
 
132
- calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
132
+ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, exportMinQuality) {
133
133
  ops := exportSpecOpsFromPreset(presetSpecForBack)
134
134
 
135
135
  assemblingFeature := ops.assemblingFeature
136
136
  cellTags := ops.cellTags
137
137
  hasUmi := ops.hasUmi
138
138
  splitByC := ops.splitByC
139
+
140
+ // Default to false if not provided
141
+ if is_undefined(exportMinQuality) {
142
+ exportMinQuality = false
143
+ }
139
144
 
140
145
  isSingleCell := !is_undefined(cellTags) && len(cellTags) > 0
141
146
  hashCellKey := isSingleCell && len(cellTags) > 1
@@ -260,13 +265,14 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
260
265
  spec: {
261
266
  name: "pl7.app/vdj/readFractionMean",
262
267
  valueType: "Double",
263
- annotations: a(87130, true, {
268
+ annotations: a(87130, false, {
264
269
  "pl7.app/min": "0",
265
270
  "pl7.app/max": "1",
266
271
  "pl7.app/isAbundance": "true",
267
272
  "pl7.app/abundance/unit": "reads",
268
273
  "pl7.app/abundance/normalized": "true",
269
274
  "pl7.app/label": "Mean Fraction of Reads",
275
+ "pl7.app/description": "The average read fraction of a clonotype across all samples where it is present.",
270
276
  "pl7.app/format": ".2p"
271
277
  })
272
278
  }
@@ -341,13 +347,14 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
341
347
  spec: {
342
348
  name: "pl7.app/vdj/uniqueMoleculeFractionMean",
343
349
  valueType: "Double",
344
- annotations: a(87130, true, {
350
+ annotations: a(87130, false, {
345
351
  "pl7.app/min": "0",
346
352
  "pl7.app/max": "1",
347
353
  "pl7.app/isAbundance": "true",
348
354
  "pl7.app/abundance/unit": "molecules",
349
355
  "pl7.app/abundance/normalized": "true",
350
356
  "pl7.app/label": "Mean Fraction of UMIs",
357
+ "pl7.app/description": "The average UMI fraction of a clonotype across all samples where it is present.",
351
358
  "pl7.app/format": ".2p"
352
359
  })
353
360
  }
@@ -480,7 +487,7 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId) {
480
487
  }
481
488
  } ]
482
489
  exportArgs += [ [ "-" + alphabetShortMixcr + "Feature" + imputedU, featureInFrameU ] ]
483
- if !isImputed && !isAminoAcid {
490
+ if !isImputed && !isAminoAcid && exportMinQuality {
484
491
  columnsSpecPerClonotypeNoAggregates += [ {
485
492
  column: "minQual" + featureU,
486
493
  id: "min-qual-" + featureL,
@@ -122,7 +122,7 @@ wf.body(func(args) {
122
122
  limitInput: limitInput,
123
123
  perProcessMemGB: perProcessMemGB,
124
124
  perProcessCPUs: perProcessCPUs,
125
- highDiversityLibrary: args.highDiversityLibrary,
125
+ cloneClusteringMode: args.cloneClusteringMode,
126
126
  blockId: blockId,
127
127
  libraryId: libraryId,
128
128
  presetCommonName: args.presetCommonName,
@@ -131,7 +131,8 @@ wf.body(func(args) {
131
131
  rightAlignmentMode: args.rightAlignmentMode,
132
132
  materialType: args.materialType,
133
133
  tagPattern: args.tagPattern,
134
- assembleClonesBy: args.assembleClonesBy
134
+ assembleClonesBy: args.assembleClonesBy,
135
+ exportMinQuality: args.exportMinQuality
135
136
  })
136
137
  })
137
138
 
@@ -143,14 +143,19 @@ self.body(func(inputs) {
143
143
  if !is_undefined(assembleClonesBy) {
144
144
  mixcrCmdBuilder.arg("--assemble-clonotypes-by").arg(assembleClonesBy)
145
145
  }
146
- // High diversity library tuning
147
- highDiversityLibrary := params.highDiversityLibrary
148
- if !is_undefined(highDiversityLibrary) && highDiversityLibrary {
146
+ // Clone clustering tuning
147
+ cloneClusteringMode := params.cloneClusteringMode
148
+ if is_undefined(cloneClusteringMode) {
149
+ cloneClusteringMode = "default"
150
+ }
151
+ if cloneClusteringMode == "relaxed" {
149
152
  mixcrCmdBuilder.
150
153
  arg("-Massemble.cloneAssemblerParameters.minimalQuality=20").
151
154
  arg("-Massemble.cloneAssemblerParameters.badQualityThreshold=10").
152
155
  arg("-Massemble.cloneAssemblerParameters.cloneClusteringParameters.searchParameters=oneMismatchOrIndel").
153
156
  arg("-Massemble.cloneAssemblerParameters.cloneClusteringParameters.searchDepth=1")
157
+ } else if cloneClusteringMode == "off" {
158
+ mixcrCmdBuilder.arg("-Massemble.cloneAssemblerParameters.cloneClusteringParameters=null")
154
159
  }
155
160
 
156
161
  inputMap := inputData.inputs()
@@ -203,7 +203,7 @@ self.body(func(inputs) {
203
203
  }
204
204
  } ]
205
205
 
206
- exportSpecs := calculateExportSpecs(presetSpecForBack, sampleIdAxisSpec, blockId)
206
+ exportSpecs := calculateExportSpecs(presetSpecForBack, sampleIdAxisSpec, blockId, params.exportMinQuality)
207
207
 
208
208
  columnsSpecPerSample := exportSpecs.columnsSpecPerSample
209
209
  columnsSpecPerSampleSc := exportSpecs.columnsSpecPerSampleSc
@@ -273,7 +273,7 @@ self.body(func(inputs) {
273
273
  materialType: params.materialType,
274
274
  tagPattern: params.tagPattern,
275
275
  assembleClonesBy: params.assembleClonesBy,
276
- highDiversityLibrary: params.highDiversityLibrary
276
+ cloneClusteringMode: params.cloneClusteringMode
277
277
  },
278
278
  library: library,
279
279
  presetContent: presetContent
@@ -457,12 +457,35 @@ self.body(func(inputs) {
457
457
  } ]
458
458
 
459
459
  if !isSingleCell {
460
+ // Modify column visibility for TCR chains
461
+ isTCRChain := text.has_prefix(chain, "TCR")
462
+ columnsForAggregation := columnsSpecPerClonotypeNoAggregates + columnsSpecPerClonotypeAggregates
463
+ if isTCRChain {
464
+ visibilitySettings := {
465
+ "bestCGene": "optional",
466
+ "bestCHit": "optional",
467
+ "isotypePrimary": "hidden"
468
+ }
469
+ columnsForAggregation = slices.map(columnsForAggregation, func(col) {
470
+ visibility := visibilitySettings[col.column]
471
+ if !is_undefined(visibility) {
472
+ return maps.deepMerge(col, {
473
+ spec: {
474
+ annotations: maps.merge(col.spec.annotations, {
475
+ "pl7.app/table/visibility": visibility
476
+ })
477
+ }
478
+ })
479
+ }
480
+ return col
481
+ })
482
+ }
460
483
  aggregationOutputs += [ {
461
484
  type: "Xsv",
462
485
  xsvType: "tsv",
463
486
  settings: {
464
487
  axes: [ axisByClonotypeKeyGen(chain) ],
465
- columns: columnsSpecPerClonotypeNoAggregates + columnsSpecPerClonotypeAggregates,
488
+ columns: columnsForAggregation,
466
489
  storageFormat: "Parquet",
467
490
  partitionKeyLength: 0
468
491
  },
@@ -588,9 +611,34 @@ self.body(func(inputs) {
588
611
  for chainIdx in [0, 1] {
589
612
  // "A" chain is always the one that is more diverse
590
613
  chainLetterU := ["A", "B"][chainIdx]
591
- chainNameU := chainInfos[receptorInfo.chains[chainIdx]].shortName
614
+ chain := receptorInfo.chains[chainIdx]
615
+ chainNameU := chainInfos[chain].shortName
592
616
  chainNameL := text.to_lower(chainNameU)
593
617
 
618
+ // Modify column visibility for TCR chains
619
+ isTCRChain := text.has_prefix(chain, "TCR")
620
+ columnsForSingleCell := columnsSpecPerClonotypeNoAggregates
621
+ if isTCRChain {
622
+ visibilitySettings := {
623
+ "bestCGene": "optional",
624
+ "bestCHit": "optional",
625
+ "isotypePrimary": "hidden"
626
+ }
627
+ columnsForSingleCell = slices.map(columnsForSingleCell, func(col) {
628
+ visibility := visibilitySettings[col.column]
629
+ if !is_undefined(visibility) {
630
+ return maps.deepMerge(col, {
631
+ spec: {
632
+ annotations: maps.merge(col.spec.annotations, {
633
+ "pl7.app/table/visibility": visibility
634
+ })
635
+ }
636
+ })
637
+ }
638
+ return col
639
+ })
640
+ }
641
+
594
642
  for isPrimary in [true, false] {
595
643
  pPrefixU := isPrimary ? "Primary" : "Secondary"
596
644
  pPrefixL := text.to_lower(pPrefixU)
@@ -630,7 +678,7 @@ self.body(func(inputs) {
630
678
  xsvType: "tsv",
631
679
  settings: {
632
680
  axes: [ axisByScClonotypeKeyGen(receptor) ],
633
- columns: transformSpecs(isPrimary ? columnsSpecPerClonotypeNoAggregates : columnsSpecPerClonotypeSecondary, {
681
+ columns: transformSpecs(isPrimary ? columnsForSingleCell : columnsSpecPerClonotypeSecondary, {
634
682
  spec: {
635
683
  domain: {
636
684
  "pl7.app/vdj/scClonotypeChain": chainLetterU,
@@ -9,7 +9,7 @@ self.defineOutputs("exportSpecs")
9
9
  self.body(func(inputs) {
10
10
  presetSpecForBack := inputs.presetSpecForBack.getDataAsJson()
11
11
 
12
- exportSpecs := calculateExportSpecs(presetSpecForBack, {}, "test")
12
+ exportSpecs := calculateExportSpecs(presetSpecForBack, {}, "test", false)
13
13
  exportSpecs = maps.deepMerge(exportSpecs, {
14
14
  axisByClonotypeKeyGen: undefined,
15
15
  axisByScClonotypeKeyGen: undefined,