@platforma-open/milaboratories.mixcr-clonotyping-2.workflow 2.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.
- package/.turbo/turbo-build.log +30 -0
- package/.turbo/turbo-test.log +20 -0
- package/CHANGELOG.md +247 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +12 -0
- package/dist/index.mjs +13 -0
- package/dist/tengo/lib/calculate-export-specs.lib.tengo +576 -0
- 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/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.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/format.el +43 -0
- package/package.json +21 -0
- package/scripts/build-static.mjs +4 -0
- package/src/aggregate-by-clonotype-key.tpl.tengo +65 -0
- package/src/calculate-export-specs.lib.tengo +576 -0
- package/src/calculate-preset-info.tpl.tengo +74 -0
- package/src/list-presets.tpl.tengo +26 -0
- package/src/main.tpl.tengo +159 -0
- package/src/mixcr-analyze.tpl.tengo +171 -0
- package/src/mixcr-export.tpl.tengo +77 -0
- package/src/prerun.tpl.tengo +70 -0
- package/src/process.tpl.tengo +337 -0
- package/src/test/columns-calculate.tpl.tengo +16 -0
- package/src/test/columns.test.tpl.tengo +28 -0
- package/src/test/columns.test.ts +146 -0
- package/tsconfig.json +15 -0
- package/vitest.config.mts +10 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// list presets
|
|
2
|
+
|
|
3
|
+
self := import("@platforma-sdk/workflow-tengo:tpl")
|
|
4
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
5
|
+
exec := import("@platforma-sdk/workflow-tengo:exec")
|
|
6
|
+
file := import("@platforma-sdk/workflow-tengo:file")
|
|
7
|
+
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
8
|
+
|
|
9
|
+
self.defineOutputs("presets")
|
|
10
|
+
|
|
11
|
+
mixcrSw := assets.importSoftware("@platforma-open/milaboratories.software-mixcr:low-memory")
|
|
12
|
+
|
|
13
|
+
self.body(func(inputs) {
|
|
14
|
+
listPresets := exec.builder().
|
|
15
|
+
inUiQueue().
|
|
16
|
+
software(mixcrSw).
|
|
17
|
+
secret("MI_LICENSE", "MI_LICENSE").
|
|
18
|
+
arg("listPresetSpecificationsForUI").
|
|
19
|
+
arg("presets.json").
|
|
20
|
+
saveFile("presets.json").
|
|
21
|
+
run()
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
presets: file.exportFile(listPresets.getFile("presets.json"))
|
|
25
|
+
}
|
|
26
|
+
})
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
wf := import("@platforma-sdk/workflow-tengo:workflow")
|
|
2
|
+
|
|
3
|
+
render := import("@platforma-sdk/workflow-tengo:render")
|
|
4
|
+
|
|
5
|
+
maps := import("@platforma-sdk/workflow-tengo:maps")
|
|
6
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
7
|
+
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
8
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
9
|
+
file := import("@platforma-sdk/workflow-tengo:file")
|
|
10
|
+
llPFrames := import("@platforma-sdk/workflow-tengo:pframes.ll")
|
|
11
|
+
pframes := import("@platforma-sdk/workflow-tengo:pframes")
|
|
12
|
+
exec := import("@platforma-sdk/workflow-tengo:exec")
|
|
13
|
+
self := import("@platforma-sdk/workflow-tengo:tpl")
|
|
14
|
+
|
|
15
|
+
json := import("json")
|
|
16
|
+
|
|
17
|
+
calculatePresetInfoTpl := assets.importTemplate(":calculate-preset-info")
|
|
18
|
+
processTpl := assets.importTemplate(":process")
|
|
19
|
+
|
|
20
|
+
wf.setPreRun(assets.importTemplate(":prerun"))
|
|
21
|
+
|
|
22
|
+
wf.prepare(func(args){
|
|
23
|
+
return{
|
|
24
|
+
resolvedLibraryInput: wf.resolve(args.inputLibrary, { errIfMissing: false })
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
wf.body(func(args) {
|
|
29
|
+
// (begin) @TODO To be moved to SDK / Model
|
|
30
|
+
|
|
31
|
+
fileImports := {}
|
|
32
|
+
|
|
33
|
+
importFile := func(importHandle) {
|
|
34
|
+
fromMap := fileImports[importHandle]
|
|
35
|
+
if fromMap == undefined {
|
|
36
|
+
fImport := file.importFile(importHandle)
|
|
37
|
+
fileImports[importHandle] = fImport
|
|
38
|
+
return fImport.file
|
|
39
|
+
} else {
|
|
40
|
+
return fromMap.file
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// (end)
|
|
45
|
+
|
|
46
|
+
blockId := wf.blockId().getDataAsJson()
|
|
47
|
+
|
|
48
|
+
inputRef := args.input
|
|
49
|
+
|
|
50
|
+
preset := args.preset
|
|
51
|
+
|
|
52
|
+
// file or json with preset name
|
|
53
|
+
presetResource := undefined
|
|
54
|
+
|
|
55
|
+
if preset.type == "file" {
|
|
56
|
+
presetResource = importFile(preset.file)
|
|
57
|
+
} else {
|
|
58
|
+
ll.assert(preset.type == "name", "unexpected preset type")
|
|
59
|
+
// whole json, including type
|
|
60
|
+
presetResource = smart.createJsonResource(preset)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
limitInput := args.limitInput
|
|
64
|
+
isLibraryFileGzipped := false
|
|
65
|
+
|
|
66
|
+
library := false
|
|
67
|
+
species := args.species
|
|
68
|
+
libraryImportHandle := undefined
|
|
69
|
+
if !is_undefined(args.resolvedLibraryInput) {
|
|
70
|
+
library = args.resolvedLibraryInput.data
|
|
71
|
+
librarySpec := args.resolvedLibraryInput.spec
|
|
72
|
+
species = librarySpec["annotations"]["pl7.app/species"]
|
|
73
|
+
} else if !is_undefined(args.libraryFile) {
|
|
74
|
+
fImport := file.importFile(args.libraryFile)
|
|
75
|
+
libraryImportHandle = fImport.handle
|
|
76
|
+
library = fImport.file
|
|
77
|
+
species = args.customSpecies
|
|
78
|
+
isLibraryFileGzipped = args.isLibraryFileGzipped
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
input := wf.resolve(inputRef)
|
|
82
|
+
|
|
83
|
+
//ll.print("__THE_LOG__ " +input)
|
|
84
|
+
|
|
85
|
+
presetInfoResult := render.create(calculatePresetInfoTpl, {
|
|
86
|
+
preset: presetResource,
|
|
87
|
+
params: {
|
|
88
|
+
species: species
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
presetContent := presetInfoResult.output("preset", 24 * 60 * 60 * 1000)
|
|
93
|
+
presetSpecForBack := presetInfoResult.output("presetSpecForBack", 24 * 60 * 60 * 1000)
|
|
94
|
+
|
|
95
|
+
// calculating chains
|
|
96
|
+
chains := [
|
|
97
|
+
{ name: "IGH", mixcrChain: "IGH" },
|
|
98
|
+
{ name: "IGKL", mixcrChain: "IGK,IGL" },
|
|
99
|
+
{ name: "TRA", mixcrChain: "TRA" },
|
|
100
|
+
{ name: "TRB", mixcrChain: "TRB" },
|
|
101
|
+
{ name: "TRD", mixcrChain: "TRD" },
|
|
102
|
+
{ name: "TRG", mixcrChain: "TRG" } ]
|
|
103
|
+
|
|
104
|
+
runMixcr := render.createEphemeral(processTpl, {
|
|
105
|
+
inputSpec: input.getFutureInputField("spec"),
|
|
106
|
+
inputData: input.getFutureInputField("data"),
|
|
107
|
+
|
|
108
|
+
preset: presetResource,
|
|
109
|
+
presetSpecForBack: presetSpecForBack,
|
|
110
|
+
presetContent: presetContent,
|
|
111
|
+
|
|
112
|
+
library: library,
|
|
113
|
+
|
|
114
|
+
params: smart.createJsonResource({
|
|
115
|
+
species: species,
|
|
116
|
+
chains: chains,
|
|
117
|
+
limitInput: limitInput,
|
|
118
|
+
blockId: blockId,
|
|
119
|
+
presetCommonName: args.presetCommonName,
|
|
120
|
+
isLibraryFileGzipped: isLibraryFileGzipped
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
exports := {
|
|
125
|
+
qc: {
|
|
126
|
+
spec: runMixcr.output("qc.spec"),
|
|
127
|
+
data: runMixcr.output("qc.data")
|
|
128
|
+
},
|
|
129
|
+
reports: {
|
|
130
|
+
spec: runMixcr.output("reports.spec"),
|
|
131
|
+
data: runMixcr.output("reports.data")
|
|
132
|
+
},
|
|
133
|
+
clones: runMixcr.output("clonotypes"),
|
|
134
|
+
clns: {
|
|
135
|
+
spec: runMixcr.output("clns.spec"),
|
|
136
|
+
data: runMixcr.output("clns.data")
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
outputs := {
|
|
141
|
+
qc: pframes.exportColumnData(runMixcr.output("qc.data")),
|
|
142
|
+
reports: pframes.exportColumnData(runMixcr.output("reports.data")),
|
|
143
|
+
logs: runMixcr.output("logs.data"),
|
|
144
|
+
clonotypes: pframes.exportFrame(runMixcr.output("clonotypes")),
|
|
145
|
+
clns: runMixcr.output("clns.data"),
|
|
146
|
+
fileImports: smart.createMapResource(maps.mapValues(fileImports, func(im) {
|
|
147
|
+
return im.handle
|
|
148
|
+
}))
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if !is_undefined(libraryImportHandle) {
|
|
152
|
+
outputs.libraryImportHandle = libraryImportHandle
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
outputs: outputs,
|
|
157
|
+
exports: exports
|
|
158
|
+
}
|
|
159
|
+
})
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// mixcr analyze
|
|
2
|
+
|
|
3
|
+
self := import("@platforma-sdk/workflow-tengo:tpl")
|
|
4
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
5
|
+
pConstants := import("@platforma-sdk/workflow-tengo:pframes.constants")
|
|
6
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
7
|
+
exec := import("@platforma-sdk/workflow-tengo:exec")
|
|
8
|
+
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
9
|
+
render := import("@platforma-sdk/workflow-tengo:render")
|
|
10
|
+
pframes := import("@platforma-sdk/workflow-tengo:pframes")
|
|
11
|
+
pcolumn := import("@platforma-sdk/workflow-tengo:pframes.pcolumn")
|
|
12
|
+
xsv := import("@platforma-sdk/workflow-tengo:pframes.xsv")
|
|
13
|
+
file := import("@platforma-sdk/workflow-tengo:file")
|
|
14
|
+
times := import("times")
|
|
15
|
+
|
|
16
|
+
json := import("json")
|
|
17
|
+
|
|
18
|
+
self.defineOutputs("qc", "reports", "log", "clns")
|
|
19
|
+
|
|
20
|
+
mixcrSw := assets.importSoftware("@platforma-open/milaboratories.software-mixcr:main")
|
|
21
|
+
|
|
22
|
+
progressPrefix := "[==PROGRESS==]"
|
|
23
|
+
|
|
24
|
+
self.body(func(inputs) {
|
|
25
|
+
inputData := inputs[pConstants.VALUE_FIELD_NAME]
|
|
26
|
+
aggregationAxesNames := inputs[pConstants.AGGREGATION_AXES_NAMES_FIELD_NAME]
|
|
27
|
+
|
|
28
|
+
preset := inputs.preset
|
|
29
|
+
library := inputs.library
|
|
30
|
+
|
|
31
|
+
params := inputs.params
|
|
32
|
+
species := params.species
|
|
33
|
+
limitInput := params.limitInput
|
|
34
|
+
fileExtension := params.fileExtension
|
|
35
|
+
reports := params.reports
|
|
36
|
+
isLibraryFileGzipped := params.isLibraryFileGzipped
|
|
37
|
+
|
|
38
|
+
presetContent := inputs.presetContent.getDataAsJson()
|
|
39
|
+
|
|
40
|
+
if !is_map(presetContent) {
|
|
41
|
+
ll.panic("malformed presetContent %v", presetContent)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
inputDataMeta := inputData.getDataAsJson()
|
|
45
|
+
|
|
46
|
+
hasAssembleContigs := false
|
|
47
|
+
hasAssembleCells := false
|
|
48
|
+
for stage in presetContent.analysisStages {
|
|
49
|
+
if stage == "assembleContigs" {
|
|
50
|
+
hasAssembleContigs = true
|
|
51
|
+
} else if stage == "assembleCells" {
|
|
52
|
+
hasAssembleCells = true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
clnsFileName := "result.clns"
|
|
57
|
+
if hasAssembleContigs {
|
|
58
|
+
clnsFileName = "result.contigs.clns"
|
|
59
|
+
}
|
|
60
|
+
if hasAssembleCells {
|
|
61
|
+
clnsFileName = "result.assembledCells.clns"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
mixcrCmdBuilder := exec.builder().
|
|
65
|
+
printErrStreamToStdout().
|
|
66
|
+
env("MI_PROGRESS_PREFIX", progressPrefix).
|
|
67
|
+
software(mixcrSw).
|
|
68
|
+
secret("MI_LICENSE", "MI_LICENSE").
|
|
69
|
+
arg("analyze")
|
|
70
|
+
|
|
71
|
+
if !is_undefined(limitInput) {
|
|
72
|
+
mixcrCmdBuilder.arg("--limit-input").arg(string(limitInput))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if library {
|
|
76
|
+
mixcrCmdBuilder.arg("--species").arg(species)
|
|
77
|
+
if isLibraryFileGzipped {
|
|
78
|
+
mixcrCmdBuilder.arg("--library").arg("library.json.gz").
|
|
79
|
+
addFile("library.json.gz", library)
|
|
80
|
+
} else {
|
|
81
|
+
mixcrCmdBuilder.arg("--library").arg("library.json").
|
|
82
|
+
addFile("library.json", library)
|
|
83
|
+
}
|
|
84
|
+
} else if !is_undefined(species) {
|
|
85
|
+
species = params.species
|
|
86
|
+
mixcrCmdBuilder.arg("--species").arg(species)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if smart.isResource(preset) /* file */ {
|
|
90
|
+
mixcrCmdBuilder.
|
|
91
|
+
arg("local#input_preset").
|
|
92
|
+
addFile("input_preset.yaml", preset)
|
|
93
|
+
} else {
|
|
94
|
+
ll.assert(!is_undefined(preset.name), "undefined preset name")
|
|
95
|
+
mixcrCmdBuilder.
|
|
96
|
+
arg(preset.name)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if inputDataMeta.keyLength == 0 {
|
|
100
|
+
ll.assert(aggregationAxesNames == [], "unexpected aggregation axes names")
|
|
101
|
+
inputFile := inputData.inputs()["[]"]
|
|
102
|
+
ll.assert(!is_undefined(inputFile), "unexpected agg group structure")
|
|
103
|
+
inputFileName := "input." + fileExtension
|
|
104
|
+
mixcrCmdBuilder.addFile(inputFileName, inputFile)
|
|
105
|
+
mixcrCmdBuilder.arg(inputFileName)
|
|
106
|
+
} else if inputDataMeta.keyLength == 1 {
|
|
107
|
+
ll.assert(aggregationAxesNames == ["pl7.app/sequencing/readIndex"], "unexpected aggregation axes names")
|
|
108
|
+
for sKey, inputFile in inputData.inputs() {
|
|
109
|
+
key := json.decode(sKey)
|
|
110
|
+
if len(key) != 1 {
|
|
111
|
+
ll.panic("malformed key: %v", sKey)
|
|
112
|
+
}
|
|
113
|
+
r := key[0]
|
|
114
|
+
if (r[0] != 'R' && r[0] != "I") || (r[1] != '1' && r[1] != '2') || len(r) != 2 {
|
|
115
|
+
ll.panic("malformed read index: %v", r)
|
|
116
|
+
}
|
|
117
|
+
mixcrCmdBuilder.addFile("input_" + r + "." + fileExtension, inputFile)
|
|
118
|
+
}
|
|
119
|
+
mixcrCmdBuilder.arg("input_{{R}}." + fileExtension)
|
|
120
|
+
} else if inputDataMeta.keyLength == 2 {
|
|
121
|
+
ll.assert(aggregationAxesNames == ["pl7.app/sequencing/lane", "pl7.app/sequencing/readIndex"], "unexpected aggregation axes names")
|
|
122
|
+
for sKey, inputFile in inputData.inputs() {
|
|
123
|
+
key := json.decode(sKey)
|
|
124
|
+
if len(key) != 2 {
|
|
125
|
+
ll.panic("malformed key: %v", sKey)
|
|
126
|
+
}
|
|
127
|
+
lane := key[0]
|
|
128
|
+
r := key[1]
|
|
129
|
+
if (r[0] != 'R' && r[0] != "I") || (r[1] != '1' && r[1] != '2') || len(r) != 2 {
|
|
130
|
+
ll.panic("malformed read index: %v", r)
|
|
131
|
+
}
|
|
132
|
+
if is_undefined(int(lane)) {
|
|
133
|
+
ll.panic("malformed lane: %v", lane)
|
|
134
|
+
}
|
|
135
|
+
mixcrCmdBuilder.addFile("input_L" + lane + "_" + r + "." + fileExtension, inputFile)
|
|
136
|
+
}
|
|
137
|
+
mixcrCmdBuilder.arg("input_L{{n}}_{{R}}." + fileExtension)
|
|
138
|
+
} else {
|
|
139
|
+
ll.panic("too many axes / not supported")
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
mixcrCmdBuilder.arg("result")
|
|
143
|
+
|
|
144
|
+
mixcrCmdBuilder.saveFile("result.qc.json")
|
|
145
|
+
mixcrCmdBuilder.saveFile(clnsFileName)
|
|
146
|
+
|
|
147
|
+
for report in reports {
|
|
148
|
+
mixcrCmdBuilder.saveFile(report.fileJson)
|
|
149
|
+
mixcrCmdBuilder.saveFile(report.fileTxt)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
mixcrCmdBuilder = mixcrCmdBuilder.cache(48 * times.hour)
|
|
153
|
+
mixcrCmd := mixcrCmdBuilder.run()
|
|
154
|
+
|
|
155
|
+
// collecting results
|
|
156
|
+
|
|
157
|
+
reportsMap := pcolumn.resourceMapBuilder( /* keyLength */ 2 )
|
|
158
|
+
for report in reports {
|
|
159
|
+
reportsMap.add([report.id, "json"], mixcrCmd.getFile(report.fileJson))
|
|
160
|
+
reportsMap.add([report.id, "txt"], mixcrCmd.getFile(report.fileTxt))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
result := {
|
|
164
|
+
qc: mixcrCmd.getFile("result.qc.json"),
|
|
165
|
+
log: mixcrCmd.getStdoutStream(),
|
|
166
|
+
reports: reportsMap.build(),
|
|
167
|
+
clns: mixcrCmd.getFile(clnsFileName)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return result
|
|
171
|
+
})
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
self := import("@platforma-sdk/workflow-tengo:tpl")
|
|
3
|
+
pConstants := import("@platforma-sdk/workflow-tengo:pframes.constants")
|
|
4
|
+
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
5
|
+
exec := import("@platforma-sdk/workflow-tengo:exec")
|
|
6
|
+
|
|
7
|
+
json := import("json")
|
|
8
|
+
|
|
9
|
+
self.defineOutputs("tsv")
|
|
10
|
+
|
|
11
|
+
mixcrSw := assets.importSoftware("@platforma-open/milaboratories.software-mixcr:low-memory")
|
|
12
|
+
ptransformSw := assets.importSoftware("@platforma-open/milaboratories.software-ptransform:main")
|
|
13
|
+
|
|
14
|
+
self.body(func(inputs) {
|
|
15
|
+
clnsFile := inputs[pConstants.VALUE_FIELD_NAME]
|
|
16
|
+
|
|
17
|
+
params := inputs.params
|
|
18
|
+
chains := params.chains
|
|
19
|
+
exportArgs := params.exportArgs
|
|
20
|
+
|
|
21
|
+
clonotypeKeyColumns := params.clonotypeKeyColumns
|
|
22
|
+
|
|
23
|
+
// Exporting clones from clns file
|
|
24
|
+
|
|
25
|
+
mixcrCmdBuilder := exec.builder().
|
|
26
|
+
printErrStreamToStdout().
|
|
27
|
+
software(mixcrSw).
|
|
28
|
+
secret("MI_LICENSE", "MI_LICENSE").
|
|
29
|
+
arg("exportClones").
|
|
30
|
+
arg("--dont-split-files").
|
|
31
|
+
arg("--chains").arg(chains)
|
|
32
|
+
|
|
33
|
+
for argGrp in exportArgs {
|
|
34
|
+
for arg in argGrp {
|
|
35
|
+
mixcrCmdBuilder.arg(arg)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
mixcrCmd := mixcrCmdBuilder.
|
|
40
|
+
arg("clones.clns").
|
|
41
|
+
addFile("clones.clns", clnsFile).
|
|
42
|
+
arg("clones.tsv").
|
|
43
|
+
saveFile("clones.tsv").
|
|
44
|
+
run()
|
|
45
|
+
|
|
46
|
+
unprocessedTsv := mixcrCmd.getFile("clones.tsv")
|
|
47
|
+
|
|
48
|
+
if is_undefined(clonotypeKeyColumns) {
|
|
49
|
+
return {
|
|
50
|
+
tsv: unprocessedTsv
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
// Adding clonotypeKey column
|
|
54
|
+
pWorkflow := {
|
|
55
|
+
steps: [ {
|
|
56
|
+
type: "combine_columns_as_json",
|
|
57
|
+
src: clonotypeKeyColumns,
|
|
58
|
+
dst: "clonotypeKey"
|
|
59
|
+
} ]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
aggregateCmd := exec.builder().
|
|
63
|
+
printErrStreamToStdout().
|
|
64
|
+
software(ptransformSw).
|
|
65
|
+
arg("--workflow").arg("wf.json").
|
|
66
|
+
writeFile("wf.json", json.encode(pWorkflow)).
|
|
67
|
+
arg("input.tsv").addFile("input.tsv", unprocessedTsv).
|
|
68
|
+
arg("output.tsv").saveFile("output.tsv").
|
|
69
|
+
run()
|
|
70
|
+
|
|
71
|
+
processedTsv := aggregateCmd.getFile("output.tsv")
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
tsv: processedTsv
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// pre-run
|
|
2
|
+
|
|
3
|
+
wf := import("@platforma-sdk/workflow-tengo:workflow")
|
|
4
|
+
maps := import("@platforma-sdk/workflow-tengo:maps")
|
|
5
|
+
render := import("@platforma-sdk/workflow-tengo:render")
|
|
6
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
7
|
+
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
8
|
+
assets := import("@platforma-sdk/workflow-tengo:assets")
|
|
9
|
+
file := import("@platforma-sdk/workflow-tengo:file")
|
|
10
|
+
|
|
11
|
+
listPresetsTpl := assets.importTemplate(":list-presets")
|
|
12
|
+
calculatePresetInfoTpl := assets.importTemplate(":calculate-preset-info")
|
|
13
|
+
|
|
14
|
+
wf.body(func(args) {
|
|
15
|
+
|
|
16
|
+
// (begin) @TODO To be moved to SDK / Model
|
|
17
|
+
|
|
18
|
+
fileImports := {}
|
|
19
|
+
|
|
20
|
+
importFile := func(importHandle) {
|
|
21
|
+
fromMap := fileImports[importHandle]
|
|
22
|
+
if fromMap == undefined {
|
|
23
|
+
fImport := file.importFile(importHandle)
|
|
24
|
+
fileImports[importHandle] = fImport
|
|
25
|
+
return fImport.file
|
|
26
|
+
} else {
|
|
27
|
+
return fromMap.file
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// (end)
|
|
32
|
+
|
|
33
|
+
outputs := {}
|
|
34
|
+
|
|
35
|
+
listPresets := render.create(listPresetsTpl, {})
|
|
36
|
+
outputs.presets = listPresets.output("presets", 24 * 60 * 60 * 1000)
|
|
37
|
+
|
|
38
|
+
if !is_undefined(args.preset) {
|
|
39
|
+
|
|
40
|
+
preset := args.preset
|
|
41
|
+
|
|
42
|
+
// file or json with preset name
|
|
43
|
+
presetResource := undefined
|
|
44
|
+
|
|
45
|
+
if preset.type == "file" {
|
|
46
|
+
//presetResource = importFile(preset.file)
|
|
47
|
+
presetResource = undefined
|
|
48
|
+
} else {
|
|
49
|
+
ll.assert(preset.type == "name", "unexpected preset type")
|
|
50
|
+
// whole json, including type
|
|
51
|
+
presetResource = smart.createJsonResource(preset)
|
|
52
|
+
presetInfoResult := render.create(calculatePresetInfoTpl, {
|
|
53
|
+
preset: presetResource,
|
|
54
|
+
params: {
|
|
55
|
+
species: args.species
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
outputs.preset = presetInfoResult.output("presetSpecForBack", 24 * 60 * 60 * 1000)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
outputs.fileImports = smart.createMapResource(maps.mapValues(fileImports, func(im) {
|
|
63
|
+
return im.handle
|
|
64
|
+
}))
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
outputs: outputs,
|
|
68
|
+
exports: {}
|
|
69
|
+
}
|
|
70
|
+
})
|