@sjcrh/proteinpaint-server 2.173.0 → 2.174.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.
@@ -6,35 +6,42 @@ f{}
6
6
  returns a GDC filter object, or null if no filter
7
7
 
8
8
  GDC filter: https://docs.gdc.cancer.gov/API/Users_Guide/Search_and_Retrieval/
9
-
10
- TODO !!support nested filter!!
11
9
  */
12
- export function filter2GDCfilter(f) {
10
+ export function filter2GDCfilter(f, level = 0) {
13
11
  // gdc filter that will be returned
14
- const obj = {
15
- op: f.in ? 'and' : 'not',
12
+ let obj = {
13
+ op: f.join || 'and',
16
14
  content: []
17
15
  }
18
- if (!Array.isArray(f.lst)) throw 'filter.lst[] not array'
16
+ if (!Array.isArray(f.lst)) throw new Error('filter.lst[] not array')
17
+ if (f.in === false) throw `negation of nested filters is not supported`
18
+
19
19
  for (const item of f.lst) {
20
- if (item.type != 'tvs') throw 'filter.lst[] item.type!="tvs"'
21
- if (!item.tvs) throw 'item.tvs missing'
22
- if (!item.tvs.term) throw 'item.tvs.term missing'
20
+ if (item.type != 'tvs') {
21
+ const f = filter2GDCfilter(item, level + 1)
22
+ if (f) obj.content.push(f)
23
+ continue
24
+ }
25
+ if (!item.tvs) throw new Error('item.tvs missing')
26
+ if (!item.tvs.term) throw new Error('item.tvs.term missing')
23
27
  if (dtTermTypes.has(item.tvs.term.type)) {
24
28
  // geneVariant/dt term filtering will be performed during post-processing
25
29
  // (see mayFilterByGeneVariant() in server/src/mds3.init.js)
26
30
  continue
27
31
  }
28
32
  if (item.tvs.term.type == 'geneExpression') {
33
+ if (level > 0) throw new Error(`gene expression filters are only supported at the root level of a nested filter`)
29
34
  // geneExpression term filtering will be performed during post-processing (see mayFilterByExpression() in server/src/mds3.gdc.js)
30
35
  continue
31
36
  }
32
37
  if (item.tvs.term.type == 'survival') {
38
+ if (level > 0) throw new Error(`survival filters are only supported at the root level of a nested filter`)
33
39
  // survival term filtering will be performed during post-processing (see mayFilterBySurvival() in server/src/mds3.gdc.js)
34
40
  continue
35
41
  }
36
42
 
37
- if (item.tvs.values) {
43
+ // sometimes, numeric filters have a values entry
44
+ if (item.tvs.values && !item.tvs.ranges) {
38
45
  // categorical
39
46
  const f = {
40
47
  op: item.tvs.isnot ? '!=' : 'in',
@@ -47,65 +54,24 @@ export function filter2GDCfilter(f) {
47
54
  continue
48
55
  }
49
56
  if (item.tvs.ranges) {
50
- for (const range of item.tvs.ranges) {
51
- if (range.startunbounded) {
52
- obj.content.push({
53
- op: range.stopinclusive ? (item.tvs.isnot ? '>' : '<=') : item.tvs.isnot ? '>=' : '<',
54
- content: { field: mayChangeCase2Cases(item.tvs.term), value: range.stop }
55
- })
56
- continue
57
- }
58
- if (range.stopunbounded) {
59
- obj.content.push({
60
- op: range.startinclusive ? (item.tvs.isnot ? '<' : '>=') : item.tvs.isnot ? '<=' : '>',
61
- content: { field: mayChangeCase2Cases(item.tvs.term), value: range.start }
62
- })
63
- continue
64
- }
65
- if (item.tvs.isnot) {
66
- obj.content.push({
67
- op: 'or',
68
- content: [
69
- {
70
- op: 'and',
71
- content: [
72
- {
73
- op: range.startinclusive ? '<' : '<=',
74
- content: { field: mayChangeCase2Cases(item.tvs.term), value: range.start }
75
- }
76
- ]
77
- },
78
- {
79
- op: 'and',
80
- content: [
81
- {
82
- op: range.stopinclusive ? '>' : '>=',
83
- content: { field: mayChangeCase2Cases(item.tvs.term), value: range.stop }
84
- }
85
- ]
86
- }
87
- ]
88
- })
89
- } else {
90
- obj.content.push({
91
- op: 'and',
92
- content: [
93
- {
94
- op: range.startinclusive ? '>=' : '>',
95
- content: { field: mayChangeCase2Cases(item.tvs.term), value: range.start }
96
- },
97
- {
98
- op: range.stopinclusive ? '<=' : '<',
99
- content: { field: mayChangeCase2Cases(item.tvs.term), value: range.stop }
100
- }
101
- ]
102
- })
57
+ let f
58
+ if (!item.tvs.ranges.length) throw new Error('item.tvs.ranges[] is empty')
59
+ if (item.tvs.ranges.length == 1) {
60
+ const range = item.tvs.ranges[0]
61
+ f = range2GDCrange(range, item)
62
+ } else {
63
+ f = { op: 'or', content: [] }
64
+ for (const range of item.tvs.ranges) {
65
+ f.content.push(range2GDCrange(range, item))
103
66
  }
104
67
  }
68
+ //if (item.tvs.isnot) f = { op: '!=', content: f }
69
+ obj.content.push(f)
105
70
  continue
106
71
  }
107
- throw 'unknown tvs structure when converting to gdc filter'
72
+ throw new Error('unknown tvs structure when converting to gdc filter')
108
73
  }
74
+ if (!level) console.log(JSON.stringify(obj, null, ' '))
109
75
  return obj.content.length ? obj : null
110
76
  }
111
77
 
@@ -123,3 +89,31 @@ function mayChangeCase2Cases(t) {
123
89
  if (l[0] == 'case') l[0] = 'cases'
124
90
  return l.join('.')
125
91
  }
92
+
93
+ function range2GDCrange(range, item) {
94
+ if (range.startunbounded) {
95
+ return {
96
+ op: range.stopinclusive ? (item.tvs.isnot ? '>' : '<=') : item.tvs.isnot ? '>=' : '<',
97
+ content: { field: mayChangeCase2Cases(item.tvs.term), value: range.stop }
98
+ }
99
+ }
100
+ if (range.stopunbounded) {
101
+ return {
102
+ op: range.startinclusive ? (item.tvs.isnot ? '<' : '>=') : item.tvs.isnot ? '<=' : '>',
103
+ content: { field: mayChangeCase2Cases(item.tvs.term), value: range.start }
104
+ }
105
+ }
106
+ return {
107
+ op: 'and',
108
+ content: [
109
+ {
110
+ op: range.startinclusive ? (item.tvs.isnot ? '<' : '>=') : item.tvs.isnot ? '>=' : '>',
111
+ content: { field: mayChangeCase2Cases(item.tvs.term), value: range.start }
112
+ },
113
+ {
114
+ op: range.stopinclusive ? (item.tvs.isnot ? '>' : '<=') : item.tvs.isnot ? '<=' : '<',
115
+ content: { field: mayChangeCase2Cases(item.tvs.term), value: range.stop }
116
+ }
117
+ ]
118
+ }
119
+ }