@platforma-open/milaboratories.mixcr-clonotyping-2.workflow 3.26.3 → 3.27.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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/tengo/lib/calculate-export-specs.lib.tengo +103 -5
- package/dist/tengo/tpl/aggregate-by-clonotype-key.plj.gz +0 -0
- package/dist/tengo/tpl/calculate-preset-info.plj.gz +0 -0
- package/dist/tengo/tpl/export-report.plj.gz +0 -0
- package/dist/tengo/tpl/list-presets.plj.gz +0 -0
- package/dist/tengo/tpl/main.plj.gz +0 -0
- package/dist/tengo/tpl/mixcr-analyze.plj.gz +0 -0
- package/dist/tengo/tpl/mixcr-export.plj.gz +0 -0
- package/dist/tengo/tpl/prerun.plj.gz +0 -0
- package/dist/tengo/tpl/process-single-cell.plj.gz +0 -0
- package/dist/tengo/tpl/process.plj.gz +0 -0
- package/dist/tengo/tpl/test.columns-calculate.plj.gz +0 -0
- package/dist/tengo/tpl/test.columns.test.plj.gz +0 -0
- package/package.json +3 -3
- package/src/calculate-export-specs.lib.tengo +103 -5
- package/src/main.tpl.tengo +1 -0
- package/src/mixcr-analyze.tpl.tengo +27 -11
- package/src/process.tpl.tengo +1 -1
- package/src/test/columns-calculate.tpl.tengo +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -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.
|
|
3
|
+
> @platforma-open/milaboratories.mixcr-clonotyping-2.workflow@3.27.1 build /home/runner/work/mixcr-clonotyping/mixcr-clonotyping/workflow
|
|
4
4
|
> shx 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.27.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a297368: Size MiXCR analyze memory from the input reads' file size on top of the per-analysis floor. The per-analysis baseline (64 / 110 / 192 GiB for default / contig-cell / single-cell+MiTool) stays as a floor; memory then grows linearly with the R1+R2 FASTQ blob size (4 bytes of RAM per byte), clamped to 256 GiB. File size is read from blob metadata (getBlobSize) with no pre-exec. The explicit "Advanced Settings" memory override is unchanged; on backends that can't evaluate resource formulas the baseline is the static fallback.
|
|
8
|
+
|
|
9
|
+
## 3.27.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 1ed23a7: Add "Impute non-covered parts from germline" option for generic amplicon presets. When enabled, the block exports additional germline-imputed sequence columns for the gene-feature regions outside the assembling feature span (plus the full VDJRegion), reconstructing non-covered parts from the assigned V/J germline. Imputed sequences are not used for clonotype assembly. The option is shown only for presets that expose "Assemble clones by".
|
|
14
|
+
|
|
3
15
|
## 3.26.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -105,6 +105,71 @@ formatId := func(input) {
|
|
|
105
105
|
return result
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
germlineRegionOrder := ["FR1", "CDR1", "FR2", "CDR2", "FR3", "CDR3", "FR4"]
|
|
111
|
+
|
|
112
|
+
germlineRegionIndex := func(region) {
|
|
113
|
+
for i, r in germlineRegionOrder {
|
|
114
|
+
if r == region {
|
|
115
|
+
return i
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return -1
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
imputedFlankFeatures := func(assembleClonesBy) {
|
|
130
|
+
if is_undefined(assembleClonesBy) || assembleClonesBy == "CDR3" || assembleClonesBy == "VDJRegion" {
|
|
131
|
+
return []
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
begin := undefined
|
|
135
|
+
end := undefined
|
|
136
|
+
|
|
137
|
+
toParts := text.split(assembleClonesBy, "_TO_")
|
|
138
|
+
if len(toParts) == 2 {
|
|
139
|
+
begin = toParts[0]
|
|
140
|
+
end = toParts[1]
|
|
141
|
+
} else if text.has_prefix(assembleClonesBy, "{") && text.has_suffix(assembleClonesBy, "}") {
|
|
142
|
+
inner := assembleClonesBy[1:len(assembleClonesBy) - 1]
|
|
143
|
+
colonParts := text.split(inner, ":")
|
|
144
|
+
if len(colonParts) != 2 {
|
|
145
|
+
return []
|
|
146
|
+
}
|
|
147
|
+
begin = text.replace(colonParts[0], "Begin", "", -1)
|
|
148
|
+
end = text.replace(colonParts[1], "End", "", -1)
|
|
149
|
+
} else {
|
|
150
|
+
return []
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
iBegin := germlineRegionIndex(begin)
|
|
154
|
+
iEnd := germlineRegionIndex(end)
|
|
155
|
+
if iBegin == -1 || iEnd == -1 || iBegin > iEnd {
|
|
156
|
+
return []
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
imputed := []
|
|
160
|
+
for i := 0; i < iBegin; i++ {
|
|
161
|
+
imputed = append(imputed, germlineRegionOrder[i])
|
|
162
|
+
}
|
|
163
|
+
for i := iEnd + 1; i < len(germlineRegionOrder); i++ {
|
|
164
|
+
imputed = append(imputed, germlineRegionOrder[i])
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if !(begin == "FR1" && end == "FR4") {
|
|
168
|
+
imputed = append(imputed, "VDJRegion")
|
|
169
|
+
}
|
|
170
|
+
return imputed
|
|
171
|
+
}
|
|
172
|
+
|
|
108
173
|
exportSpecOpsFromPreset := func(presetSpecForBack) {
|
|
109
174
|
assemblingFeature := undefined
|
|
110
175
|
if !is_undefined(presetSpecForBack.assemblingFeature) {
|
|
@@ -129,7 +194,7 @@ addSpec := func(columns, additionalSpec) {
|
|
|
129
194
|
|
|
130
195
|
|
|
131
196
|
|
|
132
|
-
calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, exportMinQuality) {
|
|
197
|
+
calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, exportMinQuality, imputeGermline, assembleClonesBy) {
|
|
133
198
|
ops := exportSpecOpsFromPreset(presetSpecForBack)
|
|
134
199
|
|
|
135
200
|
assemblingFeature := ops.assemblingFeature
|
|
@@ -137,11 +202,14 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, expor
|
|
|
137
202
|
cellTags := ops.cellTags
|
|
138
203
|
hasUmi := ops.hasUmi
|
|
139
204
|
splitByC := ops.splitByC
|
|
140
|
-
|
|
205
|
+
|
|
141
206
|
|
|
142
207
|
if is_undefined(exportMinQuality) {
|
|
143
208
|
exportMinQuality = false
|
|
144
209
|
}
|
|
210
|
+
if is_undefined(imputeGermline) {
|
|
211
|
+
imputeGermline = false
|
|
212
|
+
}
|
|
145
213
|
|
|
146
214
|
isSingleCell := !is_undefined(cellTags) && len(cellTags) > 0
|
|
147
215
|
hashCellKey := isSingleCell && len(cellTags) > 1
|
|
@@ -496,10 +564,40 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, expor
|
|
|
496
564
|
|
|
497
565
|
annotationTypes := assemblingFeature == "CDR3" ? ["Segments"] : ["CDRs", "Segments"]
|
|
498
566
|
|
|
499
|
-
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
imputedFeatures := imputeGermline ? imputedFlankFeatures(assembleClonesBy) : []
|
|
574
|
+
doImpute := len(imputedFeatures) > 0
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
if doImpute {
|
|
583
|
+
imputedSet := {}
|
|
584
|
+
for f in imputedFeatures {
|
|
585
|
+
imputedSet[f] = true
|
|
586
|
+
}
|
|
587
|
+
nonImputedFeatures := []
|
|
588
|
+
for f in features {
|
|
589
|
+
if is_undefined(imputedSet[f]) {
|
|
590
|
+
nonImputedFeatures = append(nonImputedFeatures, f)
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
features = nonImputedFeatures
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
for isImputed in ( doImpute ? [false, true] : [false] ) {
|
|
500
597
|
imputedU := isImputed ? "Imputed" : ""
|
|
501
598
|
imputedL := text.to_lower(imputedU)
|
|
502
|
-
|
|
599
|
+
featuresList := isImputed ? imputedFeatures : features
|
|
600
|
+
for featureU in featuresList {
|
|
503
601
|
featureL := text.to_lower(formatId(featureU))
|
|
504
602
|
for isAminoAcid in [true, false] {
|
|
505
603
|
featureInFrameU := isAminoAcid ? inFrameFeatures[featureU] : featureU
|
|
@@ -539,7 +637,7 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, expor
|
|
|
539
637
|
"pl7.app/vdj/isMainSequence": featureU == anchorFeature ? "true" : "false",
|
|
540
638
|
"pl7.app/vdj/imputed": string(isImputed),
|
|
541
639
|
"pl7.app/table/fontFamily": "monospace",
|
|
542
|
-
"pl7.app/label": featureInFrameU + " " + alphabetShort
|
|
640
|
+
"pl7.app/label": (isImputed ? "Imputed " : "") + featureInFrameU + " " + alphabetShort
|
|
543
641
|
})
|
|
544
642
|
}
|
|
545
643
|
} ]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-open/milaboratories.mixcr-clonotyping-2.workflow",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.27.1",
|
|
4
4
|
"description": "Tengo-based template",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@platforma-sdk/workflow-tengo": "5.
|
|
6
|
+
"@platforma-sdk/workflow-tengo": "6.5.0",
|
|
7
7
|
"@platforma-open/milaboratories.software-mixcr": "4.7.0-347-develop"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@platforma-sdk/tengo-builder": "
|
|
10
|
+
"@platforma-sdk/tengo-builder": "4.0.9"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "shx rm -rf dist && pl-tengo check && pl-tengo build",
|
|
@@ -105,6 +105,71 @@ formatId := func(input) {
|
|
|
105
105
|
return result
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
// Gene-feature regions in 5'->3' order, used to derive which regions fall outside an
|
|
109
|
+
// assembled span.
|
|
110
|
+
germlineRegionOrder := ["FR1", "CDR1", "FR2", "CDR2", "FR3", "CDR3", "FR4"]
|
|
111
|
+
|
|
112
|
+
germlineRegionIndex := func(region) {
|
|
113
|
+
for i, r in germlineRegionOrder {
|
|
114
|
+
if r == region {
|
|
115
|
+
return i
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return -1
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Derives the gene-feature regions lying OUTSIDE the assembled span (5' and 3' flanks),
|
|
122
|
+
// plus the full VDJRegion, for germline imputation. Mirrors the mixcr-amplicon-alignment
|
|
123
|
+
// block's parseAssemblingFeature, adapted to the "Assemble clones by" value formats:
|
|
124
|
+
// CDR3, VDJRegion -> nothing to impute (minimal / full feature)
|
|
125
|
+
// <X>_TO_<Y> -> span X..Y (e.g. CDR1_TO_FR4)
|
|
126
|
+
// {<X>Begin:<Y>End} -> span X..Y (e.g. {FR1Begin:CDR3End})
|
|
127
|
+
// The assembled span itself is observed, not imputed, so it never gets a duplicate
|
|
128
|
+
// imputed column. Returns [] when there is nothing to impute or the value is unrecognised.
|
|
129
|
+
imputedFlankFeatures := func(assembleClonesBy) {
|
|
130
|
+
if is_undefined(assembleClonesBy) || assembleClonesBy == "CDR3" || assembleClonesBy == "VDJRegion" {
|
|
131
|
+
return []
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
begin := undefined
|
|
135
|
+
end := undefined
|
|
136
|
+
|
|
137
|
+
toParts := text.split(assembleClonesBy, "_TO_")
|
|
138
|
+
if len(toParts) == 2 {
|
|
139
|
+
begin = toParts[0]
|
|
140
|
+
end = toParts[1]
|
|
141
|
+
} else if text.has_prefix(assembleClonesBy, "{") && text.has_suffix(assembleClonesBy, "}") {
|
|
142
|
+
inner := assembleClonesBy[1:len(assembleClonesBy) - 1]
|
|
143
|
+
colonParts := text.split(inner, ":")
|
|
144
|
+
if len(colonParts) != 2 {
|
|
145
|
+
return []
|
|
146
|
+
}
|
|
147
|
+
begin = text.replace(colonParts[0], "Begin", "", -1)
|
|
148
|
+
end = text.replace(colonParts[1], "End", "", -1)
|
|
149
|
+
} else {
|
|
150
|
+
return []
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
iBegin := germlineRegionIndex(begin)
|
|
154
|
+
iEnd := germlineRegionIndex(end)
|
|
155
|
+
if iBegin == -1 || iEnd == -1 || iBegin > iEnd {
|
|
156
|
+
return []
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
imputed := []
|
|
160
|
+
for i := 0; i < iBegin; i++ {
|
|
161
|
+
imputed = append(imputed, germlineRegionOrder[i])
|
|
162
|
+
}
|
|
163
|
+
for i := iEnd + 1; i < len(germlineRegionOrder); i++ {
|
|
164
|
+
imputed = append(imputed, germlineRegionOrder[i])
|
|
165
|
+
}
|
|
166
|
+
// VDJRegion is the full FR1..FR4; impute it unless the span already covers everything.
|
|
167
|
+
if !(begin == "FR1" && end == "FR4") {
|
|
168
|
+
imputed = append(imputed, "VDJRegion")
|
|
169
|
+
}
|
|
170
|
+
return imputed
|
|
171
|
+
}
|
|
172
|
+
|
|
108
173
|
exportSpecOpsFromPreset := func(presetSpecForBack) {
|
|
109
174
|
assemblingFeature := undefined
|
|
110
175
|
if !is_undefined(presetSpecForBack.assemblingFeature) {
|
|
@@ -129,7 +194,7 @@ addSpec := func(columns, additionalSpec) {
|
|
|
129
194
|
// Ordering rules
|
|
130
195
|
// AA Sequences
|
|
131
196
|
|
|
132
|
-
calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, exportMinQuality) {
|
|
197
|
+
calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, exportMinQuality, imputeGermline, assembleClonesBy) {
|
|
133
198
|
ops := exportSpecOpsFromPreset(presetSpecForBack)
|
|
134
199
|
|
|
135
200
|
assemblingFeature := ops.assemblingFeature
|
|
@@ -137,11 +202,14 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, expor
|
|
|
137
202
|
cellTags := ops.cellTags
|
|
138
203
|
hasUmi := ops.hasUmi
|
|
139
204
|
splitByC := ops.splitByC
|
|
140
|
-
|
|
205
|
+
|
|
141
206
|
// Default to false if not provided
|
|
142
207
|
if is_undefined(exportMinQuality) {
|
|
143
208
|
exportMinQuality = false
|
|
144
209
|
}
|
|
210
|
+
if is_undefined(imputeGermline) {
|
|
211
|
+
imputeGermline = false
|
|
212
|
+
}
|
|
145
213
|
|
|
146
214
|
isSingleCell := !is_undefined(cellTags) && len(cellTags) > 0
|
|
147
215
|
hashCellKey := isSingleCell && len(cellTags) > 1
|
|
@@ -496,10 +564,40 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, expor
|
|
|
496
564
|
// aaAnnotationOfSegmentsForVDJRegionInFrame
|
|
497
565
|
annotationTypes := assemblingFeature == "CDR3" ? ["Segments"] : ["CDRs", "Segments"]
|
|
498
566
|
|
|
499
|
-
|
|
567
|
+
// Germline imputation (generic amplicon presets only): when enabled, emit additional
|
|
568
|
+
// germline-imputed sequence columns for the gene-feature regions OUTSIDE the assembled
|
|
569
|
+
// span (plus the full VDJRegion). imputedFlankFeatures returns [] for non-generic presets
|
|
570
|
+
// (assembleClonesBy undefined) and for full/minimal spans, so this never fires outside the
|
|
571
|
+
// intended scope. The clonotype key, built from the non-imputed assembling feature, is
|
|
572
|
+
// unaffected.
|
|
573
|
+
imputedFeatures := imputeGermline ? imputedFlankFeatures(assembleClonesBy) : []
|
|
574
|
+
doImpute := len(imputedFeatures) > 0
|
|
575
|
+
|
|
576
|
+
// Keep the imputed and non-imputed feature sets disjoint (as mixcr-amplicon-alignment does).
|
|
577
|
+
// A flank feature (e.g. FR1) lives in the fixed non-imputed `features` list AND in the imputed
|
|
578
|
+
// set; emitting both yields two columns with identical PColumn identity (name + domain - the
|
|
579
|
+
// `imputed` flag is annotation-only, so it does not disambiguate). The empty non-imputed column
|
|
580
|
+
// (region_not_covered) then shadows the populated germline-imputed one. So when imputing, drop
|
|
581
|
+
// those features from the non-imputed list - only the imputed column remains for the flanks.
|
|
582
|
+
if doImpute {
|
|
583
|
+
imputedSet := {}
|
|
584
|
+
for f in imputedFeatures {
|
|
585
|
+
imputedSet[f] = true
|
|
586
|
+
}
|
|
587
|
+
nonImputedFeatures := []
|
|
588
|
+
for f in features {
|
|
589
|
+
if is_undefined(imputedSet[f]) {
|
|
590
|
+
nonImputedFeatures = append(nonImputedFeatures, f)
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
features = nonImputedFeatures
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
for isImputed in ( doImpute ? [false, true] : [false] ) {
|
|
500
597
|
imputedU := isImputed ? "Imputed" : ""
|
|
501
598
|
imputedL := text.to_lower(imputedU)
|
|
502
|
-
|
|
599
|
+
featuresList := isImputed ? imputedFeatures : features
|
|
600
|
+
for featureU in featuresList {
|
|
503
601
|
featureL := text.to_lower(formatId(featureU))
|
|
504
602
|
for isAminoAcid in [true, false] {
|
|
505
603
|
featureInFrameU := isAminoAcid ? inFrameFeatures[featureU] : featureU
|
|
@@ -539,7 +637,7 @@ calculateExportSpecs := func(presetSpecForBack, sampleIdAxisSpec, blockId, expor
|
|
|
539
637
|
"pl7.app/vdj/isMainSequence": featureU == anchorFeature ? "true" : "false",
|
|
540
638
|
"pl7.app/vdj/imputed": string(isImputed),
|
|
541
639
|
"pl7.app/table/fontFamily": "monospace",
|
|
542
|
-
"pl7.app/label": featureInFrameU + " " + alphabetShort
|
|
640
|
+
"pl7.app/label": (isImputed ? "Imputed " : "") + featureInFrameU + " " + alphabetShort
|
|
543
641
|
})
|
|
544
642
|
}
|
|
545
643
|
} ]
|
package/src/main.tpl.tengo
CHANGED
|
@@ -134,6 +134,7 @@ wf.body(func(args) {
|
|
|
134
134
|
materialType: args.materialType,
|
|
135
135
|
tagPattern: args.tagPattern,
|
|
136
136
|
assembleClonesBy: args.assembleClonesBy,
|
|
137
|
+
imputeGermline: args.imputeGermline,
|
|
137
138
|
exportMinQuality: args.exportMinQuality,
|
|
138
139
|
stopCodonTypes: args.stopCodonTypes,
|
|
139
140
|
stopCodonReplacements: args.stopCodonReplacements
|
|
@@ -86,18 +86,34 @@ self.body(func(inputs) {
|
|
|
86
86
|
mixcrCmdBuilder.cpu(16) // default CPUs number per sample
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
// Memory limit per process
|
|
89
|
+
// Memory limit per process.
|
|
90
|
+
// Size analyze RAM from the input reads' file size, on top of a per-analysis
|
|
91
|
+
// floor. size("reads") sums the stored (compressed) blob size of the sample's
|
|
92
|
+
// R1+R2 FASTQ via getBlobSize — a metadata read, no pre-exec — so it tracks
|
|
93
|
+
// total input volume (read count and read length) without decompressing.
|
|
94
|
+
// mem = clamp(baseMemGiB + 4 bytes/byte * size, baseMemGiB, 256 GiB)
|
|
95
|
+
// baseMemGiB is the per-analysis floor (64, or 110/192 for contig/cell and
|
|
96
|
+
// single-cell+MiTool pipelines, which need that headroom regardless of size);
|
|
97
|
+
// the linear term scales with input volume; the 256 GiB cap bounds the largest.
|
|
98
|
+
// An "Advanced Settings" memory override takes precedence; on backends that
|
|
99
|
+
// cannot evaluate resource formulas, memFormula falls back to the baseline.
|
|
90
100
|
if !is_undefined(perProcessMemGB) {
|
|
91
101
|
// memory per process was set in "Advanced Settings" block directly
|
|
92
102
|
mixcrCmdBuilder.mem(string(perProcessMemGB) + "GiB")
|
|
93
|
-
} else if hasMiToolSteps {
|
|
94
|
-
// allow to use more memory for single cell analysis with mitool pre-
|
|
95
|
-
mixcrCmdBuilder.mem("192GiB")
|
|
96
|
-
} else if hasAssembleContigs || hasAssembleCells {
|
|
97
|
-
// allow to use more memory for single cell analysis
|
|
98
|
-
mixcrCmdBuilder.mem("110GiB")
|
|
99
103
|
} else {
|
|
100
|
-
|
|
104
|
+
baseMemGiB := 64
|
|
105
|
+
if hasMiToolSteps {
|
|
106
|
+
baseMemGiB = 192
|
|
107
|
+
} else if hasAssembleContigs || hasAssembleCells {
|
|
108
|
+
baseMemGiB = 110
|
|
109
|
+
}
|
|
110
|
+
f := exec.formula
|
|
111
|
+
mixcrCmdBuilder.memFormula(
|
|
112
|
+
f.clamp(
|
|
113
|
+
f.add(f.gib(baseMemGiB), f.mul(f.size("reads"), 4)),
|
|
114
|
+
f.gib(baseMemGiB),
|
|
115
|
+
f.gib(256)),
|
|
116
|
+
{ fallback: string(baseMemGiB) + "GiB" })
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
if !is_undefined(limitInput) {
|
|
@@ -166,7 +182,7 @@ self.body(func(inputs) {
|
|
|
166
182
|
inputFile := inputMap["[]"]
|
|
167
183
|
ll.assert(!is_undefined(inputFile), "unexpected agg group structure")
|
|
168
184
|
inputFileName := "input." + fileExtension
|
|
169
|
-
mixcrCmdBuilder.addFile(inputFileName, inputFile)
|
|
185
|
+
mixcrCmdBuilder.addFile(inputFileName, inputFile, { tag: "reads" })
|
|
170
186
|
mixcrCmdBuilder.arg(inputFileName)
|
|
171
187
|
} else if inputDataMeta.keyLength == 1 {
|
|
172
188
|
ll.assert(aggregationAxesNames == ["pl7.app/sequencing/readIndex"], "unexpected aggregation axes names")
|
|
@@ -180,7 +196,7 @@ self.body(func(inputs) {
|
|
|
180
196
|
if (r[0] != 'R' && r[0] != "I") || (r[1] != '1' && r[1] != '2') || len(r) != 2 {
|
|
181
197
|
ll.panic("malformed read index: %v", r)
|
|
182
198
|
}
|
|
183
|
-
mixcrCmdBuilder.addFile("input_" + r + "." + fileExtension, inputFile)
|
|
199
|
+
mixcrCmdBuilder.addFile("input_" + r + "." + fileExtension, inputFile, { tag: "reads" })
|
|
184
200
|
}
|
|
185
201
|
mixcrCmdBuilder.arg("input_{{R}}." + fileExtension)
|
|
186
202
|
} else if inputDataMeta.keyLength == 2 {
|
|
@@ -199,7 +215,7 @@ self.body(func(inputs) {
|
|
|
199
215
|
if is_undefined(int(lane)) {
|
|
200
216
|
ll.panic("malformed lane: %v", lane)
|
|
201
217
|
}
|
|
202
|
-
mixcrCmdBuilder.addFile("input_L" + lane + "_" + r + "." + fileExtension, inputFile)
|
|
218
|
+
mixcrCmdBuilder.addFile("input_L" + lane + "_" + r + "." + fileExtension, inputFile, { tag: "reads" })
|
|
203
219
|
}
|
|
204
220
|
mixcrCmdBuilder.arg("input_L{{n}}_{{R}}." + fileExtension)
|
|
205
221
|
} else {
|
package/src/process.tpl.tengo
CHANGED
|
@@ -203,7 +203,7 @@ self.body(func(inputs) {
|
|
|
203
203
|
}
|
|
204
204
|
} ]
|
|
205
205
|
|
|
206
|
-
exportSpecs := calculateExportSpecs(presetSpecForBack, sampleIdAxisSpec, blockId, params.exportMinQuality)
|
|
206
|
+
exportSpecs := calculateExportSpecs(presetSpecForBack, sampleIdAxisSpec, blockId, params.exportMinQuality, params.imputeGermline, params.assembleClonesBy)
|
|
207
207
|
|
|
208
208
|
columnsSpecPerSample := exportSpecs.columnsSpecPerSample
|
|
209
209
|
columnsSpecPerSampleSc := exportSpecs.columnsSpecPerSampleSc
|
|
@@ -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", false)
|
|
12
|
+
exportSpecs := calculateExportSpecs(presetSpecForBack, {}, "test", false, false, undefined)
|
|
13
13
|
exportSpecs = maps.deepMerge(exportSpecs, {
|
|
14
14
|
axisByClonotypeKeyGen: undefined,
|
|
15
15
|
axisByScClonotypeKeyGen: undefined,
|