@jbrowse/plugin-bed 3.4.0 → 3.5.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.
@@ -42,9 +42,9 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
42
42
  }
43
43
  async getRefNameAliases(opts) {
44
44
  const { header } = await this.configure(opts);
45
- const ret = await Promise.all(Object.keys(header.refsByName).map(async (r) => (await (0, rxjs_2.firstValueFrom)(this.getFeatures({
45
+ const ret = await Promise.all(Object.keys(header.refsByName).map(async (refName) => (await (0, rxjs_2.firstValueFrom)(this.getFeatures({
46
46
  assemblyName: '',
47
- refName: r,
47
+ refName,
48
48
  start: 0,
49
49
  end: 1,
50
50
  }).pipe((0, rxjs_2.toArray)())))[0]));
@@ -73,11 +73,11 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
73
73
  async getHeader(opts) {
74
74
  const { parser, header } = await this.configure(opts);
75
75
  const { version, fileType } = header;
76
- const { fields, ...rest } = parser.autoSql;
76
+ const { fields, ...autoSql } = parser.autoSql;
77
77
  return {
78
78
  version,
79
79
  fileType,
80
- autoSql: { ...rest },
80
+ autoSql,
81
81
  fields: await this.getMetadata(opts),
82
82
  };
83
83
  }
@@ -87,7 +87,6 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
87
87
  return Object.fromEntries(fields.map(({ name, comment }) => [name, comment]));
88
88
  }
89
89
  async getFeaturesHelper({ query, opts, observer, allowRedispatch, originalQuery = query, }) {
90
- var _a;
91
90
  const { statusCallback = () => { } } = opts;
92
91
  const scoreColumn = this.getConf('scoreColumn');
93
92
  const aggregateField = this.getConf('aggregateField');
@@ -95,95 +94,119 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
95
94
  const feats = await (0, util_1.updateStatus)('Downloading features', statusCallback, () => bigbed.getFeatures(query.refName, query.start, query.end, {
96
95
  basesPerSpan: query.end - query.start,
97
96
  }));
98
- const parentAggregation = {};
99
- const parentAggregationFlat = [];
100
- if (feats.some(f => f.uniqueId === undefined)) {
101
- throw new Error('found uniqueId undefined');
102
- }
103
- for (const feat of feats) {
104
- const splitLine = [
105
- query.refName,
106
- `${feat.start}`,
107
- `${feat.end}`,
108
- ...(((_a = feat.rest) === null || _a === void 0 ? void 0 : _a.split('\t')) || []),
109
- ];
110
- const data = parser.parseLine(splitLine, {
111
- uniqueId: feat.uniqueId,
112
- });
113
- const aggr = data[aggregateField];
114
- const aggrIsNotNone = aggr && aggr !== 'none';
115
- if (aggrIsNotNone && !parentAggregation[aggr]) {
116
- parentAggregation[aggr] = [];
117
- }
118
- const { uniqueId, type, chrom, chromStart, chromEnd, description, chromStarts: chromStarts2, blockStarts: blockStarts2, blockSizes: blockSizes2, score: score2, blockCount, thickStart, thickEnd, strand, ...rest } = data;
119
- const f = (0, util_2.featureData2)({
120
- ...rest,
121
- scoreColumn,
122
- splitLine,
123
- parser,
124
- uniqueId,
125
- start: feat.start,
126
- end: feat.end,
127
- refName: query.refName,
128
- });
129
- if (aggrIsNotNone) {
130
- parentAggregation[aggr].push(f);
131
- parentAggregationFlat.push(f);
97
+ await (0, util_1.updateStatus)('Processing features', statusCallback, async () => {
98
+ var _a;
99
+ const parentAggregation = {};
100
+ const parentAggregationFlat = [];
101
+ if (feats.some(f => f.uniqueId === undefined)) {
102
+ throw new Error('found uniqueId undefined');
132
103
  }
133
- else {
134
- if ((0, util_1.doesIntersect2)(f.start, f.end, originalQuery.start, originalQuery.end)) {
135
- observer.next(new util_1.SimpleFeature({
136
- id: `${this.id}-${uniqueId}`,
137
- data: f,
138
- }));
104
+ for (const feat of feats) {
105
+ const splitLine = [
106
+ query.refName,
107
+ `${feat.start}`,
108
+ `${feat.end}`,
109
+ ...(((_a = feat.rest) === null || _a === void 0 ? void 0 : _a.split('\t')) || []),
110
+ ];
111
+ const data = parser.parseLine(splitLine, {
112
+ uniqueId: feat.uniqueId,
113
+ });
114
+ const aggr = data[aggregateField];
115
+ const aggrIsNotNone = aggr && aggr !== 'none';
116
+ if (aggrIsNotNone && !parentAggregation[aggr]) {
117
+ parentAggregation[aggr] = [];
139
118
  }
140
- }
141
- }
142
- if (allowRedispatch && parentAggregationFlat.length) {
143
- let minStart = Number.POSITIVE_INFINITY;
144
- let maxEnd = Number.NEGATIVE_INFINITY;
145
- for (const feat of parentAggregationFlat) {
146
- if (feat.start < minStart) {
147
- minStart = feat.start;
119
+ const { uniqueId, type, chrom, chromStart, chromEnd, description, chromStarts: chromStarts2, blockStarts: blockStarts2, blockSizes: blockSizes2, score: score2, blockCount, thickStart, thickEnd, strand, ...rest } = data;
120
+ const f = (0, util_2.featureData2)({
121
+ ...rest,
122
+ scoreColumn,
123
+ splitLine,
124
+ parser,
125
+ uniqueId,
126
+ start: feat.start,
127
+ end: feat.end,
128
+ refName: query.refName,
129
+ });
130
+ if (aggrIsNotNone) {
131
+ parentAggregation[aggr].push(f);
132
+ parentAggregationFlat.push(f);
148
133
  }
149
- if (feat.end > maxEnd) {
150
- maxEnd = feat.end;
134
+ else {
135
+ if ((0, util_1.doesIntersect2)(f.start, f.end, originalQuery.start, originalQuery.end)) {
136
+ observer.next(new util_1.SimpleFeature({
137
+ id: `${this.id}-${uniqueId}`,
138
+ data: f,
139
+ }));
140
+ }
151
141
  }
152
142
  }
153
- if (maxEnd > query.end || minStart < query.start) {
154
- await this.getFeaturesHelper({
155
- query: {
156
- ...query,
157
- start: minStart - 500000,
158
- end: maxEnd + 500000,
159
- },
160
- opts,
161
- observer,
162
- allowRedispatch: false,
163
- originalQuery: query,
164
- });
165
- return;
166
- }
167
- }
168
- Object.entries(parentAggregation).map(([name, subfeatures]) => {
169
- var _a, _b;
170
- const s = (0, util_1.min)(subfeatures.map(f => f.start));
171
- const e = (0, util_1.max)(subfeatures.map(f => f.end));
172
- if ((0, util_1.doesIntersect2)(s, e, originalQuery.start, originalQuery.end)) {
173
- const subs = subfeatures.sort((a, b) => a.uniqueId.localeCompare(b.uniqueId));
174
- observer.next(new util_1.SimpleFeature({
175
- id: `${this.id}-${(_a = subs[0]) === null || _a === void 0 ? void 0 : _a.uniqueId}-parent`,
176
- data: {
177
- type: 'gene',
178
- subfeatures: subs,
179
- strand: ((_b = subs[0]) === null || _b === void 0 ? void 0 : _b.strand) || 1,
180
- name,
181
- start: s,
182
- end: e,
183
- refName: query.refName,
184
- },
185
- }));
143
+ if (allowRedispatch && parentAggregationFlat.length) {
144
+ let minStart = Number.POSITIVE_INFINITY;
145
+ let maxEnd = Number.NEGATIVE_INFINITY;
146
+ for (const feat of parentAggregationFlat) {
147
+ if (feat.start < minStart) {
148
+ minStart = feat.start;
149
+ }
150
+ if (feat.end > maxEnd) {
151
+ maxEnd = feat.end;
152
+ }
153
+ }
154
+ if (maxEnd > query.end || minStart < query.start) {
155
+ await this.getFeaturesHelper({
156
+ query: {
157
+ ...query,
158
+ start: minStart - 500000,
159
+ end: maxEnd + 500000,
160
+ },
161
+ opts,
162
+ observer,
163
+ allowRedispatch: false,
164
+ originalQuery: query,
165
+ });
166
+ return;
167
+ }
186
168
  }
169
+ Object.entries(parentAggregation).map(([name, subfeatures]) => {
170
+ var _a, _b, _c;
171
+ const s = (0, util_1.min)(subfeatures.map(f => f.start));
172
+ const e = (0, util_1.max)(subfeatures.map(f => f.end));
173
+ if ((0, util_1.doesIntersect2)(s, e, originalQuery.start, originalQuery.end)) {
174
+ const subs = subfeatures.sort((a, b) => a.uniqueId.localeCompare(b.uniqueId));
175
+ if (subs.every(s => {
176
+ var _a;
177
+ return s.strand === (((_a = subs[0]) === null || _a === void 0 ? void 0 : _a.strand) || 1);
178
+ })) {
179
+ observer.next(new util_1.SimpleFeature({
180
+ id: `${this.id}-${(_a = subs[0]) === null || _a === void 0 ? void 0 : _a.uniqueId}-parent`,
181
+ data: {
182
+ type: 'gene',
183
+ subfeatures: subs,
184
+ strand: ((_b = subs[0]) === null || _b === void 0 ? void 0 : _b.strand) || 1,
185
+ name,
186
+ start: s,
187
+ end: e,
188
+ refName: query.refName,
189
+ },
190
+ }));
191
+ }
192
+ else {
193
+ for (const sub of subs) {
194
+ observer.next(new util_1.SimpleFeature({
195
+ id: `${this.id}-${sub.uniqueId}-parent`,
196
+ data: {
197
+ type: 'gene',
198
+ subfeatures: [sub],
199
+ strand: ((_c = subs[0]) === null || _c === void 0 ? void 0 : _c.strand) || 1,
200
+ name,
201
+ start: sub.start,
202
+ end: sub.end,
203
+ refName: query.refName,
204
+ },
205
+ }));
206
+ }
207
+ }
208
+ }
209
+ });
187
210
  });
188
211
  observer.complete();
189
212
  }
@@ -1,4 +1,4 @@
1
- import type { MinimalFeature, TranscriptFeat } from './types';
1
+ import type { TranscriptFeat } from './types';
2
2
  export declare function isUcscTranscript({ thickStart, blockCount, strand, }: {
3
3
  thickStart?: number;
4
4
  blockCount?: number;
@@ -9,7 +9,12 @@ export declare function generateUcscTranscript(data: TranscriptFeat): {
9
9
  strand: number;
10
10
  type: string;
11
11
  refName: string;
12
- subfeatures: MinimalFeature[];
12
+ subfeatures: {
13
+ type: string;
14
+ start: number;
15
+ end: number;
16
+ refName: string;
17
+ }[];
13
18
  start: number;
14
19
  end: number;
15
20
  };
@@ -12,81 +12,105 @@ function generateUcscTranscript(data) {
12
12
  const feats = oldSubfeatures
13
13
  .filter(child => child.type === 'block')
14
14
  .sort((a, b) => a.start - b.start);
15
- for (const block of feats) {
16
- const start = block.start;
17
- const end = block.end;
18
- if (thickStart >= end) {
19
- subfeatures.push({
20
- type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
21
- start,
22
- end,
23
- refName,
24
- });
25
- }
26
- else if (thickStart > start && thickStart < end && thickEnd >= end) {
27
- subfeatures.push({
28
- type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
29
- start,
30
- end: thickStart,
31
- refName,
32
- }, {
33
- type: 'CDS',
34
- phase: 0,
35
- start: thickStart,
36
- end,
37
- refName,
38
- });
39
- }
40
- else if (thickStart <= start && thickEnd >= end) {
41
- subfeatures.push({
42
- type: 'CDS',
43
- phase: 0,
44
- start,
45
- end,
46
- refName,
47
- });
48
- }
49
- else if (thickStart > start && thickStart < end && thickEnd < end) {
50
- subfeatures.push({
51
- type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
52
- start,
53
- end: thickStart,
54
- refName,
55
- }, {
56
- type: 'CDS',
57
- phase: 0,
58
- start: thickStart,
59
- end: thickEnd,
60
- refName,
61
- }, {
62
- type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
63
- start: thickEnd,
64
- end,
65
- refName,
66
- });
67
- }
68
- else if (thickStart <= start && thickEnd > start && thickEnd < end) {
69
- subfeatures.push({
70
- type: 'CDS',
71
- phase: 0,
72
- start,
73
- end: thickEnd,
74
- refName,
75
- }, {
76
- type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
77
- start: thickEnd,
78
- end,
79
- refName,
80
- });
81
- }
82
- else if (thickEnd <= start) {
83
- subfeatures.push({
84
- type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
85
- start,
86
- end,
87
- refName,
88
- });
15
+ const { cdsEndStat, cdsStartStat } = rest2;
16
+ if (cdsStartStat === 'none' && cdsEndStat === 'none') {
17
+ return {
18
+ ...rest2,
19
+ uniqueId,
20
+ strand,
21
+ type: 'transcript',
22
+ refName,
23
+ subfeatures: feats.map(e => ({
24
+ ...e,
25
+ type: 'exon',
26
+ })),
27
+ };
28
+ }
29
+ else {
30
+ for (const block of feats) {
31
+ const start = block.start;
32
+ const end = block.end;
33
+ if (thickStart >= end) {
34
+ subfeatures.push({
35
+ type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
36
+ start,
37
+ end,
38
+ refName,
39
+ });
40
+ }
41
+ else if (thickStart > start && thickStart < end && thickEnd >= end) {
42
+ subfeatures.push({
43
+ type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
44
+ start,
45
+ end: thickStart,
46
+ refName,
47
+ }, {
48
+ type: 'CDS',
49
+ phase: 0,
50
+ start: thickStart,
51
+ end,
52
+ refName,
53
+ });
54
+ }
55
+ else if (thickStart <= start && thickEnd >= end) {
56
+ subfeatures.push({
57
+ type: 'CDS',
58
+ phase: 0,
59
+ start,
60
+ end,
61
+ refName,
62
+ });
63
+ }
64
+ else if (thickStart > start && thickStart < end && thickEnd < end) {
65
+ subfeatures.push({
66
+ type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
67
+ start,
68
+ end: thickStart,
69
+ refName,
70
+ }, {
71
+ type: 'CDS',
72
+ phase: 0,
73
+ start: thickStart,
74
+ end: thickEnd,
75
+ refName,
76
+ }, {
77
+ type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
78
+ start: thickEnd,
79
+ end,
80
+ refName,
81
+ });
82
+ }
83
+ else if (thickStart <= start && thickEnd > start && thickEnd < end) {
84
+ subfeatures.push({
85
+ type: 'CDS',
86
+ phase: 0,
87
+ start,
88
+ end: thickEnd,
89
+ refName,
90
+ }, {
91
+ type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
92
+ start: thickEnd,
93
+ end,
94
+ refName,
95
+ });
96
+ }
97
+ else if (thickEnd <= start) {
98
+ subfeatures.push({
99
+ type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
100
+ start,
101
+ end,
102
+ refName,
103
+ });
104
+ }
89
105
  }
106
+ return {
107
+ ...rest2,
108
+ uniqueId,
109
+ strand,
110
+ type: 'mRNA',
111
+ refName,
112
+ subfeatures,
113
+ };
90
114
  }
91
115
  return {
92
116
  ...rest2,
package/dist/util.d.ts CHANGED
@@ -89,7 +89,12 @@ export declare function featureData({ line, colRef, colStart, colEnd, scoreColum
89
89
  strand: number;
90
90
  type: string;
91
91
  refName: string;
92
- subfeatures: import("./types").MinimalFeature[];
92
+ subfeatures: {
93
+ type: string;
94
+ start: number;
95
+ end: number;
96
+ refName: string;
97
+ }[];
93
98
  start: number;
94
99
  end: number;
95
100
  } | {
@@ -182,7 +187,12 @@ export declare function featureData2({ splitLine, refName, start, end, parser, u
182
187
  strand: number;
183
188
  type: string;
184
189
  refName: string;
185
- subfeatures: import("./types").MinimalFeature[];
190
+ subfeatures: {
191
+ type: string;
192
+ start: number;
193
+ end: number;
194
+ refName: string;
195
+ }[];
186
196
  start: number;
187
197
  end: number;
188
198
  } | {
@@ -37,9 +37,9 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
37
37
  }
38
38
  async getRefNameAliases(opts) {
39
39
  const { header } = await this.configure(opts);
40
- const ret = await Promise.all(Object.keys(header.refsByName).map(async (r) => (await firstValueFrom(this.getFeatures({
40
+ const ret = await Promise.all(Object.keys(header.refsByName).map(async (refName) => (await firstValueFrom(this.getFeatures({
41
41
  assemblyName: '',
42
- refName: r,
42
+ refName,
43
43
  start: 0,
44
44
  end: 1,
45
45
  }).pipe(toArray())))[0]));
@@ -68,11 +68,11 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
68
68
  async getHeader(opts) {
69
69
  const { parser, header } = await this.configure(opts);
70
70
  const { version, fileType } = header;
71
- const { fields, ...rest } = parser.autoSql;
71
+ const { fields, ...autoSql } = parser.autoSql;
72
72
  return {
73
73
  version,
74
74
  fileType,
75
- autoSql: { ...rest },
75
+ autoSql,
76
76
  fields: await this.getMetadata(opts),
77
77
  };
78
78
  }
@@ -82,7 +82,6 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
82
82
  return Object.fromEntries(fields.map(({ name, comment }) => [name, comment]));
83
83
  }
84
84
  async getFeaturesHelper({ query, opts, observer, allowRedispatch, originalQuery = query, }) {
85
- var _a;
86
85
  const { statusCallback = () => { } } = opts;
87
86
  const scoreColumn = this.getConf('scoreColumn');
88
87
  const aggregateField = this.getConf('aggregateField');
@@ -90,95 +89,119 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
90
89
  const feats = await updateStatus('Downloading features', statusCallback, () => bigbed.getFeatures(query.refName, query.start, query.end, {
91
90
  basesPerSpan: query.end - query.start,
92
91
  }));
93
- const parentAggregation = {};
94
- const parentAggregationFlat = [];
95
- if (feats.some(f => f.uniqueId === undefined)) {
96
- throw new Error('found uniqueId undefined');
97
- }
98
- for (const feat of feats) {
99
- const splitLine = [
100
- query.refName,
101
- `${feat.start}`,
102
- `${feat.end}`,
103
- ...(((_a = feat.rest) === null || _a === void 0 ? void 0 : _a.split('\t')) || []),
104
- ];
105
- const data = parser.parseLine(splitLine, {
106
- uniqueId: feat.uniqueId,
107
- });
108
- const aggr = data[aggregateField];
109
- const aggrIsNotNone = aggr && aggr !== 'none';
110
- if (aggrIsNotNone && !parentAggregation[aggr]) {
111
- parentAggregation[aggr] = [];
112
- }
113
- const { uniqueId, type, chrom, chromStart, chromEnd, description, chromStarts: chromStarts2, blockStarts: blockStarts2, blockSizes: blockSizes2, score: score2, blockCount, thickStart, thickEnd, strand, ...rest } = data;
114
- const f = featureData2({
115
- ...rest,
116
- scoreColumn,
117
- splitLine,
118
- parser,
119
- uniqueId,
120
- start: feat.start,
121
- end: feat.end,
122
- refName: query.refName,
123
- });
124
- if (aggrIsNotNone) {
125
- parentAggregation[aggr].push(f);
126
- parentAggregationFlat.push(f);
92
+ await updateStatus('Processing features', statusCallback, async () => {
93
+ var _a;
94
+ const parentAggregation = {};
95
+ const parentAggregationFlat = [];
96
+ if (feats.some(f => f.uniqueId === undefined)) {
97
+ throw new Error('found uniqueId undefined');
127
98
  }
128
- else {
129
- if (doesIntersect2(f.start, f.end, originalQuery.start, originalQuery.end)) {
130
- observer.next(new SimpleFeature({
131
- id: `${this.id}-${uniqueId}`,
132
- data: f,
133
- }));
99
+ for (const feat of feats) {
100
+ const splitLine = [
101
+ query.refName,
102
+ `${feat.start}`,
103
+ `${feat.end}`,
104
+ ...(((_a = feat.rest) === null || _a === void 0 ? void 0 : _a.split('\t')) || []),
105
+ ];
106
+ const data = parser.parseLine(splitLine, {
107
+ uniqueId: feat.uniqueId,
108
+ });
109
+ const aggr = data[aggregateField];
110
+ const aggrIsNotNone = aggr && aggr !== 'none';
111
+ if (aggrIsNotNone && !parentAggregation[aggr]) {
112
+ parentAggregation[aggr] = [];
134
113
  }
135
- }
136
- }
137
- if (allowRedispatch && parentAggregationFlat.length) {
138
- let minStart = Number.POSITIVE_INFINITY;
139
- let maxEnd = Number.NEGATIVE_INFINITY;
140
- for (const feat of parentAggregationFlat) {
141
- if (feat.start < minStart) {
142
- minStart = feat.start;
114
+ const { uniqueId, type, chrom, chromStart, chromEnd, description, chromStarts: chromStarts2, blockStarts: blockStarts2, blockSizes: blockSizes2, score: score2, blockCount, thickStart, thickEnd, strand, ...rest } = data;
115
+ const f = featureData2({
116
+ ...rest,
117
+ scoreColumn,
118
+ splitLine,
119
+ parser,
120
+ uniqueId,
121
+ start: feat.start,
122
+ end: feat.end,
123
+ refName: query.refName,
124
+ });
125
+ if (aggrIsNotNone) {
126
+ parentAggregation[aggr].push(f);
127
+ parentAggregationFlat.push(f);
143
128
  }
144
- if (feat.end > maxEnd) {
145
- maxEnd = feat.end;
129
+ else {
130
+ if (doesIntersect2(f.start, f.end, originalQuery.start, originalQuery.end)) {
131
+ observer.next(new SimpleFeature({
132
+ id: `${this.id}-${uniqueId}`,
133
+ data: f,
134
+ }));
135
+ }
146
136
  }
147
137
  }
148
- if (maxEnd > query.end || minStart < query.start) {
149
- await this.getFeaturesHelper({
150
- query: {
151
- ...query,
152
- start: minStart - 500000,
153
- end: maxEnd + 500000,
154
- },
155
- opts,
156
- observer,
157
- allowRedispatch: false,
158
- originalQuery: query,
159
- });
160
- return;
161
- }
162
- }
163
- Object.entries(parentAggregation).map(([name, subfeatures]) => {
164
- var _a, _b;
165
- const s = min(subfeatures.map(f => f.start));
166
- const e = max(subfeatures.map(f => f.end));
167
- if (doesIntersect2(s, e, originalQuery.start, originalQuery.end)) {
168
- const subs = subfeatures.sort((a, b) => a.uniqueId.localeCompare(b.uniqueId));
169
- observer.next(new SimpleFeature({
170
- id: `${this.id}-${(_a = subs[0]) === null || _a === void 0 ? void 0 : _a.uniqueId}-parent`,
171
- data: {
172
- type: 'gene',
173
- subfeatures: subs,
174
- strand: ((_b = subs[0]) === null || _b === void 0 ? void 0 : _b.strand) || 1,
175
- name,
176
- start: s,
177
- end: e,
178
- refName: query.refName,
179
- },
180
- }));
138
+ if (allowRedispatch && parentAggregationFlat.length) {
139
+ let minStart = Number.POSITIVE_INFINITY;
140
+ let maxEnd = Number.NEGATIVE_INFINITY;
141
+ for (const feat of parentAggregationFlat) {
142
+ if (feat.start < minStart) {
143
+ minStart = feat.start;
144
+ }
145
+ if (feat.end > maxEnd) {
146
+ maxEnd = feat.end;
147
+ }
148
+ }
149
+ if (maxEnd > query.end || minStart < query.start) {
150
+ await this.getFeaturesHelper({
151
+ query: {
152
+ ...query,
153
+ start: minStart - 500000,
154
+ end: maxEnd + 500000,
155
+ },
156
+ opts,
157
+ observer,
158
+ allowRedispatch: false,
159
+ originalQuery: query,
160
+ });
161
+ return;
162
+ }
181
163
  }
164
+ Object.entries(parentAggregation).map(([name, subfeatures]) => {
165
+ var _a, _b, _c;
166
+ const s = min(subfeatures.map(f => f.start));
167
+ const e = max(subfeatures.map(f => f.end));
168
+ if (doesIntersect2(s, e, originalQuery.start, originalQuery.end)) {
169
+ const subs = subfeatures.sort((a, b) => a.uniqueId.localeCompare(b.uniqueId));
170
+ if (subs.every(s => {
171
+ var _a;
172
+ return s.strand === (((_a = subs[0]) === null || _a === void 0 ? void 0 : _a.strand) || 1);
173
+ })) {
174
+ observer.next(new SimpleFeature({
175
+ id: `${this.id}-${(_a = subs[0]) === null || _a === void 0 ? void 0 : _a.uniqueId}-parent`,
176
+ data: {
177
+ type: 'gene',
178
+ subfeatures: subs,
179
+ strand: ((_b = subs[0]) === null || _b === void 0 ? void 0 : _b.strand) || 1,
180
+ name,
181
+ start: s,
182
+ end: e,
183
+ refName: query.refName,
184
+ },
185
+ }));
186
+ }
187
+ else {
188
+ for (const sub of subs) {
189
+ observer.next(new SimpleFeature({
190
+ id: `${this.id}-${sub.uniqueId}-parent`,
191
+ data: {
192
+ type: 'gene',
193
+ subfeatures: [sub],
194
+ strand: ((_c = subs[0]) === null || _c === void 0 ? void 0 : _c.strand) || 1,
195
+ name,
196
+ start: sub.start,
197
+ end: sub.end,
198
+ refName: query.refName,
199
+ },
200
+ }));
201
+ }
202
+ }
203
+ }
204
+ });
182
205
  });
183
206
  observer.complete();
184
207
  }
@@ -1,4 +1,4 @@
1
- import type { MinimalFeature, TranscriptFeat } from './types';
1
+ import type { TranscriptFeat } from './types';
2
2
  export declare function isUcscTranscript({ thickStart, blockCount, strand, }: {
3
3
  thickStart?: number;
4
4
  blockCount?: number;
@@ -9,7 +9,12 @@ export declare function generateUcscTranscript(data: TranscriptFeat): {
9
9
  strand: number;
10
10
  type: string;
11
11
  refName: string;
12
- subfeatures: MinimalFeature[];
12
+ subfeatures: {
13
+ type: string;
14
+ start: number;
15
+ end: number;
16
+ refName: string;
17
+ }[];
13
18
  start: number;
14
19
  end: number;
15
20
  };
@@ -8,81 +8,105 @@ export function generateUcscTranscript(data) {
8
8
  const feats = oldSubfeatures
9
9
  .filter(child => child.type === 'block')
10
10
  .sort((a, b) => a.start - b.start);
11
- for (const block of feats) {
12
- const start = block.start;
13
- const end = block.end;
14
- if (thickStart >= end) {
15
- subfeatures.push({
16
- type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
17
- start,
18
- end,
19
- refName,
20
- });
21
- }
22
- else if (thickStart > start && thickStart < end && thickEnd >= end) {
23
- subfeatures.push({
24
- type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
25
- start,
26
- end: thickStart,
27
- refName,
28
- }, {
29
- type: 'CDS',
30
- phase: 0,
31
- start: thickStart,
32
- end,
33
- refName,
34
- });
35
- }
36
- else if (thickStart <= start && thickEnd >= end) {
37
- subfeatures.push({
38
- type: 'CDS',
39
- phase: 0,
40
- start,
41
- end,
42
- refName,
43
- });
44
- }
45
- else if (thickStart > start && thickStart < end && thickEnd < end) {
46
- subfeatures.push({
47
- type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
48
- start,
49
- end: thickStart,
50
- refName,
51
- }, {
52
- type: 'CDS',
53
- phase: 0,
54
- start: thickStart,
55
- end: thickEnd,
56
- refName,
57
- }, {
58
- type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
59
- start: thickEnd,
60
- end,
61
- refName,
62
- });
63
- }
64
- else if (thickStart <= start && thickEnd > start && thickEnd < end) {
65
- subfeatures.push({
66
- type: 'CDS',
67
- phase: 0,
68
- start,
69
- end: thickEnd,
70
- refName,
71
- }, {
72
- type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
73
- start: thickEnd,
74
- end,
75
- refName,
76
- });
77
- }
78
- else if (thickEnd <= start) {
79
- subfeatures.push({
80
- type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
81
- start,
82
- end,
83
- refName,
84
- });
11
+ const { cdsEndStat, cdsStartStat } = rest2;
12
+ if (cdsStartStat === 'none' && cdsEndStat === 'none') {
13
+ return {
14
+ ...rest2,
15
+ uniqueId,
16
+ strand,
17
+ type: 'transcript',
18
+ refName,
19
+ subfeatures: feats.map(e => ({
20
+ ...e,
21
+ type: 'exon',
22
+ })),
23
+ };
24
+ }
25
+ else {
26
+ for (const block of feats) {
27
+ const start = block.start;
28
+ const end = block.end;
29
+ if (thickStart >= end) {
30
+ subfeatures.push({
31
+ type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
32
+ start,
33
+ end,
34
+ refName,
35
+ });
36
+ }
37
+ else if (thickStart > start && thickStart < end && thickEnd >= end) {
38
+ subfeatures.push({
39
+ type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
40
+ start,
41
+ end: thickStart,
42
+ refName,
43
+ }, {
44
+ type: 'CDS',
45
+ phase: 0,
46
+ start: thickStart,
47
+ end,
48
+ refName,
49
+ });
50
+ }
51
+ else if (thickStart <= start && thickEnd >= end) {
52
+ subfeatures.push({
53
+ type: 'CDS',
54
+ phase: 0,
55
+ start,
56
+ end,
57
+ refName,
58
+ });
59
+ }
60
+ else if (thickStart > start && thickStart < end && thickEnd < end) {
61
+ subfeatures.push({
62
+ type: `${strand > 0 ? 'five' : 'three'}_prime_UTR`,
63
+ start,
64
+ end: thickStart,
65
+ refName,
66
+ }, {
67
+ type: 'CDS',
68
+ phase: 0,
69
+ start: thickStart,
70
+ end: thickEnd,
71
+ refName,
72
+ }, {
73
+ type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
74
+ start: thickEnd,
75
+ end,
76
+ refName,
77
+ });
78
+ }
79
+ else if (thickStart <= start && thickEnd > start && thickEnd < end) {
80
+ subfeatures.push({
81
+ type: 'CDS',
82
+ phase: 0,
83
+ start,
84
+ end: thickEnd,
85
+ refName,
86
+ }, {
87
+ type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
88
+ start: thickEnd,
89
+ end,
90
+ refName,
91
+ });
92
+ }
93
+ else if (thickEnd <= start) {
94
+ subfeatures.push({
95
+ type: `${strand > 0 ? 'three' : 'five'}_prime_UTR`,
96
+ start,
97
+ end,
98
+ refName,
99
+ });
100
+ }
85
101
  }
102
+ return {
103
+ ...rest2,
104
+ uniqueId,
105
+ strand,
106
+ type: 'mRNA',
107
+ refName,
108
+ subfeatures,
109
+ };
86
110
  }
87
111
  return {
88
112
  ...rest2,
package/esm/util.d.ts CHANGED
@@ -89,7 +89,12 @@ export declare function featureData({ line, colRef, colStart, colEnd, scoreColum
89
89
  strand: number;
90
90
  type: string;
91
91
  refName: string;
92
- subfeatures: import("./types").MinimalFeature[];
92
+ subfeatures: {
93
+ type: string;
94
+ start: number;
95
+ end: number;
96
+ refName: string;
97
+ }[];
93
98
  start: number;
94
99
  end: number;
95
100
  } | {
@@ -182,7 +187,12 @@ export declare function featureData2({ splitLine, refName, start, end, parser, u
182
187
  strand: number;
183
188
  type: string;
184
189
  refName: string;
185
- subfeatures: import("./types").MinimalFeature[];
190
+ subfeatures: {
191
+ type: string;
192
+ start: number;
193
+ end: number;
194
+ refName: string;
195
+ }[];
186
196
  start: number;
187
197
  end: number;
188
198
  } | {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-bed",
3
- "version": "3.4.0",
3
+ "version": "3.5.1",
4
4
  "description": "JBrowse 2 bed adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -39,9 +39,9 @@
39
39
  "@flatten-js/interval-tree": "^1.0.15",
40
40
  "@gmod/bbi": "^7.0.0",
41
41
  "@gmod/bed": "^2.1.2",
42
- "@gmod/bgzf-filehandle": "^3.0.2",
42
+ "@gmod/bgzf-filehandle": "^4.0.0",
43
43
  "@gmod/tabix": "^3.0.1",
44
- "@jbrowse/core": "^3.4.0",
44
+ "@jbrowse/core": "^3.5.1",
45
45
  "mobx": "^6.0.0",
46
46
  "mobx-react": "^9.0.0",
47
47
  "mobx-state-tree": "^5.0.0",
@@ -53,5 +53,5 @@
53
53
  "distModule": "esm/index.js",
54
54
  "srcModule": "src/index.ts",
55
55
  "module": "esm/index.js",
56
- "gitHead": "a9f1ac35fc2dd810bae92cdaf1fc19995bee4413"
56
+ "gitHead": "cb8859da9d838ad2594964777c5c54f385d98f5e"
57
57
  }