@platforma-open/milaboratories.mixcr-amplicon-alignment.workflow 1.16.0 → 1.17.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-amplicon-alignment/mixcr-amplicon-alignment/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-open/milaboratories.mixcr-amplicon-alignment.workflow@1.16.0 build /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow
3
+ > @platforma-open/milaboratories.mixcr-amplicon-alignment.workflow@1.17.0 build /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow
4
4
  > rm -rf dist && pl-tengo check && pl-tengo build
5
5
 
6
6
  Processing "src/aggregate-by-clonotype-key.tpl.tengo"...
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @platforma-open/milaboratories.mixcr-amplicon-alignment.workflow
2
2
 
3
+ ## 1.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 34824d1: mutations columns added, removed unused columns, dependency updates and migrate block code to latest layout
8
+
3
9
  ## 1.16.0
4
10
 
5
11
  ### Minor Changes
@@ -91,13 +91,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
91
91
  [ "-jGene" ]
92
92
  ]
93
93
  }
94
- if splitByC {
95
- clonotypeKeyColumns += ["bestCGene"]
96
- clonotypeKeyArgs += [ [ "-cGene" ] ]
97
- }
98
94
 
99
95
  columnsSpecPerSample := []
100
96
  columnsSpecPerClonotypeNoAggregates := []
97
+ mutationColumns := []
101
98
 
102
99
  clonotypeLabelColumn := {
103
100
  column: "clonotypeLabel",
@@ -419,14 +416,15 @@ inFrameFeatures := {
419
416
  argSuffix: "Gene",
420
417
  visible: true
421
418
  } ]
422
- for vdjcU in ["V", "D", "J", "C"] {
419
+
420
+ for vdjcU in ["V", "J"] {
423
421
  vdjcL := text.to_lower(vdjcU)
424
422
  for variant in geneHitColumnVariants {
425
423
  columnsSpecPerClonotypeNoAggregates += [ {
426
424
  column: "best" + vdjcU + variant.columnNameSuffix,
427
425
  id: "best-" + vdjcL + variant.idSuffix,
428
426
  naRegex: "",
429
- allowNA: vdjcU == "C" || vdjcU == "D",
427
+ allowNA: false,
430
428
  spec: {
431
429
  name: variant.name,
432
430
  valueType: "String",
@@ -475,7 +473,7 @@ inFrameFeatures := {
475
473
  }
476
474
 
477
475
  for variant in mutationColumnVariants {
478
- columnsSpecPerClonotypeNoAggregates += [ {
476
+ mutationColumns += [ {
479
477
  column: alphabetShortMixcr + variant.name + coreFeature,
480
478
  id: alphabetShortMixcr + variant.idPart + geneL,
481
479
  allowNA: true,
@@ -499,6 +497,212 @@ inFrameFeatures := {
499
497
  }
500
498
 
501
499
 
500
+ if assemblingFeature == "VDJRegion" {
501
+ orderP = 9500
502
+
503
+
504
+
505
+
506
+ for featureU in features {
507
+
508
+ if featureU == "CDR3" || featureU == "VDJRegion" || featureU == "FR4" {
509
+ continue
510
+ }
511
+ featureL := text.to_lower(formatId(featureU))
512
+ rateOrderP := orderP - 1
513
+ columnName := "nMutationsCount" + featureU
514
+ mutationColumns += [ {
515
+ column: columnName,
516
+ id: "n-mutations-count-" + featureL,
517
+ allowNA: true,
518
+ naRegex: "region_not_covered",
519
+ spec: {
520
+ valueType: "Int",
521
+ name: "pl7.app/vdj/sequence/nMutationsCount",
522
+ domain: {
523
+ "pl7.app/vdj/feature": featureU
524
+ },
525
+ annotations: a(orderP, false, {
526
+ "pl7.app/label": "Nt mutations count in " + featureU
527
+ })
528
+ }
529
+ } ]
530
+ columnName = "nMutationsRate" + featureU
531
+ mutationColumns += [ {
532
+ column: columnName,
533
+ id: "n-mutations-rate-" + featureL,
534
+ allowNA: true,
535
+ naRegex: "region_not_covered",
536
+ spec: {
537
+ valueType: "Double",
538
+ name: "pl7.app/vdj/sequence/nMutationsRate",
539
+ domain: {
540
+ "pl7.app/vdj/feature": featureU
541
+ },
542
+ annotations: a(rateOrderP, false, {
543
+ "pl7.app/label": "Nt mutations rate in " + featureU
544
+ })
545
+ }
546
+ } ]
547
+ exportArgs += [ [ "-nMutationRate", featureU ] ]
548
+ orderP -= 100
549
+ }
550
+
551
+
552
+ exportArgs += [ [ "-allNMutationsCount", "FR1Begin", "FR4End" ] ]
553
+
554
+
555
+ orderP = 8500
556
+
557
+
558
+
559
+
560
+ for featureU in features {
561
+
562
+ if featureU == "CDR3" || featureU == "VDJRegion" || featureU == "FR4" {
563
+ continue
564
+ }
565
+ featureL := text.to_lower(formatId(featureU))
566
+ rateOrderP := orderP - 1
567
+ columnName := "aaMutationsCount" + featureU
568
+ mutationColumns += [ {
569
+ column: columnName,
570
+ id: "aa-mutations-count-" + featureL,
571
+ allowNA: true,
572
+ naRegex: "region_not_covered",
573
+ spec: {
574
+ valueType: "Int",
575
+ name: "pl7.app/vdj/sequence/aaMutationsCount",
576
+ domain: {
577
+ "pl7.app/vdj/feature": featureU
578
+ },
579
+ annotations: a(orderP, false, {
580
+ "pl7.app/label": "AA mutations count in " + featureU
581
+ })
582
+ }
583
+ } ]
584
+ columnName = "aaMutationsRate" + featureU
585
+ mutationColumns += [ {
586
+ column: columnName,
587
+ id: "aa-mutations-rate-" + featureL,
588
+ allowNA: true,
589
+ naRegex: "region_not_covered",
590
+ spec: {
591
+ valueType: "Double",
592
+ name: "pl7.app/vdj/sequence/aaMutationsRate",
593
+ domain: {
594
+ "pl7.app/vdj/feature": featureU
595
+ },
596
+ annotations: a(rateOrderP, false, {
597
+ "pl7.app/label": "AA mutations rate in " + featureU
598
+ })
599
+ }
600
+ } ]
601
+ exportArgs += [ [ "-aaMutationRate", featureU ] ]
602
+ orderP -= 100
603
+ }
604
+
605
+
606
+ exportArgs += [ [ "-allAAMutationsCount", "FR1Begin", "FR4End" ] ]
607
+
608
+ }
609
+
610
+
611
+
612
+ germlineVFeature := "GermlineVCDR3Part"
613
+ germlineJFeature := "GermlineJCDR3Part"
614
+ exportArgs += [ [ "-nMutationsCount", germlineVFeature ] ]
615
+ exportArgs += [ [ "-nMutationsCount", germlineJFeature ] ]
616
+ exportArgs += [ [ "-aaMutationsCount", germlineVFeature ] ]
617
+ exportArgs += [ [ "-aaMutationsCount", germlineJFeature ] ]
618
+
619
+
620
+
621
+ orderP = 9400
622
+ cdr3Feature := "CDR3"
623
+ cdr3FeatureL := text.to_lower(formatId(cdr3Feature))
624
+
625
+
626
+ columnName := "nMutationsCount" + cdr3Feature
627
+ cdr3DistanceColumnsSpec := [ {
628
+ column: columnName,
629
+ id: "n-mutations-count-" + cdr3FeatureL,
630
+ allowNA: true,
631
+ naRegex: "region_not_covered",
632
+ spec: {
633
+ valueType: "Int",
634
+ name: "pl7.app/vdj/sequence/nMutationsCount",
635
+ domain: {
636
+ "pl7.app/vdj/feature": cdr3Feature
637
+ },
638
+ annotations: a(orderP, false, {
639
+ "pl7.app/label": "Nt mutations count in " + cdr3Feature
640
+ })
641
+ }
642
+ } ]
643
+
644
+
645
+ orderP = 8400
646
+ columnName = "aaMutationsCount" + cdr3Feature
647
+ cdr3DistanceColumnsSpec = append(cdr3DistanceColumnsSpec, {
648
+ column: columnName,
649
+ id: "aa-mutations-count-" + cdr3FeatureL,
650
+ allowNA: true,
651
+ naRegex: "region_not_covered",
652
+ spec: {
653
+ valueType: "Int",
654
+ name: "pl7.app/vdj/sequence/aaMutationsCount",
655
+ domain: {
656
+ "pl7.app/vdj/feature": cdr3Feature
657
+ },
658
+ annotations: a(orderP, false, {
659
+ "pl7.app/label": "AA mutations count in " + cdr3Feature
660
+ })
661
+ }
662
+ } )
663
+
664
+
665
+ orderP = 9300
666
+ columnName = "nMutationsRate" + cdr3Feature
667
+ cdr3DistanceColumnsSpec = append(cdr3DistanceColumnsSpec, {
668
+ column: columnName,
669
+ id: "n-mutations-rate-" + cdr3FeatureL,
670
+ allowNA: true,
671
+ naRegex: "region_not_covered",
672
+ spec: {
673
+ valueType: "Double",
674
+ name: "pl7.app/vdj/sequence/nMutationsRate",
675
+ domain: {
676
+ "pl7.app/vdj/feature": cdr3Feature
677
+ },
678
+ annotations: a(orderP, false, {
679
+ "pl7.app/label": "Nt mutations rate in " + cdr3Feature
680
+ })
681
+ }
682
+ })
683
+
684
+
685
+ orderP = 8300
686
+ columnName = "aaMutationsRate" + cdr3Feature
687
+ cdr3DistanceColumnsSpec = append(cdr3DistanceColumnsSpec, {
688
+ column: columnName,
689
+ id: "aa-mutations-rate-" + cdr3FeatureL,
690
+ allowNA: true,
691
+ naRegex: "region_not_covered",
692
+ spec: {
693
+ valueType: "Double",
694
+ name: "pl7.app/vdj/sequence/aaMutationsRate",
695
+ domain: {
696
+ "pl7.app/vdj/feature": cdr3Feature
697
+ },
698
+ annotations: a(orderP, false, {
699
+ "pl7.app/label": "AA mutations rate in " + cdr3Feature
700
+ })
701
+ }
702
+ })
703
+
704
+
705
+ orderP = 12000
502
706
 
503
707
  flagColumnVariants := [ {
504
708
  columnPrefix: "isProductive",
@@ -533,18 +737,6 @@ inFrameFeatures := {
533
737
 
534
738
 
535
739
  columnsSpecPerClonotypeNoAggregates += [ {
536
- column: "isotypePrimary",
537
- id: "isotype",
538
- naRegex: "",
539
- spec: {
540
- valueType: "String",
541
- name: "pl7.app/vdj/isotype",
542
- annotations: a(orderP, true, {
543
- "pl7.app/label": "IG isotype",
544
- "pl7.app/isDiscreteFilter": "true"
545
- })
546
- }
547
- }, {
548
740
  column: "topChains",
549
741
  id: "top-chains",
550
742
  naRegex: "",
@@ -560,12 +752,12 @@ inFrameFeatures := {
560
752
  }
561
753
  } ]
562
754
  exportArgs += [
563
- [ "-isotype", "primary" ],
564
755
  [ "-topChains" ]
565
756
  ]
566
757
 
567
758
 
568
759
 
760
+ columnsSpecPerClonotypeNoAggregates += mutationColumns
569
761
 
570
762
  columnsSpec := columnsSpecPerSample + columnsSpecPerClonotypeNoAggregates + columnsSpecPerClonotypeAggregates
571
763
 
@@ -623,6 +815,7 @@ inFrameFeatures := {
623
815
  columnsSpecPerSample: columnsSpecPerSample,
624
816
  columnsSpecPerClonotypeNoAggregates: columnsSpecPerClonotypeNoAggregates,
625
817
  columnsSpecPerClonotypeAggregates: columnsSpecPerClonotypeAggregates,
818
+ cdr3DistanceColumnsSpec: cdr3DistanceColumnsSpec,
626
819
 
627
820
  columnsSpec: columnsSpec,
628
821
 
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,21 +1,20 @@
1
1
  {
2
2
  "name": "@platforma-open/milaboratories.mixcr-amplicon-alignment.workflow",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "MiXCR Amplicon Alignment Workflow",
5
5
  "type": "module",
6
6
  "dependencies": {
7
- "@platforma-sdk/workflow-tengo": "^5.8.0",
8
- "@platforma-open/milaboratories.software-mixcr": "4.7.0-254-develop",
9
- "@platforma-open/milaboratories.software-repseqio": "^2.5.0-13-master"
7
+ "@platforma-sdk/workflow-tengo": "5.8.0",
8
+ "@platforma-open/milaboratories.software-mixcr": "4.7.0-279-develop",
9
+ "@platforma-open/milaboratories.software-repseqio": "^2.5.0-13-master",
10
+ "@platforma-open/milaboratories.mixcr-amplicon-alignment.software": "1.0.0"
10
11
  },
11
12
  "devDependencies": {
12
- "@platforma-sdk/tengo-builder": "^2.4.11",
13
- "@platforma-sdk/test": "^1.52.4",
14
- "vitest": "^4.0.17"
13
+ "@platforma-sdk/tengo-builder": "2.4.11"
15
14
  },
16
15
  "scripts": {
17
16
  "build": "rm -rf dist && pl-tengo check && pl-tengo build",
18
- "test": "vitest",
19
- "format": "/usr/bin/env emacs --script ./format.el"
17
+ "format": "/usr/bin/env emacs --script ./format.el",
18
+ "do-pack": "rm -f *.tgz && pnpm pack && mv *.tgz package.tgz"
20
19
  }
21
20
  }
@@ -5,12 +5,16 @@ slices := import("@platforma-sdk/workflow-tengo:slices")
5
5
  maps := import("@platforma-sdk/workflow-tengo:maps")
6
6
  units := import("@platforma-sdk/workflow-tengo:units")
7
7
  pt := import("@platforma-sdk/workflow-tengo:pt")
8
+ assets := import("@platforma-sdk/workflow-tengo:assets")
9
+ exec := import("@platforma-sdk/workflow-tengo:exec")
8
10
  clonotypeLabel := import(":clonotype-label")
9
11
 
10
12
  math := import("math")
11
13
  json := import("json")
12
14
 
13
- self.defineOutputs("tsv")
15
+ self.defineOutputs("tsv", "cdr3DistancesTsv")
16
+
17
+ cdr3DistanceSw := assets.importSoftware("@platforma-open/milaboratories.mixcr-amplicon-alignment.software:cdr3-distance-calculation")
14
18
 
15
19
  self.body(func(inputs) {
16
20
  inputData := inputs[pConstants.VALUE_FIELD_NAME]
@@ -88,13 +92,37 @@ self.body(func(inputs) {
88
92
 
89
93
  aggregatedDf = clonotypeLabel.addClonotypeLabelColumnsPt(aggregatedDf, "clonotypeKey", "clonotypeLabel", pt)
90
94
 
95
+ cdr3Df := aggregatedDf.select(
96
+ pt.col("clonotypeKey"),
97
+ pt.col("nSeqCDR3").alias("nSeqCDR3"),
98
+ pt.col("aaSeqCDR3").alias("aaSeqCDR3")
99
+ )
100
+
91
101
  aggregatedDf.save("output.tsv")
102
+ cdr3Df.save("cdr3-sequences.tsv")
92
103
 
93
104
  ptablerResult := wf.run()
94
105
 
95
106
  processedTsv := ptablerResult.getFile("output.tsv")
107
+ cdr3Tsv := ptablerResult.getFile("cdr3-sequences.tsv")
108
+ cdr3DistancesTsv := undefined
109
+
110
+ if !is_undefined(params.cdr3Sequences) {
111
+ cdr3DistanceCmd := exec.builder().
112
+ software(cdr3DistanceSw).
113
+ mem("8GB").
114
+ cpu(1).
115
+ writeFile("cdr3-sequences.fasta", params.cdr3Sequences).saveFile("cdr3-sequences.fasta").
116
+ arg("--tsv").arg("cdr3-sequences.tsv").addFile("cdr3-sequences.tsv", cdr3Tsv).
117
+ arg("--ref-fasta").arg("cdr3-sequences.fasta").
118
+ arg("--out").arg("cdr3-distances.tsv").saveFile("cdr3-distances.tsv")
119
+
120
+ cdr3DistanceResult := cdr3DistanceCmd.run()
121
+ cdr3DistancesTsv = cdr3DistanceResult.getFile("cdr3-distances.tsv")
122
+ }
96
123
 
97
124
  return {
98
- tsv: processedTsv
125
+ tsv: processedTsv,
126
+ cdr3DistancesTsv: cdr3DistancesTsv
99
127
  }
100
128
  })
@@ -91,13 +91,10 @@ calculateExportSpecs := func(presetSpecForBack, blockId) {
91
91
  [ "-jGene" ]
92
92
  ]
93
93
  }
94
- if splitByC {
95
- clonotypeKeyColumns += ["bestCGene"]
96
- clonotypeKeyArgs += [ [ "-cGene" ] ]
97
- }
98
94
 
99
95
  columnsSpecPerSample := []
100
96
  columnsSpecPerClonotypeNoAggregates := []
97
+ mutationColumns := []
101
98
 
102
99
  clonotypeLabelColumn := {
103
100
  column: "clonotypeLabel",
@@ -419,14 +416,15 @@ inFrameFeatures := {
419
416
  argSuffix: "Gene",
420
417
  visible: true
421
418
  } ]
422
- for vdjcU in ["V", "D", "J", "C"] {
419
+ // Only export V and J genes (D and C are excluded)
420
+ for vdjcU in ["V", "J"] {
423
421
  vdjcL := text.to_lower(vdjcU)
424
422
  for variant in geneHitColumnVariants {
425
423
  columnsSpecPerClonotypeNoAggregates += [ {
426
424
  column: "best" + vdjcU + variant.columnNameSuffix,
427
425
  id: "best-" + vdjcL + variant.idSuffix,
428
426
  naRegex: "",
429
- allowNA: vdjcU == "C" || vdjcU == "D",
427
+ allowNA: false,
430
428
  spec: {
431
429
  name: variant.name,
432
430
  valueType: "String",
@@ -475,7 +473,7 @@ inFrameFeatures := {
475
473
  }
476
474
 
477
475
  for variant in mutationColumnVariants {
478
- columnsSpecPerClonotypeNoAggregates += [ {
476
+ mutationColumns += [ {
479
477
  column: alphabetShortMixcr + variant.name + coreFeature,
480
478
  id: alphabetShortMixcr + variant.idPart + geneL,
481
479
  allowNA: true,
@@ -498,7 +496,213 @@ inFrameFeatures := {
498
496
  }
499
497
  }
500
498
 
499
+ // All nucleotide mutations count for each feature (only for VDJRegion assembling feature)
500
+ if assemblingFeature == "VDJRegion" {
501
+ orderP = 9500
502
+
503
+ // MixCR -allNMutationsCount exports columns for all features between specified boundaries.
504
+ // We add column specs for each feature and call -allNMutationsCount once with boundaries
505
+ // FR1Begin FR4End to cover all features. This exports all mutation types in one column.
506
+ for featureU in features {
507
+ // Skip CDR3 and VDJRegion features
508
+ if featureU == "CDR3" || featureU == "VDJRegion" || featureU == "FR4" {
509
+ continue
510
+ }
511
+ featureL := text.to_lower(formatId(featureU))
512
+ rateOrderP := orderP - 1
513
+ columnName := "nMutationsCount" + featureU
514
+ mutationColumns += [ {
515
+ column: columnName,
516
+ id: "n-mutations-count-" + featureL,
517
+ allowNA: true,
518
+ naRegex: "region_not_covered",
519
+ spec: {
520
+ valueType: "Int",
521
+ name: "pl7.app/vdj/sequence/nMutationsCount",
522
+ domain: {
523
+ "pl7.app/vdj/feature": featureU
524
+ },
525
+ annotations: a(orderP, false, {
526
+ "pl7.app/label": "Nt mutations count in " + featureU
527
+ })
528
+ }
529
+ } ]
530
+ columnName = "nMutationsRate" + featureU
531
+ mutationColumns += [ {
532
+ column: columnName,
533
+ id: "n-mutations-rate-" + featureL,
534
+ allowNA: true,
535
+ naRegex: "region_not_covered",
536
+ spec: {
537
+ valueType: "Double",
538
+ name: "pl7.app/vdj/sequence/nMutationsRate",
539
+ domain: {
540
+ "pl7.app/vdj/feature": featureU
541
+ },
542
+ annotations: a(rateOrderP, false, {
543
+ "pl7.app/label": "Nt mutations rate in " + featureU
544
+ })
545
+ }
546
+ } ]
547
+ exportArgs += [ [ "-nMutationRate", featureU ] ]
548
+ orderP -= 100
549
+ }
550
+ // Call -allNMutationsCount with boundaries FR1Begin FR4End (no mutation type parameter)
551
+ // This will export columns for all features between FR1Begin and FR4End with all mutation types
552
+ exportArgs += [ [ "-allNMutationsCount", "FR1Begin", "FR4End" ] ]
553
+
554
+ // All amino acid mutations count for each feature (only for VDJRegion assembling feature)
555
+ orderP = 8500
556
+
557
+ // MixCR -allAAMutationsCount exports columns for all features between specified boundaries.
558
+ // We add column specs for each feature and call -allAAMutationsCount once with boundaries
559
+ // FR1Begin FR4End to cover all features. This exports all mutation types in one column.
560
+ for featureU in features {
561
+ // Skip CDR3 and VDJRegion features
562
+ if featureU == "CDR3" || featureU == "VDJRegion" || featureU == "FR4" {
563
+ continue
564
+ }
565
+ featureL := text.to_lower(formatId(featureU))
566
+ rateOrderP := orderP - 1
567
+ columnName := "aaMutationsCount" + featureU
568
+ mutationColumns += [ {
569
+ column: columnName,
570
+ id: "aa-mutations-count-" + featureL,
571
+ allowNA: true,
572
+ naRegex: "region_not_covered",
573
+ spec: {
574
+ valueType: "Int",
575
+ name: "pl7.app/vdj/sequence/aaMutationsCount",
576
+ domain: {
577
+ "pl7.app/vdj/feature": featureU
578
+ },
579
+ annotations: a(orderP, false, {
580
+ "pl7.app/label": "AA mutations count in " + featureU
581
+ })
582
+ }
583
+ } ]
584
+ columnName = "aaMutationsRate" + featureU
585
+ mutationColumns += [ {
586
+ column: columnName,
587
+ id: "aa-mutations-rate-" + featureL,
588
+ allowNA: true,
589
+ naRegex: "region_not_covered",
590
+ spec: {
591
+ valueType: "Double",
592
+ name: "pl7.app/vdj/sequence/aaMutationsRate",
593
+ domain: {
594
+ "pl7.app/vdj/feature": featureU
595
+ },
596
+ annotations: a(rateOrderP, false, {
597
+ "pl7.app/label": "AA mutations rate in " + featureU
598
+ })
599
+ }
600
+ } ]
601
+ exportArgs += [ [ "-aaMutationRate", featureU ] ]
602
+ orderP -= 100
603
+ }
604
+ // Call -allAAMutationsCount with boundaries FR1Begin FR4End (no mutation type parameter)
605
+ // This will export columns for all features between FR1Begin and FR4End with all mutation types
606
+ exportArgs += [ [ "-allAAMutationsCount", "FR1Begin", "FR4End" ] ]
607
+
608
+ }
609
+
610
+ // Export germline CDR3 part mutations for both VDJRegion and CDR3 assembling features
611
+ // These will be summed to create the CDR3 mutations count columns
612
+ germlineVFeature := "GermlineVCDR3Part"
613
+ germlineJFeature := "GermlineJCDR3Part"
614
+ exportArgs += [ [ "-nMutationsCount", germlineVFeature ] ]
615
+ exportArgs += [ [ "-nMutationsCount", germlineJFeature ] ]
616
+ exportArgs += [ [ "-aaMutationsCount", germlineVFeature ] ]
617
+ exportArgs += [ [ "-aaMutationsCount", germlineJFeature ] ]
618
+
619
+ // Add CDR3 mutations count columns (sum of V and J germline CDR3 part mutations)
620
+ // These work for both VDJRegion and CDR3 assembling features
621
+ orderP = 9400
622
+ cdr3Feature := "CDR3"
623
+ cdr3FeatureL := text.to_lower(formatId(cdr3Feature))
624
+
625
+ // Nucleotide mutations count
626
+ columnName := "nMutationsCount" + cdr3Feature
627
+ cdr3DistanceColumnsSpec := [ {
628
+ column: columnName,
629
+ id: "n-mutations-count-" + cdr3FeatureL,
630
+ allowNA: true,
631
+ naRegex: "region_not_covered",
632
+ spec: {
633
+ valueType: "Int",
634
+ name: "pl7.app/vdj/sequence/nMutationsCount",
635
+ domain: {
636
+ "pl7.app/vdj/feature": cdr3Feature
637
+ },
638
+ annotations: a(orderP, false, {
639
+ "pl7.app/label": "Nt mutations count in " + cdr3Feature
640
+ })
641
+ }
642
+ } ]
643
+
644
+ // Amino acid mutations count
645
+ orderP = 8400
646
+ columnName = "aaMutationsCount" + cdr3Feature
647
+ cdr3DistanceColumnsSpec = append(cdr3DistanceColumnsSpec, {
648
+ column: columnName,
649
+ id: "aa-mutations-count-" + cdr3FeatureL,
650
+ allowNA: true,
651
+ naRegex: "region_not_covered",
652
+ spec: {
653
+ valueType: "Int",
654
+ name: "pl7.app/vdj/sequence/aaMutationsCount",
655
+ domain: {
656
+ "pl7.app/vdj/feature": cdr3Feature
657
+ },
658
+ annotations: a(orderP, false, {
659
+ "pl7.app/label": "AA mutations count in " + cdr3Feature
660
+ })
661
+ }
662
+ } )
663
+
664
+ // Nucleotide mutations rate
665
+ orderP = 9300
666
+ columnName = "nMutationsRate" + cdr3Feature
667
+ cdr3DistanceColumnsSpec = append(cdr3DistanceColumnsSpec, {
668
+ column: columnName,
669
+ id: "n-mutations-rate-" + cdr3FeatureL,
670
+ allowNA: true,
671
+ naRegex: "region_not_covered",
672
+ spec: {
673
+ valueType: "Double",
674
+ name: "pl7.app/vdj/sequence/nMutationsRate",
675
+ domain: {
676
+ "pl7.app/vdj/feature": cdr3Feature
677
+ },
678
+ annotations: a(orderP, false, {
679
+ "pl7.app/label": "Nt mutations rate in " + cdr3Feature
680
+ })
681
+ }
682
+ })
683
+
684
+ // Amino acid mutations rate
685
+ orderP = 8300
686
+ columnName = "aaMutationsRate" + cdr3Feature
687
+ cdr3DistanceColumnsSpec = append(cdr3DistanceColumnsSpec, {
688
+ column: columnName,
689
+ id: "aa-mutations-rate-" + cdr3FeatureL,
690
+ allowNA: true,
691
+ naRegex: "region_not_covered",
692
+ spec: {
693
+ valueType: "Double",
694
+ name: "pl7.app/vdj/sequence/aaMutationsRate",
695
+ domain: {
696
+ "pl7.app/vdj/feature": cdr3Feature
697
+ },
698
+ annotations: a(orderP, false, {
699
+ "pl7.app/label": "AA mutations rate in " + cdr3Feature
700
+ })
701
+ }
702
+ })
703
+
501
704
  // Flags: productive, oof, stop codons
705
+ orderP = 12000
502
706
 
503
707
  flagColumnVariants := [ {
504
708
  columnPrefix: "isProductive",
@@ -530,21 +734,9 @@ inFrameFeatures := {
530
734
  orderP -= 100
531
735
  }
532
736
 
533
- // Isotype and chain
737
+ // Chain (isotype removed)
534
738
 
535
739
  columnsSpecPerClonotypeNoAggregates += [ {
536
- column: "isotypePrimary",
537
- id: "isotype",
538
- naRegex: "",
539
- spec: {
540
- valueType: "String",
541
- name: "pl7.app/vdj/isotype",
542
- annotations: a(orderP, true, {
543
- "pl7.app/label": "IG isotype",
544
- "pl7.app/isDiscreteFilter": "true"
545
- })
546
- }
547
- }, {
548
740
  column: "topChains",
549
741
  id: "top-chains",
550
742
  naRegex: "",
@@ -560,12 +752,12 @@ inFrameFeatures := {
560
752
  }
561
753
  } ]
562
754
  exportArgs += [
563
- [ "-isotype", "primary" ],
564
755
  [ "-topChains" ]
565
756
  ]
566
757
 
567
758
 
568
759
  // All columns are added
760
+ columnsSpecPerClonotypeNoAggregates += mutationColumns
569
761
 
570
762
  columnsSpec := columnsSpecPerSample + columnsSpecPerClonotypeNoAggregates + columnsSpecPerClonotypeAggregates
571
763
 
@@ -623,6 +815,7 @@ inFrameFeatures := {
623
815
  columnsSpecPerSample: columnsSpecPerSample,
624
816
  columnsSpecPerClonotypeNoAggregates: columnsSpecPerClonotypeNoAggregates,
625
817
  columnsSpecPerClonotypeAggregates: columnsSpecPerClonotypeAggregates,
818
+ cdr3DistanceColumnsSpec: cdr3DistanceColumnsSpec,
626
819
 
627
820
  columnsSpec: columnsSpec,
628
821
 
@@ -58,6 +58,7 @@ wf.body(func(args) {
58
58
  inputData: input.getFutureInputField("data"),
59
59
  referenceLibrary: referenceLibrary,
60
60
  limitInput: limitInput,
61
+ cdr3Sequences: args.cdr3Sequences,
61
62
 
62
63
  params: smart.createJsonResource({
63
64
  blockId: blockId,
@@ -22,6 +22,7 @@ self.awaitState("InputsLocked")
22
22
  self.awaitState("params", "ResourceReady")
23
23
  self.awaitState("inputSpec", "ResourceReady")
24
24
  self.awaitState("referenceLibrary", "ResourceReady")
25
+ self.awaitState("cdr3Sequences", "ResourceReady")
25
26
 
26
27
  self.body(func(inputs) {
27
28
 
@@ -86,6 +87,7 @@ self.body(func(inputs) {
86
87
  columnsSpecPerSample := exportSpecs.columnsSpecPerSample
87
88
  columnsSpecPerClonotypeNoAggregates := exportSpecs.columnsSpecPerClonotypeNoAggregates
88
89
  columnsSpecPerClonotypeAggregates := exportSpecs.columnsSpecPerClonotypeAggregates
90
+ cdr3DistanceColumnsSpec := exportSpecs.cdr3DistanceColumnsSpec
89
91
  clonotypeKeyColumns := exportSpecs.clonotypeKeyColumns
90
92
  clonotypeKeyArgs := exportSpecs.clonotypeKeyArgs
91
93
  exportArgs := exportSpecs.exportArgs
@@ -294,6 +296,18 @@ self.body(func(inputs) {
294
296
  cpu: 2,
295
297
  name: "aggregates",
296
298
  path: ["tsv"]
299
+ }, {
300
+ type: "Xsv",
301
+ xsvType: "tsv",
302
+ settings: {
303
+ axes: axesByClonotypeKeyWithChain,
304
+ columns: cdr3DistanceColumnsSpec,
305
+ storageFormat: "Parquet"
306
+ },
307
+ mem: "8GB",
308
+ cpu: 1,
309
+ name: "cdr3Distances",
310
+ path: ["cdr3DistancesTsv"]
297
311
  } ]
298
312
 
299
313
  aggregationResults := pframes.processColumn(
@@ -310,7 +324,9 @@ self.body(func(inputs) {
310
324
  mainAbundanceColumnUnnormalized: mainAbundanceColumnUnnormalized,
311
325
  schemaPerClonotypeNoAggregates: columnsToSchema(columnsSpecPerClonotypeNoAggregates),
312
326
  schemaPerClonotypeAggregates: columnsToSchema(columnsSpecPerClonotypeAggregates),
313
- schemaPerSample: columnsToSchema(columnsSpecPerSample)
327
+ schemaPerSample: columnsToSchema(columnsSpecPerSample),
328
+ cdr3Sequences: inputs.cdr3Sequences,
329
+ cdr3DistanceColumnsSpec: cdr3DistanceColumnsSpec
314
330
  }
315
331
  }
316
332
  }
@@ -320,6 +336,7 @@ self.body(func(inputs) {
320
336
  clones := pframes.pFrameBuilder()
321
337
  exportResults.addXsvOutputToBuilder(clones, "byCloneKeyBySample", "clonotypeProperties/bySample/" + chains + "/")
322
338
  aggregationResults.addXsvOutputToBuilder(clones, "aggregates", "clonotypeProperties/aggregates/" + chains + "/")
339
+ aggregationResults.addXsvOutputToBuilder(clones, "cdr3Distances", "clonotypeProperties/cdr3Distances/" + chains + "/")
323
340
 
324
341
  qcReportTable := render.create(exportReportTpl, {
325
342
  clnsData: mixcrResults.outputData("clns"),
package/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- declare type TemplateFromFile = { readonly type: "from-file"; readonly path: string; };
2
- declare type TplName = "main";
3
- declare const Templates: Record<TplName, TemplateFromFile>;
4
- export { Templates };
package/index.js DELETED
@@ -1,3 +0,0 @@
1
- module.exports = { Templates: {
2
- 'main': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/main.plj.gz') }
3
- }}
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2022",
4
- "module": "commonjs",
5
- "moduleResolution": "node",
6
- "esModuleInterop": true,
7
- "strict": true,
8
- "outDir": "./dist",
9
- "rootDir": "./src",
10
- "sourceMap": true,
11
- "declaration": true
12
- },
13
- "types": [],
14
- "include": ["src/**/*"],
15
- "exclude": ["node_modules", "dist"]
16
- }
package/vitest.config.mts DELETED
@@ -1,9 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- watch: false,
6
- maxConcurrency: 3,
7
- testTimeout: 5000
8
- }
9
- });