@platforma-open/milaboratories.top-antibodies.workflow 1.8.1 → 1.9.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/antibody-tcr-lead-selection/antibody-tcr-lead-selection/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-open/milaboratories.top-antibodies.workflow@1.8.1 build /home/runner/work/antibody-tcr-lead-selection/antibody-tcr-lead-selection/workflow
3
+ > @platforma-open/milaboratories.top-antibodies.workflow@1.9.0 build /home/runner/work/antibody-tcr-lead-selection/antibody-tcr-lead-selection/workflow
4
4
  > rm -rf dist && pl-tengo check && pl-tengo build
5
5
 
6
6
  Processing "src/filter-and-sample.tpl.tengo"...
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @platforma-open/milaboratories.top-antibodies.workflow
2
2
 
3
+ ## 1.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b499ab2: Add rank column
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [b499ab2]
12
+ - @platforma-open/milaboratories.top-antibodies.sample-clonotypes@1.2.0
13
+
14
+ ## 1.8.2
15
+
16
+ ### Patch Changes
17
+
18
+ - f25cad6: Fix slices typo in main workflow
19
+
3
20
  ## 1.8.1
4
21
 
5
22
  ### Patch Changes
@@ -1,14 +1,7 @@
1
1
  ll := import("@platforma-sdk/workflow-tengo:ll")
2
2
 
3
- getColumns := func(datasetSpec) {
4
- return {
5
- axes: [
6
- {
7
- column: "clonotypeKey",
8
- spec: datasetSpec.axesSpec[1]
9
- }],
10
- columns: [
11
- {
3
+ getColumns := func(datasetSpec, addRanking) {
4
+ columns := [{
12
5
  column: "top",
13
6
  id: "link",
14
7
  allowNA: false,
@@ -22,8 +15,31 @@ getColumns := func(datasetSpec) {
22
15
  "pl7.app/isSubset": "true"
23
16
  }
24
17
  }
25
- }
26
- ],
18
+ }]
19
+ if addRanking {
20
+ columns = columns + [{
21
+ column: "ranked_order",
22
+ spec: {
23
+ name: "pl7.app/vdj/ranking-order",
24
+ valueType: "Int",
25
+ domain: {},
26
+ annotations: {
27
+ "pl7.app/label": "Rank",
28
+ "pl7.app/table/visibility": "optional",
29
+ "pl7.app/isSubset": "true"
30
+ }
31
+ }
32
+ }]
33
+ }
34
+
35
+
36
+ return {
37
+ axes: [
38
+ {
39
+ column: "clonotypeKey",
40
+ spec: datasetSpec.axesSpec[1]
41
+ }],
42
+ columns: columns,
27
43
  storageFormat: "Binary",
28
44
  partitionKeyLength: 0
29
45
  }
Binary file
Binary file
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@platforma-open/milaboratories.top-antibodies.workflow",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "type": "module",
5
5
  "description": "Block Workflow",
6
6
  "dependencies": {
7
7
  "@platforma-sdk/workflow-tengo": "^4.9.2",
8
- "@platforma-open/milaboratories.top-antibodies.sample-clonotypes": "1.1.0",
8
+ "@platforma-open/milaboratories.top-antibodies.sample-clonotypes": "1.2.0",
9
9
  "@platforma-open/milaboratories.top-antibodies.spectratype": "1.4.0",
10
10
  "@platforma-open/milaboratories.top-antibodies.umap": "1.0.3"
11
11
  },
@@ -1,4 +1,4 @@
1
- // Template for clonotype filtering
1
+ // Template for clonotype filtering and sampling
2
2
  self := import("@platforma-sdk/workflow-tengo:tpl")
3
3
  exec := import("@platforma-sdk/workflow-tengo:exec")
4
4
  assets := import("@platforma-sdk/workflow-tengo:assets")
@@ -39,7 +39,7 @@ self.body(func(inputs) {
39
39
  filteredClonotypesCsv := filterResult.getFile("filteredClonotypes.csv")
40
40
 
41
41
  // Store outputs
42
- sampledColsParams := sampledColsConv.getColumns(datasetSpec)
42
+ sampledColsParams := sampledColsConv.getColumns(datasetSpec, false) // No ranking column
43
43
  filteredClonotypesPf := xsv.importFile(filteredClonotypesCsv, "csv", sampledColsParams,
44
44
  {cpu: 1, mem: "16GiB"})
45
45
 
@@ -69,6 +69,7 @@ self.body(func(inputs) {
69
69
  finalClonotypesCsv = sampleClones.getFile("sampledClonotypes_top.csv")
70
70
 
71
71
  // Store outputs
72
+ sampledColsParams := sampledColsConv.getColumns(datasetSpec, true) // Add ranking column
72
73
  sampledColumnsPf := xsv.importFile(finalClonotypesCsv, "csv", sampledColsParams,
73
74
  {cpu: 1, mem: "16GiB"})
74
75
  outputs["sampledRows"] = pframes.exportFrame(sampledColumnsPf)
@@ -4,7 +4,6 @@ exec := import("@platforma-sdk/workflow-tengo:exec")
4
4
  assets:= import("@platforma-sdk/workflow-tengo:assets")
5
5
  xsv := import("@platforma-sdk/workflow-tengo:pframes.xsv")
6
6
  pframes := import("@platforma-sdk/workflow-tengo:pframes")
7
- sampledColsConv := import(":sampled-cols-conv")
8
7
  spectratypeConv := import(":pf-spectratype-conv")
9
8
  vjUsageConv := import(":pf-vj-usage-conv")
10
9
  slices := import("@platforma-sdk/workflow-tengo:slices")
@@ -88,23 +87,23 @@ wf.body(func(args) {
88
87
  // Input arguments
89
88
  columns := args.columns
90
89
  datasetSpec := columns.getSpec(args.inputAnchor)
91
-
92
90
  topClonotypes := args.topClonotypes
93
91
 
94
- // Needed conditional variables
92
+ // Needed conditional variable
95
93
  isSingleCell := datasetSpec.axesSpec[1].name == "pl7.app/vdj/scClonotypeKey"
96
94
 
97
- // output containers
95
+ // Output container
98
96
  outputs := {}
99
97
 
100
- // Get filtered clonotypes from prerun
101
- // Build clonotype table
98
+ // Build clonotype table csv for filtering script
102
99
  cloneTable := pframes.csvFileBuilder()
103
100
  cloneTable.setAxisHeader(datasetSpec.axesSpec[1].name, "clonotypeKey")
104
101
 
105
- // Add Filters to table
106
- addedAxes := []
107
- filterMap := {}
102
+ // Add filter columns to table
103
+ // Filter structure {id: UI id, value: AnchoredColumnId, filter: Filter criteria, isExpanded: boolean (UI state)}
104
+ // AnchoredColumnId {anchorRef: PlRef, anchorName: string, column: SUniversalPColumnId (unique column id)}
105
+ addedAxes := [] // Keep track of axes that are added to the table to prevent duplicates
106
+ filterMap := {} // Map column headers to filter criteria
108
107
  if len(args.filters) > 0 {
109
108
  for i, filter in args.filters {
110
109
  if filter.value != undefined {
@@ -114,14 +113,14 @@ wf.body(func(args) {
114
113
  // Store reference value and filter type associated to this column
115
114
  filterMap["Filter_" + string(i)] = filter.filter
116
115
 
117
- // If column does not have main anchor axis we have to include theirs
116
+ // If column does not have main anchor axis we have to include theirs (columns coming from clustering blocks for example)
118
117
  colsSpec := columns.getSpec(filter.value.column)
119
- axesNames := slices.map(colsSpec.axesSpec, func (a) { return a.name})
118
+ axesNames := slices.map(colsSpec.axesSpec, func (a) {return a.name})
120
119
  if !slices.hasElement(axesNames, datasetSpec.axesSpec[1].name) {
121
120
  for na, ax in colsSpec.axesSpec {
122
121
  if ax.name != datasetSpec.axesSpec[1].name {
123
122
  cloneTable.setAxisHeader(ax.name, "cluster_" + string(i) + string(na))
124
- addedAxes = slices.append(addedAxes, ax.name)
123
+ addedAxes = append(addedAxes, ax.name)
125
124
  }
126
125
  }
127
126
  }
@@ -134,12 +133,12 @@ wf.body(func(args) {
134
133
  for i, col in args.rankingOrder {
135
134
  cloneTable.add(columns.getColumn(col.value.column), {header: "Col" + string(i)})
136
135
 
137
- // If column does not have main anchor axis we have to include theirs
136
+ // If column does not have main anchor axis we have to include theirs (columns coming from clustering blocks for example)
138
137
  colsSpec := columns.getSpec(col.value.column)
139
- axesNames := slices.map(colsSpec.axesSpec, func (a) { return a.name})
138
+ axesNames := slices.map(colsSpec.axesSpec, func (a) {return a.name})
140
139
  if !slices.hasElement(axesNames, datasetSpec.axesSpec[1].name) {
141
140
  for na, ax in colsSpec.axesSpec {
142
- if ax.name != datasetSpec.axesSpec[1].name && !slices.hasElement(addedAxes, ax.name) {
141
+ if ax.name != datasetSpec.axesSpec[1].name && !slices.hasElement(addedAxes, ax.name) { // Prevent duplicates
143
142
  cloneTable.setAxisHeader(ax.name, "cluster_" + string(i) + string(na))
144
143
  }
145
144
  }
@@ -161,8 +160,8 @@ wf.body(func(args) {
161
160
  }
162
161
  }
163
162
 
164
- // Get linker columns if needed
165
- linkerAxisSpec := {}
163
+ // Add linker columns when needed
164
+ linkerAxisSpec := {} // Map cluster axis names to specs. Is it needed????
166
165
  if len(columns.getColumns("linkers")) > 0 {
167
166
  for i, col in columns.getColumns("linkers") {
168
167
  if datasetSpec.axesSpec[1].name == col.spec.axesSpec[1].name {
@@ -180,8 +179,8 @@ wf.body(func(args) {
180
179
  cloneTable.cpu(1)
181
180
  cloneTable = cloneTable.build()
182
181
 
183
- // Use ender.create to call the filter-clonotypes template
184
- filterResult := render.create(filterAndSampleTpl, {
182
+ // Use render.create to call the filtering and sampling clonotypes template
183
+ filterSampleResult := render.create(filterAndSampleTpl, {
185
184
  inputAnchor: args.inputAnchor,
186
185
  cloneTable: cloneTable,
187
186
  rankingOrder: args.rankingOrder,
@@ -192,9 +191,9 @@ wf.body(func(args) {
192
191
  topClonotypes: args.topClonotypes
193
192
  })
194
193
 
195
- // Get the filtered clonotypes P-frame and CSV from the template result
196
- finalClonotypesCsv := filterResult.output("finalClonotypesCsv", 24 * 60 * 60 * 1000)
197
- // outputs["sampledRows"] = filterResult.output("sampledRows", 24 * 60 * 60 * 1000)
194
+ // Get the filtered and sampled clonotypes P-frame and CSV from the template result
195
+ finalClonotypesCsv := filterSampleResult.output("finalClonotypesCsv", 24 * 60 * 60 * 1000)
196
+ // outputs["sampledRows"] = filterSampleResult.output("sampledRows", 24 * 60 * 60 * 1000)
198
197
 
199
198
  ////////// CDR3 Length Calculation //////////
200
199
 
@@ -217,15 +216,15 @@ wf.body(func(args) {
217
216
  chain := col.spec.domain["pl7.app/vdj/scClonotypeChain"] // e.g., "A", "B"
218
217
  receptor := col.spec.axesSpec[0].domain["pl7.app/vdj/receptor"] // e.g., "IG", "TCRAB", "TCRGD"
219
218
  chainLabel := chainMapping[receptor][chain]
220
- return baseHeaderName + "." + chainLabel
219
+ return baseHeaderName + "." + chainLabel // e.g., "cdr3Sequence.Heavy"
221
220
  } else {
222
221
  // For bulk, if chain info is available (e.g. IGH, IGK, IGL)
223
222
  chainFromDomain := col.spec.axesSpec[0].domain["pl7.app/vdj/chain"] // e.g. "IGH", "IGK"
224
223
  if chainFromDomain != undefined {
225
- return baseHeaderName + "." + chainFromDomain
224
+ return baseHeaderName + "." + chainFromDomain // e.g., "cdr3Sequence.IGH"
226
225
  }
227
226
  }
228
- return baseHeaderName // Default header for bulk
227
+ return baseHeaderName
229
228
  };
230
229
 
231
230
  // Process CDR3 sequences
@@ -251,6 +250,7 @@ wf.body(func(args) {
251
250
  headerName := makeHeaderName(col, "jGene", isSingleCell)
252
251
  cdr3SeqTable.add(col, {header: headerName})
253
252
  }
253
+
254
254
  cdr3SeqTable.mem("16GiB")
255
255
  cdr3SeqTable.cpu(1)
256
256
  cdr3SeqTableBuilt := cdr3SeqTable.build()
@@ -280,7 +280,7 @@ wf.body(func(args) {
280
280
  run()
281
281
 
282
282
 
283
- // For spectratype structure is [chain][cdr3Length][vGene] -> count
283
+ // Spectratype PFrame structure is [chain][cdr3Length][vGene] -> count
284
284
 
285
285
  cdr3VspectratypePf := xsv.importFile(cdr3VspectratypeCmd.getFile("spectratype.tsv"),
286
286
  "tsv", spectratypeConv.getColumns(),
@@ -182,7 +182,7 @@ wf.body(func(args) {
182
182
  cloneTable = cloneTable.build()
183
183
 
184
184
  // Use ender.create to call the filter-clonotypes template
185
- filterResult := render.create(filterAndSampleTpl, {
185
+ filterSampleResult := render.create(filterAndSampleTpl, {
186
186
  inputAnchor: args.inputAnchor,
187
187
  cloneTable: cloneTable,
188
188
  topClonotypes: args.topClonotypes,
@@ -194,7 +194,7 @@ wf.body(func(args) {
194
194
  })
195
195
 
196
196
  // Get the filtered clonotypes from the template result
197
- outputs["sampledRows"] = filterResult.output("sampledRows", 24 * 60 * 60 * 1000)
197
+ outputs["sampledRows"] = filterSampleResult.output("sampledRows", 24 * 60 * 60 * 1000)
198
198
  }
199
199
 
200
200
  return {
@@ -1,14 +1,7 @@
1
1
  ll := import("@platforma-sdk/workflow-tengo:ll")
2
2
 
3
- getColumns := func(datasetSpec) {
4
- return {
5
- axes: [
6
- {
7
- column: "clonotypeKey",
8
- spec: datasetSpec.axesSpec[1]
9
- }],
10
- columns: [
11
- {
3
+ getColumns := func(datasetSpec, addRanking) {
4
+ columns := [{
12
5
  column: "top",
13
6
  id: "link",
14
7
  allowNA: false,
@@ -22,8 +15,31 @@ getColumns := func(datasetSpec) {
22
15
  "pl7.app/isSubset": "true"
23
16
  }
24
17
  }
25
- }
26
- ],
18
+ }]
19
+ if addRanking {
20
+ columns = columns + [{
21
+ column: "ranked_order",
22
+ spec: {
23
+ name: "pl7.app/vdj/ranking-order",
24
+ valueType: "Int",
25
+ domain: {},
26
+ annotations: {
27
+ "pl7.app/label": "Rank",
28
+ "pl7.app/table/visibility": "optional",
29
+ "pl7.app/isSubset": "true"
30
+ }
31
+ }
32
+ }]
33
+ }
34
+
35
+
36
+ return {
37
+ axes: [
38
+ {
39
+ column: "clonotypeKey",
40
+ spec: datasetSpec.axesSpec[1]
41
+ }],
42
+ columns: columns,
27
43
  storageFormat: "Binary",
28
44
  partitionKeyLength: 0
29
45
  }