@platforma-open/milaboratories.mixcr-amplicon-alignment.workflow 1.0.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.
@@ -0,0 +1,27 @@
1
+  WARN  Issue while reading "/home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
+
3
+ > @platforma-open/milaboratories.mixcr-amplicon-alignment.workflow@1.0.0 build /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow
4
+ > rm -rf dist && pl-tengo check && pl-tengo build
5
+
6
+ info: Skipping unknown file type: wf.test.ts
7
+ Processing "src/aggregate-by-clonotype-key.tpl.tengo"...
8
+ Processing "src/calculate-export-specs.lib.tengo"...
9
+ Processing "src/clonotype-label.lib.tengo"...
10
+ Processing "src/main.tpl.tengo"...
11
+ Processing "src/mixcr-analyze.tpl.tengo"...
12
+ Processing "src/mixcr-export.tpl.tengo"...
13
+ Processing "src/process.tpl.tengo"...
14
+ Processing "src/repseqio-library.tpl.tengo"...
15
+ No syntax errors found.
16
+ info: Skipping unknown file type: wf.test.ts
17
+ info: Compiling 'dist'...
18
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/lib/calculate-export-specs.lib.tengo
19
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/lib/clonotype-label.lib.tengo
20
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/tpl/aggregate-by-clonotype-key.plj.gz
21
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/tpl/mixcr-analyze.plj.gz
22
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/tpl/mixcr-export.plj.gz
23
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/tpl/process.plj.gz
24
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/tpl/repseqio-library.plj.gz
25
+ info: - writing /home/runner/work/mixcr-amplicon-alignment/mixcr-amplicon-alignment/workflow/dist/tengo/tpl/main.plj.gz
26
+ info: Template Pack build done.
27
+ info: Template Pack build done.
package/dist/index.cjs ADDED
@@ -0,0 +1,8 @@
1
+ module.exports = { Templates: {
2
+ 'aggregate-by-clonotype-key': { type: 'from-file', path: require.resolve('./tengo/tpl/aggregate-by-clonotype-key.plj.gz') },
3
+ 'mixcr-analyze': { type: 'from-file', path: require.resolve('./tengo/tpl/mixcr-analyze.plj.gz') },
4
+ 'mixcr-export': { type: 'from-file', path: require.resolve('./tengo/tpl/mixcr-export.plj.gz') },
5
+ 'process': { type: 'from-file', path: require.resolve('./tengo/tpl/process.plj.gz') },
6
+ 'repseqio-library': { type: 'from-file', path: require.resolve('./tengo/tpl/repseqio-library.plj.gz') },
7
+ 'main': { type: 'from-file', path: require.resolve('./tengo/tpl/main.plj.gz') }
8
+ }};
@@ -0,0 +1,4 @@
1
+ declare type TemplateFromFile = { readonly type: "from-file"; readonly path: string; };
2
+ declare type TplName = "aggregate-by-clonotype-key" | "mixcr-analyze" | "mixcr-export" | "process" | "repseqio-library" | "main";
3
+ declare const Templates: Record<TplName, TemplateFromFile>;
4
+ export { Templates };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { resolve } from 'node:path';
2
+ export const Templates = {
3
+ 'aggregate-by-clonotype-key': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/aggregate-by-clonotype-key.plj.gz') },
4
+ 'mixcr-analyze': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/mixcr-analyze.plj.gz') },
5
+ 'mixcr-export': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/mixcr-export.plj.gz') },
6
+ 'process': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/process.plj.gz') },
7
+ 'repseqio-library': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/repseqio-library.plj.gz') },
8
+ 'main': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/main.plj.gz') }
9
+ };
@@ -0,0 +1,551 @@
1
+ maps := import("@platforma-sdk/workflow-tengo:maps")
2
+ slices := import("@platforma-sdk/workflow-tengo:slices")
3
+ ll := import("@platforma-sdk/workflow-tengo:ll")
4
+ text := import("text")
5
+ json := import("json")
6
+
7
+ a := func(order, defaultVisibility, spec) {
8
+ return maps.merge(spec, {
9
+ "pl7.app/table/orderPriority": string(order),
10
+ "pl7.app/table/visibility": is_undefined(defaultVisibility) ? "hidden" : defaultVisibility ? "default" : "optional"
11
+ })
12
+ }
13
+
14
+
15
+
16
+
17
+
18
+ inFrameFeatures := {
19
+ "FR4": "FR4InFrame",
20
+ "VDJRegion": "VDJRegionInFrame"
21
+ }
22
+
23
+ annotationMappings := {
24
+ "CDRs": "{\"1\":\"CDR1\",\"2\":\"CDR2\",\"3\":\"CDR3\"}",
25
+ "Segments": "{\"1\":\"V\",\"2\":\"D\",\"3\":\"J\",\"4\":\"C\"}"
26
+ }
27
+
28
+ toCombinedDomainValue := func(spec) {
29
+ result := [spec.name]
30
+
31
+ for domain in maps.getKeys(spec.domain) {
32
+ result = append(result, [domain, spec.domain[domain]])
33
+ }
34
+ return result
35
+ }
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+ assemblingFeature := "VDJRegion"
50
+ productiveFeature := "VDJRegionInFrame"
51
+ coreVFeature := "{FR1Begin:FR3End}"
52
+ coreJFeature := "FR4"
53
+ splitByC := false
54
+
55
+
56
+ formatId := func(input) {
57
+ noNums := text.re_replace(`\(\s*-?\d+(\s*,\s*-?\d+)*\s*\)`, input, "")
58
+ noBraces := text.re_replace(`[{}\(\)]`, noNums, "")
59
+ result := text.re_replace(`:`, noBraces, "-")
60
+ return result
61
+ }
62
+
63
+ addSpec := func(columns, additionalSpec) {
64
+ return slices.map(columns, func(columnSpec) {
65
+ return maps.deepMerge(columnSpec, additionalSpec)
66
+ })
67
+ }
68
+
69
+ calculateExportSpecs := func(presetSpecForBack, blockId) {
70
+
71
+ assemblingFeature := "VDJRegion" // Hardcoded to VDJRegion
72
+ splitByC := false
73
+
74
+ productiveFeature := "VDJRegionInFrame"
75
+ coreGeneFeatures := {
76
+ V: "{FR1Begin:FR3End}",
77
+ J: "FR4"
78
+ }
79
+
80
+
81
+ anchorFeature := "VDJRegion"
82
+
83
+ features := ["CDR1", "FR1", "FR2", "CDR2", "FR3", "CDR3", "FR4", "VDJRegion"]
84
+
85
+ clonotypeKeyColumns := ["nSeqVDJRegion", "bestVGene", "bestJGene"]
86
+ clonotypeKeyArgs := [
87
+ [ "-nFeature", "VDJRegion" ],
88
+ [ "-vGene" ],
89
+ [ "-jGene" ]
90
+ ]
91
+ if splitByC {
92
+ clonotypeKeyColumns += ["bestCGene"]
93
+ clonotypeKeyArgs += [ [ "-cGene" ] ]
94
+ }
95
+
96
+ columnsSpecPerSample := []
97
+ columnsSpecPerClonotypeNoAggregates := []
98
+
99
+ clonotypeLabelColumn := {
100
+ column: "clonotypeLabel",
101
+ id: "clonotype-label",
102
+ spec: {
103
+ name: "pl7.app/label",
104
+ valueType: "String",
105
+ annotations: a(100000, false, {
106
+ "pl7.app/label": "Clone label"
107
+ })
108
+ }
109
+ }
110
+ columnsSpecPerClonotypeNoAggregates += [ clonotypeLabelColumn ]
111
+
112
+
113
+ exportArgs := []
114
+
115
+
116
+
117
+ columnsSpecPerSample += [ {
118
+ column: "readCount",
119
+ id: "read-count",
120
+ allowNA: false,
121
+ spec: {
122
+ name: "pl7.app/vdj/readCount",
123
+ valueType: "Long",
124
+ annotations: a(90000, true, {
125
+ "pl7.app/min": "1",
126
+ "pl7.app/isAbundance": "true",
127
+ "pl7.app/abundance/unit": "reads",
128
+ "pl7.app/abundance/normalized": "false",
129
+ "pl7.app/abundance/isPrimary": "true",
130
+ "pl7.app/isAnchor": "true",
131
+ "pl7.app/label": "Number Of Reads"
132
+ })
133
+ }
134
+ }, {
135
+ column: "readFraction",
136
+ id: "read-fraction",
137
+ allowNA: false,
138
+ spec: {
139
+ name: "pl7.app/vdj/readFraction",
140
+ valueType: "Double",
141
+ annotations: a(89000, true, {
142
+ "pl7.app/min": "0",
143
+ "pl7.app/max": "1",
144
+ "pl7.app/isAbundance": "true",
145
+ "pl7.app/abundance/unit": "reads",
146
+ "pl7.app/abundance/normalized": "true",
147
+ "pl7.app/abundance/isPrimary": "true",
148
+ "pl7.app/label": "Fraction of reads",
149
+ "pl7.app/format": ".2p"
150
+ })
151
+ }
152
+ } ]
153
+ exportArgs += [
154
+ [ "-readCount" ],
155
+ [ "-readFraction" ]
156
+ ]
157
+
158
+ mainAbundanceColumnUnnormalized := "readCount"
159
+ mainAbundanceColumnNormalized := "readFraction"
160
+ mainAbundanceColumnUnnormalizedArgs := [ [ "-readCount" ] ]
161
+ mainAbundanceColumnNormalizedArgs := [ [ "-readFraction" ] ]
162
+
163
+ columnsSpecPerClonotypeAggregates := [{
164
+ column: mainAbundanceColumnUnnormalized + "Sum",
165
+ id: "read-count-total",
166
+ allowNA: false,
167
+ spec: {
168
+ name: "pl7.app/vdj/readCountTotal",
169
+ valueType: "Int",
170
+ annotations: a(87120, true, {
171
+ "pl7.app/min": "1",
172
+ "pl7.app/isAbundance": "true",
173
+ "pl7.app/abundance/unit": "reads",
174
+ "pl7.app/abundance/normalized": "false",
175
+ "pl7.app/label": "Supporting Reads"
176
+ })
177
+ }
178
+ }, {
179
+ column: mainAbundanceColumnNormalized + "Mean",
180
+ id: "read-fraction-mean",
181
+ allowNA: false,
182
+ spec: {
183
+ name: "pl7.app/vdj/readFractionMean",
184
+ valueType: "Double",
185
+ annotations: a(87130, true, {
186
+ "pl7.app/min": "0",
187
+ "pl7.app/max": "1",
188
+ "pl7.app/isAbundance": "true",
189
+ "pl7.app/abundance/unit": "reads",
190
+ "pl7.app/abundance/normalized": "true",
191
+ "pl7.app/label": "Mean Fraction of Reads",
192
+ "pl7.app/format": ".2p"
193
+ })
194
+ }
195
+ }]
196
+
197
+ sampleCountColumn := {
198
+ column: "sampleCount",
199
+ id: "sample-count",
200
+ allowNA: false,
201
+ spec: {
202
+ name: "pl7.app/vdj/sampleCount",
203
+ valueType: "Int",
204
+ annotations: a(87110, true, {
205
+ "pl7.app/min": "1",
206
+ "pl7.app/isAbundance": "true",
207
+ "pl7.app/abundance/unit": "samples",
208
+ "pl7.app/abundance/normalized": "false",
209
+ "pl7.app/label": "Number of Samples"
210
+ })
211
+ }
212
+ }
213
+
214
+ columnsSpecPerClonotypeAggregates += [ sampleCountColumn ]
215
+
216
+ orderP := 80000
217
+
218
+
219
+
220
+
221
+
222
+ annotationTypes := ["CDRs", "Segments"]
223
+
224
+ inFrameFeatures := {
225
+ "FR4": "FR4InFrame",
226
+ "VDJRegion": "VDJRegionInFrame"
227
+ }
228
+
229
+ for featureU in features {
230
+ featureL := text.to_lower(formatId(featureU))
231
+ for isAminoAcid in [true, false] {
232
+ featureInFrameU := isAminoAcid ? inFrameFeatures[featureU] : featureU
233
+ if is_undefined(featureInFrameU) {
234
+ featureInFrameU = featureU
235
+ }
236
+ featureInFrameL := text.to_lower(formatId(featureInFrameU))
237
+
238
+ alphabet := isAminoAcid ? "aminoacid" : "nucleotide"
239
+ alphabetShort := isAminoAcid ? "aa" : "nt"
240
+ alphabetShortMixcr := isAminoAcid ? "aa" : "n"
241
+ columnName := alphabetShortMixcr + "Seq" + featureInFrameU
242
+ visibility := featureU == "VDJRegion" || featureU == "CDR3"
243
+ columnsSpecPerClonotypeNoAggregates += [ {
244
+ column: columnName,
245
+ id: alphabetShortMixcr + "-seq-" + featureInFrameL,
246
+ naRegex: "region_not_covered",
247
+ spec: {
248
+ name: "pl7.app/vdj/sequence",
249
+ valueType: "String",
250
+ domain: {
251
+ "pl7.app/vdj/feature": featureInFrameU,
252
+ "pl7.app/alphabet": alphabet
253
+ },
254
+ annotations: a(orderP, visibility, {
255
+ "pl7.app/vdj/isAssemblingFeature": featureU == anchorFeature ? "true" : "false",
256
+ "pl7.app/vdj/isMainSequence": featureU == anchorFeature ? "true" : "false",
257
+ "pl7.app/vdj/imputed": "false",
258
+ "pl7.app/table/fontFamily": "monospace",
259
+ "pl7.app/label": featureInFrameU + " " + alphabetShort
260
+ })
261
+ }
262
+ } ]
263
+ exportArgs += [ [ "-" + alphabetShortMixcr + "Feature", featureInFrameU ] ]
264
+ orderP -= 100
265
+
266
+
267
+ if featureU == assemblingFeature {
268
+ for annotationType in annotationTypes {
269
+ columnName := alphabetShortMixcr + "AnnotationOf" + annotationType + "For" + featureInFrameU
270
+ columnsSpecPerClonotypeNoAggregates += [ {
271
+ column: columnName,
272
+ id: alphabetShortMixcr + "-annotation-" + annotationType + "-" + featureInFrameL,
273
+ naRegex: "region_not_covered",
274
+ spec: {
275
+ name: "pl7.app/vdj/sequence/annotation",
276
+ valueType: "String",
277
+ domain: {
278
+ "pl7.app/vdj/feature": featureInFrameU,
279
+ "pl7.app/alphabet": alphabet,
280
+ "pl7.app/sequence/annotation/type": annotationType
281
+ },
282
+ annotations: a(orderP, undefined, {
283
+ "pl7.app/label": annotationType + " annotation for " + featureInFrameU + " " + alphabetShort,
284
+ "pl7.app/sequence/annotation/mapping": annotationMappings[annotationType],
285
+ "pl7.app/sequence/isAnnotation": "true"
286
+ })
287
+ }
288
+ } ]
289
+ exportArgs += [ [ "-" + alphabetShortMixcr + "AnnotationString", annotationType, featureInFrameU ] ]
290
+ orderP -= 100
291
+ }
292
+ }
293
+
294
+
295
+ if featureU == "CDR3" {
296
+ columnsSpecPerClonotypeNoAggregates += [ {
297
+ column: alphabetShortMixcr + "Length" + featureU,
298
+ id: alphabetShortMixcr + "-length-" + featureL,
299
+ naRegex: "region_not_covered",
300
+ spec: {
301
+ name: "pl7.app/vdj/sequenceLength",
302
+ valueType: "Int",
303
+ domain: {
304
+ "pl7.app/vdj/feature": featureU,
305
+ "pl7.app/alphabet": alphabet
306
+ },
307
+ annotations: a(orderP, false, {
308
+ "pl7.app/label": "Length of " + featureU + " " + alphabetShort
309
+ })
310
+ }
311
+ } ]
312
+ exportArgs += [ [ "-" + alphabetShortMixcr + "Length", featureU ] ]
313
+ }
314
+ }
315
+ }
316
+
317
+
318
+
319
+ geneHitColumnVariants := [ {
320
+ name: "pl7.app/vdj/geneHitWithAllele",
321
+ columnNameSuffix: "Hit",
322
+ idSuffix: "-hit-with-allele",
323
+ labelSuffix: " hit with allele",
324
+ argSuffix: "Hit",
325
+ visible: false
326
+ }, {
327
+ name: "pl7.app/vdj/geneHit",
328
+ columnNameSuffix: "Gene",
329
+ idSuffix: "-gene",
330
+ labelSuffix: " gene",
331
+ argSuffix: "Gene",
332
+ visible: true
333
+ } ]
334
+ for vdjcU in ["V", "D", "J", "C"] {
335
+ vdjcL := text.to_lower(vdjcU)
336
+ for variant in geneHitColumnVariants {
337
+ columnsSpecPerClonotypeNoAggregates += [ {
338
+ column: "best" + vdjcU + variant.columnNameSuffix,
339
+ id: "best-" + vdjcL + variant.idSuffix,
340
+ naRegex: "",
341
+ allowNA: vdjcU == "C" || vdjcU == "D",
342
+ spec: {
343
+ name: variant.name,
344
+ valueType: "String",
345
+ domain: {
346
+ "pl7.app/vdj/reference": vdjcU + "Gene"
347
+ },
348
+ annotations: a(orderP, variant.visible, {
349
+ "pl7.app/label": "Best " + vdjcU + variant.labelSuffix,
350
+ "pl7.app/isDiscreteFilter": "true"
351
+ })
352
+ }
353
+ } ]
354
+ exportArgs += [ [ "-" + vdjcL + variant.argSuffix ] ]
355
+ orderP -= 100
356
+ }
357
+ }
358
+
359
+
360
+
361
+ orderP = 10000
362
+
363
+ mutationColumnVariants := [
364
+ {
365
+ name: "MutationsCount",
366
+ valueType: "Int",
367
+ labelPart: " mutations count in ",
368
+ idPart: "-mutations-count-"
369
+ }, {
370
+ name: "MutationsRate",
371
+ valueType: "Double",
372
+ labelPart: " mutations rate in ",
373
+ idPart: "-mutations-rate-"
374
+ } ]
375
+
376
+ for isAminoAcid in [false, true] {
377
+ alphabetShort := isAminoAcid ? "AA" : "Nt"
378
+ alphabetShortMixcr := isAminoAcid ? "aa" : "n"
379
+
380
+
381
+ for geneU in ["V", "J"] {
382
+ geneL := text.to_lower(geneU)
383
+
384
+ coreFeature := coreGeneFeatures[geneU]
385
+ if is_undefined(coreFeature) {
386
+ continue
387
+ }
388
+
389
+ for variant in mutationColumnVariants {
390
+ columnsSpecPerClonotypeNoAggregates += [ {
391
+ column: alphabetShortMixcr + variant.name + coreFeature,
392
+ id: alphabetShortMixcr + variant.idPart + geneL,
393
+ allowNA: true,
394
+ naRegex: "region_not_covered",
395
+ spec: {
396
+ valueType: variant.valueType,
397
+ name: "pl7.app/vdj/sequence/" + alphabetShortMixcr + variant.name,
398
+ domain: {
399
+ "pl7.app/vdj/gene": geneU
400
+ },
401
+ annotations: a(orderP, false, {
402
+ "pl7.app/label": alphabetShort + variant.labelPart + geneU + " gene"
403
+ })
404
+ }
405
+ } ]
406
+ exportArgs += [ [ "-" + alphabetShortMixcr + variant.name, coreFeature ] ]
407
+ orderP -= 100
408
+ }
409
+ }
410
+ }
411
+
412
+
413
+
414
+ flagColumnVariants := [ {
415
+ columnPrefix: "isProductive",
416
+ arg: "-isProductive",
417
+ specName: "pl7.app/vdj/sequence/productive",
418
+ label: "Productive",
419
+ id: "is-productive",
420
+ visibility: false
421
+ }
422
+ ]
423
+ mainIsProductiveColumn := flagColumnVariants[0].columnPrefix + productiveFeature
424
+ mainIsProductiveArgs := [ [ flagColumnVariants[0].arg, productiveFeature ] ]
425
+ for variant in flagColumnVariants {
426
+ columnsSpecPerClonotypeNoAggregates += [ {
427
+ column: variant.columnPrefix + productiveFeature,
428
+ id: variant.id,
429
+ allowNA: false,
430
+ spec: {
431
+ valueType: "String",
432
+ name: variant.specName,
433
+ annotations: a(orderP, variant.visibility, {
434
+ "pl7.app/label": variant.label,
435
+ "pl7.app/isDiscreteFilter": "true",
436
+ "pl7.app/discreteValues": string(json.encode(["True", "False"])) } )
437
+ }
438
+ } ]
439
+ exportArgs += [ [ variant.arg, productiveFeature ] ]
440
+ orderP -= 100
441
+ }
442
+
443
+
444
+
445
+ columnsSpecPerClonotypeNoAggregates += [ {
446
+ column: "isotypePrimary",
447
+ id: "isotype",
448
+ naRegex: "",
449
+ spec: {
450
+ valueType: "String",
451
+ name: "pl7.app/vdj/isotype",
452
+ annotations: a(orderP, true, {
453
+ "pl7.app/label": "IG isotype",
454
+ "pl7.app/isDiscreteFilter": "true"
455
+ })
456
+ }
457
+ }, {
458
+ column: "topChains",
459
+ id: "top-chains",
460
+ naRegex: "",
461
+ allowNA: true,
462
+ spec: {
463
+ valueType: "String",
464
+ name: "pl7.app/vdj/chain",
465
+ annotations: a(orderP, false, {
466
+ "pl7.app/label": "Chain",
467
+ "pl7.app/isDiscreteFilter": "true",
468
+ "pl7.app/discreteValues": "['TRA','TRB','TRG','TRD','IGH','IGK','IGL']"
469
+ })
470
+ }
471
+ } ]
472
+ exportArgs += [
473
+ [ "-isotype", "primary" ],
474
+ [ "-topChains" ]
475
+ ]
476
+
477
+
478
+
479
+
480
+ columnsSpec := columnsSpecPerSample + columnsSpecPerClonotypeNoAggregates + columnsSpecPerClonotypeAggregates
481
+
482
+
483
+ columnsByName := {}
484
+ for columnSpec in columnsSpec {
485
+ columnsByName[columnSpec.column] = columnSpec
486
+ }
487
+
488
+
489
+
490
+ axesByClonotypeKey := undefined
491
+
492
+
493
+ keyStrincture := []
494
+ for keyColumn in clonotypeKeyColumns {
495
+ columnSpec := columnsByName[keyColumn]
496
+ if is_undefined(columnSpec) {
497
+ ll.panic("column " + keyColumn + " does not exist in export")
498
+ }
499
+ keyStrincture += [ toCombinedDomainValue(columnSpec.spec) ]
500
+ }
501
+
502
+
503
+
504
+
505
+
506
+
507
+ axesByClonotypeKey = [ {
508
+ column: "clonotypeKey",
509
+ naRegex: "",
510
+ spec: {
511
+ name: "pl7.app/vdj/clonotypeKey",
512
+ type: "String",
513
+ domain: {
514
+ "pl7.app/vdj/clonotypeKey/structure": string(json.encode(keyStrincture)),
515
+ "pl7.app/vdj/clonotypingRunId": blockId
516
+ },
517
+ annotations: {
518
+ "pl7.app/label": "Clonotype ID",
519
+ "pl7.app/table/fontFamily": "monospace",
520
+ "pl7.app/table/visibility": "default",
521
+ "pl7.app/table/orderPriority": "110000",
522
+ "pl7.app/segmentedBy": string(json.encode(["pl7.app/vdj/clonotypingRunId"]))
523
+ }
524
+ }
525
+ } ]
526
+
527
+ return {
528
+ clonotypeKeyColumns: clonotypeKeyColumns,
529
+ clonotypeKeyArgs: clonotypeKeyArgs,
530
+
531
+ axesByClonotypeKey: axesByClonotypeKey,
532
+
533
+ columnsSpecPerSample: columnsSpecPerSample,
534
+ columnsSpecPerClonotypeNoAggregates: columnsSpecPerClonotypeNoAggregates,
535
+ columnsSpecPerClonotypeAggregates: columnsSpecPerClonotypeAggregates,
536
+
537
+ columnsSpec: columnsSpec,
538
+
539
+ mainAbundanceColumnNormalized: mainAbundanceColumnNormalized,
540
+ mainAbundanceColumnNormalizedArgs: mainAbundanceColumnNormalizedArgs,
541
+ mainAbundanceColumnUnnormalized: mainAbundanceColumnUnnormalized,
542
+ mainAbundanceColumnUnnormalizedArgs: mainAbundanceColumnUnnormalizedArgs,
543
+
544
+ mainIsProductiveColumn: mainIsProductiveColumn,
545
+ mainIsProductiveArgs: mainIsProductiveArgs,
546
+
547
+ exportArgs: exportArgs
548
+ }
549
+ }
550
+
551
+ export calculateExportSpecs