@platforma-open/milaboratories.mixcr-shm-trees.workflow 3.5.1 → 3.6.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,5 +1,6 @@
1
+  WARN  Issue while reading "/home/runner/work/mixcr-shm-trees/mixcr-shm-trees/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
1
2
 
2
- > @platforma-open/milaboratories.mixcr-shm-trees.workflow@3.5.1 build /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow
3
+ > @platforma-open/milaboratories.mixcr-shm-trees.workflow@3.6.0 build /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow
3
4
  > rm -rf dist && pl-tengo check && pl-tengo build
4
5
 
5
6
  Processing "src/export-settings.lib.tengo"...
@@ -7,6 +8,7 @@ Processing "src/main.tpl.tengo"...
7
8
  Processing "src/prepare-donor-column.lib.tengo"...
8
9
  Processing "src/process.tpl.tengo"...
9
10
  Processing "src/reconstruct-shm-trees.tpl.tengo"...
11
+ Processing "src/request-library.tpl.tengo"...
10
12
  Processing "src/soi-export.lib.tengo"...
11
13
  Processing "src/soi.tpl.tengo"...
12
14
  Processing "src/tablesAggregation.lib.tengo"...
@@ -17,8 +19,9 @@ No syntax errors found.
17
19
  info: - writing /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow/dist/tengo/lib/soi-export.lib.tengo
18
20
  info: - writing /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow/dist/tengo/lib/tablesAggregation.lib.tengo
19
21
  info: - writing /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow/dist/tengo/tpl/reconstruct-shm-trees.plj.gz
22
+ info: - writing /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow/dist/tengo/tpl/request-library.plj.gz
20
23
  info: - writing /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow/dist/tengo/tpl/soi.plj.gz
21
24
  info: - writing /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow/dist/tengo/tpl/process.plj.gz
22
25
  info: - writing /home/runner/work/mixcr-shm-trees/mixcr-shm-trees/workflow/dist/tengo/tpl/main.plj.gz
23
- info:
26
+ info: Template Pack build done.
24
27
  info: Template Pack build done.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @platforma-open/milaboratories.mixcr-shm-trees.workflow
2
2
 
3
+ ## 3.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b8af059: SDK Upgrade
8
+ - b8af059: Custom library support
9
+
3
10
  ## 3.5.1
4
11
 
5
12
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  module.exports = { Templates: {
2
2
  'reconstruct-shm-trees': { type: 'from-file', path: require.resolve('./tengo/tpl/reconstruct-shm-trees.plj.gz') },
3
+ 'request-library': { type: 'from-file', path: require.resolve('./tengo/tpl/request-library.plj.gz') },
3
4
  'soi': { type: 'from-file', path: require.resolve('./tengo/tpl/soi.plj.gz') },
4
5
  'process': { type: 'from-file', path: require.resolve('./tengo/tpl/process.plj.gz') },
5
6
  'main': { type: 'from-file', path: require.resolve('./tengo/tpl/main.plj.gz') }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  declare type TemplateFromFile = { readonly type: "from-file"; readonly path: string; };
2
- declare type TplName = "reconstruct-shm-trees" | "soi" | "process" | "main";
2
+ declare type TplName = "reconstruct-shm-trees" | "request-library" | "soi" | "process" | "main";
3
3
  declare const Templates: Record<TplName, TemplateFromFile>;
4
4
  export { Templates };
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { resolve } from 'node:path';
2
2
  export const Templates = {
3
3
  'reconstruct-shm-trees': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/reconstruct-shm-trees.plj.gz') },
4
+ 'request-library': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/request-library.plj.gz') },
4
5
  'soi': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/soi.plj.gz') },
5
6
  'process': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/process.plj.gz') },
6
7
  'main': { type: 'from-file', path: resolve(import.meta.dirname, './tengo/tpl/main.plj.gz') }
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,23 +1,21 @@
1
1
  {
2
2
  "name": "@platforma-open/milaboratories.mixcr-shm-trees.workflow",
3
- "version": "3.5.1",
3
+ "version": "3.6.0",
4
4
  "type": "module",
5
5
  "description": "Tengo-based template",
6
6
  "//": {
7
7
  "build": "node ./scripts/build-static.mjs src/pfconv_params.json src/pfconv_params.lib.tengo && rm -rf dist && pl-tengo check && pl-tengo build && ./create_tags.sh"
8
8
  },
9
9
  "dependencies": {
10
- "@platforma-sdk/workflow-tengo": "^3.1.0"
10
+ "@platforma-sdk/workflow-tengo": "^4.2.0"
11
11
  },
12
12
  "devDependencies": {
13
- "@platforma-sdk/tengo-builder": "^2.0.2",
14
- "@milaboratories/software-pframes-conv": "^2.1.20",
15
- "@platforma-open/milaboratories.software-small-binaries": "^1.15.19",
13
+ "@platforma-sdk/tengo-builder": "^2.1.3",
16
14
  "@platforma-open/milaboratories.software-mixcr": "4.7.0-139-develop",
17
15
  "@platforma-open/milaboratories.software-mitool": "2.3.1-5-main",
18
16
  "@platforma-open/milaboratories.software-ptransform": "^1.3.1",
19
- "@platforma-sdk/test": "^1.25.0",
20
- "vitest": "^2.1.8",
17
+ "@platforma-sdk/test": "^1.30.4",
18
+ "vitest": "~2.1.8",
21
19
  "typescript": "~5.6.3"
22
20
  },
23
21
  "scripts": {
@@ -6,6 +6,7 @@ ll := import("@platforma-sdk/workflow-tengo:ll")
6
6
  pframes := import("@platforma-sdk/workflow-tengo:pframes")
7
7
 
8
8
  processTpl := assets.importTemplate(":process")
9
+ requestLibraryTpl := assets.importTemplate(":request-library")
9
10
 
10
11
  wf.body(func(args) {
11
12
  if is_undefined(args.donorColumn) {
@@ -19,13 +20,15 @@ wf.body(func(args) {
19
20
  // we could not use array as request for waiting (see below), so we store datasets in a dictionary
20
21
  datasets := {}
21
22
  for datasetRef in args.datasetColumns {
22
- if is_undefined(datasetRef) {
23
- ll.panic("Dataset is undefined")
24
- }
25
- // it's blockId of MiXCR, we suppose that it procuce only one clns column
23
+ // we assume that mixcr block produces exactly one clns column
26
24
  datasets[datasetRef.blockId] = wf.resolve(datasetRef)
27
25
  }
28
26
 
27
+ library := render.createEphemeral(requestLibraryTpl, {
28
+ datasets: datasets,
29
+ ctx: wf.getParentBCtx()
30
+ }).output("library")
31
+
29
32
  donorColumn := wf.resolve(args.donorColumn)
30
33
 
31
34
  // The problem is that refs for data is not resolved.
@@ -34,6 +37,7 @@ wf.body(func(args) {
34
37
  results := render.createEphemeral(processTpl, {
35
38
  datasets: datasets,
36
39
  donorColumn: donorColumn,
40
+ library: library,
37
41
  params: {
38
42
  downsampling: args.downsampling,
39
43
  sequencesOfInterest: args.sequencesOfInterest
@@ -6,6 +6,7 @@ maps := import("@platforma-sdk/workflow-tengo:maps")
6
6
  assets := import("@platforma-sdk/workflow-tengo:assets")
7
7
  render := import("@platforma-sdk/workflow-tengo:render")
8
8
  xsv := import("@platforma-sdk/workflow-tengo:pframes.xsv")
9
+ smart := import("@platforma-sdk/workflow-tengo:smart")
9
10
  text := import("text")
10
11
  json := import("json")
11
12
  exportSettings := import(":export-settings")
@@ -20,6 +21,7 @@ self.awaitState("datasets", { wildcard: "*" }, "AllInputsSet")
20
21
  self.awaitState("datasets", { wildcard: "*" }, "data", "InputsLocked")
21
22
  // but we need spec already
22
23
  self.awaitState("datasets", { wildcard: "*" }, "spec", "ResourceReady")
24
+ self.awaitState("library", "spec", "ResourceReady")
23
25
  self.awaitState("donorColumn", "ResourceReady")
24
26
  self.awaitState("params", "ResourceReady")
25
27
 
@@ -36,6 +38,8 @@ self.body(func(inputs) {
36
38
  cellsAssembled: false
37
39
  }
38
40
 
41
+ library := inputs.library
42
+
39
43
  // clonotypingBlockId -> "bulk" | "sc"
40
44
  datasetTypes := {}
41
45
 
@@ -78,6 +82,8 @@ self.body(func(inputs) {
78
82
  shmTreeNodesWithClonesTableOptions := exportSettings.shmTreeNodesWithClonesTableOptions(dataDescription, inputs.donorColumn)
79
83
  shmTreeNodesUniqueIsotypeTableOptions := exportSettings.shmTreeNodesUniqueIsotypeTableOptions(dataDescription)
80
84
 
85
+ libraryFormat := library.spec.annotations["pl7.app/vdj/libraryFormat"]
86
+
81
87
  // TODO that call is too low level. Should be replaced with something that works with pColumns, not data only
82
88
  mixcrResults := llPFrames.aggregate(
83
89
  // files to iterate through
@@ -131,9 +137,13 @@ self.body(func(inputs) {
131
137
  shmTreeNodesWithClonesTableOptions: shmTreeNodesWithClonesTableOptions,
132
138
  shmTreeNodesWithClonesTableArgs: shmTreeNodesWithClonesTableOptions.cmdArgs,
133
139
  shmTreeNodesUniqueIsotypeTableOptions: shmTreeNodesUniqueIsotypeTableOptions,
140
+ library: is_undefined(library) ? smart.createNullResource() : library.data,
134
141
  globalParams: maps.merge(
135
142
  inputs.params,
136
- { datasetTypes: datasetTypes }
143
+ {
144
+ datasetTypes: datasetTypes,
145
+ libraryFormat: libraryFormat
146
+ }
137
147
  )
138
148
  }
139
149
  )
@@ -143,7 +153,7 @@ self.body(func(inputs) {
143
153
  additionalAxesSpec: dataGroupedByDonorId.spec["axesSpec"][:1]
144
154
  }
145
155
 
146
- ll.print("__THE_LOG__ " + string(json.encode(additionalArgsForImportTsv)))
156
+ // ll.print("__THE_LOG__ " + string(json.encode(additionalArgsForImportTsv)))
147
157
 
148
158
  trees := xsv.importFileMap(
149
159
  mixcrResults.output("trees"),
@@ -33,19 +33,32 @@ self.body(func(inputs) {
33
33
  globalParams := inputs.globalParams
34
34
  datasetTypes := globalParams.datasetTypes
35
35
  downsampling := globalParams.downsampling
36
+ library := inputs.library
37
+ libraryFormat := globalParams.libraryFormat
36
38
 
37
39
  // ll.print("__THE_LOG__ " + json.encode(datasetTypes))
38
40
  // ll.print("__THE_LOG__ " + json.encode(downsampling))
41
+ // ll.print("__THE_LOG__ " + json.encode(libraryFormat))
39
42
 
40
43
  ll.assert(!is_undefined(datasetTypes), "datasetTypes undefined")
41
44
 
42
- seed := times.time_string(times.now())
45
+ addLibraryFile := func(cmdBuilder) {
46
+ if !is_undefined(library) {
47
+ if libraryFormat == "repseqio.json.gz" {
48
+ cmdBuilder.addFile("library.json.gz", library)
49
+ } else {
50
+ cmdBuilder.addFile("library.json", library)
51
+ }
52
+ }
53
+ }
54
+
55
+ // seed := times.time_string(times.now())
43
56
 
44
57
  allelesCmdBuilder := exec.builder().
45
58
  printErrStreamToStdout().
46
59
  secret("MI_LICENSE", "MI_LICENSE").
47
60
  env("MI_PROGRESS_PREFIX", progressPrefix).
48
- env("SEED", seed).
61
+ // env("SEED", seed).
49
62
  software(mixcrSw).
50
63
  arg("findAlleles").
51
64
  arg("--report").arg("report.txt").
@@ -55,6 +68,8 @@ self.body(func(inputs) {
55
68
  // template specifies where result files will be written
56
69
  arg("--output-template").arg("alleles/{file_name}.clns")
57
70
 
71
+ addLibraryFile(allelesCmdBuilder)
72
+
58
73
  if !is_undefined(globalParams.seed) {
59
74
  allelesCmdBuilder.env("SEED", globalParams.seed)
60
75
  }
@@ -108,7 +123,7 @@ self.body(func(inputs) {
108
123
 
109
124
  for input in toProcess {
110
125
  if datasetTypes[input.clonotypingBlockId] == "bulk" {
111
- downsamplingCmd := exec.builder().
126
+ downsamplingCmdBuilder := exec.builder().
112
127
  printErrStreamToStdout().
113
128
  secret("MI_LICENSE", "MI_LICENSE").
114
129
  env("MI_PROGRESS_PREFIX", progressPrefix).
@@ -118,8 +133,9 @@ self.body(func(inputs) {
118
133
  arg(downsamplingParam).
119
134
  arg("clones.clns").
120
135
  addFile("clones.clns", input.alleles).
121
- saveFile("clones.downsampled.clns").
122
- run()
136
+ saveFile("clones.downsampled.clns")
137
+ addLibraryFile(downsamplingCmdBuilder)
138
+ downsamplingCmd := downsamplingCmdBuilder.run()
123
139
  input.alleles = downsamplingCmd.getFile("clones.downsampled.clns")
124
140
  }
125
141
  }
@@ -129,7 +145,6 @@ self.body(func(inputs) {
129
145
  printErrStreamToStdout().
130
146
  secret("MI_LICENSE", "MI_LICENSE").
131
147
  env("MI_PROGRESS_PREFIX", progressPrefix).
132
- env("SEED", seed).
133
148
  software(mixcrSw).
134
149
  arg("findShmTrees").
135
150
  arg("--report").arg("report.txt").
@@ -141,6 +156,8 @@ self.body(func(inputs) {
141
156
  shmTreesCmdBuilder.env("SEED", globalParams.seed)
142
157
  }
143
158
 
159
+ addLibraryFile(shmTreesCmdBuilder)
160
+
144
161
  for input in toProcess {
145
162
  shmTreesCmdBuilder.
146
163
  addFile(input.fileName, input.alleles).
@@ -151,15 +168,18 @@ self.body(func(inputs) {
151
168
 
152
169
  shmTrees := shmTreesCmdBuilder.run()
153
170
  outputShmt := shmTrees.getFile("output.shmt")
154
-
171
+
155
172
  // export trees without nodes
156
173
  shmTreeExportsCmdBuilder := exec.builder().
157
174
  printErrStreamToStdout().
175
+ dontSaveStdoutOrStderr().
158
176
  inLightQueue().
159
177
  secret("MI_LICENSE", "MI_LICENSE").
160
178
  software(mixcrSw).
161
179
  arg("exportShmTrees")
162
180
 
181
+ addLibraryFile(shmTreeExportsCmdBuilder)
182
+
163
183
  for arg in inputs.shmTreeTableArgs {
164
184
  shmTreeExportsCmdBuilder = shmTreeExportsCmdBuilder.arg(arg)
165
185
  }
@@ -178,11 +198,14 @@ self.body(func(inputs) {
178
198
  // export tree nodes with data uniq for the node
179
199
  shmTreeNodesExportsCmdBuilder := exec.builder().
180
200
  printErrStreamToStdout().
201
+ dontSaveStdoutOrStderr().
181
202
  inLightQueue().
182
203
  secret("MI_LICENSE", "MI_LICENSE").
183
204
  software(mixcrSw).
184
205
  arg("exportShmTreesWithNodes")
185
206
 
207
+ addLibraryFile(shmTreeNodesExportsCmdBuilder)
208
+
186
209
  for arg in inputs.shmTreeNodesTableOptions.cmdArgs {
187
210
  shmTreeNodesExportsCmdBuilder = shmTreeNodesExportsCmdBuilder.arg(arg)
188
211
  }
@@ -201,6 +224,7 @@ self.body(func(inputs) {
201
224
  // export nodes with clones. For each node could be several clones
202
225
  shmTreeNodesWithClonesExportsCmdBuilder := exec.builder().
203
226
  printErrStreamToStdout().
227
+ dontSaveStdoutOrStderr().
204
228
  inLightQueue().
205
229
  secret("MI_LICENSE", "MI_LICENSE").
206
230
  env("MI_PROGRESS_PREFIX", progressPrefix).
@@ -209,6 +233,8 @@ self.body(func(inputs) {
209
233
  // don't export nodes that don't have clones
210
234
  arg("--only-observed")
211
235
 
236
+ addLibraryFile(shmTreeNodesWithClonesExportsCmdBuilder)
237
+
212
238
  for arg in inputs.shmTreeNodesWithClonesTableArgs {
213
239
  shmTreeNodesWithClonesExportsCmdBuilder = shmTreeNodesWithClonesExportsCmdBuilder.arg(arg)
214
240
  }
@@ -0,0 +1,42 @@
1
+ smart := import("@platforma-sdk/workflow-tengo:smart")
2
+ bquery := import("@platforma-sdk/workflow-tengo:workflow.bquery")
3
+ ll := import("@platforma-sdk/workflow-tengo:ll")
4
+ self := import("@platforma-sdk/workflow-tengo:tpl")
5
+
6
+ self.awaitState("datasets", { wildcard: "*" }, "spec", "ResourceReady")
7
+ self.awaitState("datasets", { wildcard: "*" }, "ref", "ResourceReady")
8
+
9
+ self.body(func(args) {
10
+ datasets := args.datasets
11
+ ctx := args.ctx
12
+
13
+ // undefined - not initialized
14
+ // "" - no custom library, built-in library will be used
15
+ // "...." - custom library id, to be requested from the context
16
+ libraryId := undefined
17
+
18
+ for _, dataset in datasets {
19
+ dsLibraryId := dataset.spec.annotations["pl7.app/vdj/libraryId"]
20
+ if is_undefined(libraryId) {
21
+ libraryId = !is_undefined(dsLibraryId) ? dsLibraryId : ""
22
+ } else {
23
+ if libraryId != dsLibraryId {
24
+ ll.panic("All datasets should have the same libraryId. Got " + libraryId + " and " + dsLibraryId)
25
+ }
26
+ }
27
+ }
28
+
29
+ if libraryId == "" || is_undefined(libraryId) {
30
+ return { library: smart.createNullResource() }
31
+ } else {
32
+ querySpec := {
33
+ type: "And",
34
+ operands: [
35
+ { type: "Name", name: "pl7.app/vdj/library" },
36
+ { type: "Domain", domain: { "pl7.app/vdj/libraryId": libraryId } }
37
+ ]
38
+ }
39
+ return { library: bquery.create(querySpec, ctx, { single: true, errIfMissing: true }) }
40
+ }
41
+ })
42
+