@jbrowse/plugin-bed 3.1.0 → 3.3.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,7 @@
1
1
  declare const BedAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
2
  bedLocation: {
3
3
  type: string;
4
+ description: string;
4
5
  defaultValue: {
5
6
  uri: string;
6
7
  locationType: string;
@@ -5,6 +5,7 @@ function x() { }
5
5
  const BedAdapter = (0, configuration_1.ConfigurationSchema)('BedAdapter', {
6
6
  bedLocation: {
7
7
  type: 'fileLocation',
8
+ description: 'path to bed file, also allows gzipped bed',
8
9
  defaultValue: {
9
10
  uri: '/path/to/my.bed.gz',
10
11
  locationType: 'UriLocation',
@@ -119,9 +119,9 @@ class BedGraphAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
119
119
  return (0, rxjs_1.ObservableCreate)(async (observer) => {
120
120
  const { start, end, refName } = query;
121
121
  const intervalTree = await this.loadFeatureIntervalTree(refName);
122
- intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]).forEach(f => {
123
- observer.next(f);
124
- });
122
+ for (const feature of (intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end])) || []) {
123
+ observer.next(feature);
124
+ }
125
125
  observer.complete();
126
126
  });
127
127
  }
@@ -40,5 +40,4 @@ export default class BedTabixAdapter extends BaseFeatureDataAdapter {
40
40
  }>;
41
41
  getNames(): Promise<string[] | undefined>;
42
42
  getFeatures(query: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
43
- freeResources(): void;
44
43
  }
@@ -99,7 +99,6 @@ class BedTabixAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
99
99
  observer.complete();
100
100
  }, stopToken);
101
101
  }
102
- freeResources() { }
103
102
  }
104
103
  BedTabixAdapter.capabilities = ['getFeatures', 'getRefNames'];
105
104
  exports.default = BedTabixAdapter;
@@ -103,9 +103,9 @@ class BedpeAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
103
103
  return (0, rxjs_1.ObservableCreate)(async (observer) => {
104
104
  const { start, end, refName } = query;
105
105
  const intervalTree = await this.loadFeatureTree(refName);
106
- intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]).forEach(f => {
106
+ for (const f of (intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end])) || []) {
107
107
  observer.next(f);
108
- });
108
+ }
109
109
  observer.complete();
110
110
  }, opts.stopToken);
111
111
  }
@@ -1,6 +1,7 @@
1
1
  declare const BedpeAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
2
  bedpeLocation: {
3
3
  type: string;
4
+ description: string;
4
5
  defaultValue: {
5
6
  uri: string;
6
7
  locationType: string;
@@ -5,6 +5,7 @@ function x() { }
5
5
  const BedpeAdapter = (0, configuration_1.ConfigurationSchema)('BedpeAdapter', {
6
6
  bedpeLocation: {
7
7
  type: 'fileLocation',
8
+ description: 'can be plaintext or gzipped, not indexed so loaded into memory on startup',
8
9
  defaultValue: {
9
10
  uri: '/path/to/my.bedpe.gz',
10
11
  locationType: 'UriLocation',
@@ -9,7 +9,7 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
9
9
  private cachedP?;
10
10
  configurePre(opts?: BaseOptions): Promise<{
11
11
  bigbed: BigBed;
12
- header: import("@gmod/bbi").Header;
12
+ header: import("@gmod/bbi/dist/types").BigWigHeaderWithRefNames;
13
13
  parser: BED;
14
14
  }>;
15
15
  configure(opts?: BaseOptions): Promise<{
@@ -18,6 +18,11 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
18
18
  parser: BED;
19
19
  }>;
20
20
  getRefNames(opts?: BaseOptions): Promise<string[]>;
21
+ getRefNameAliases(opts?: BaseOptions): Promise<{
22
+ refName: unknown;
23
+ aliases: unknown[];
24
+ override: boolean;
25
+ }[]>;
21
26
  getData(): Promise<Feature[]>;
22
27
  getHeader(opts?: BaseOptions): Promise<{
23
28
  version: number;
@@ -40,6 +40,22 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
40
40
  const { header } = await this.configure(opts);
41
41
  return Object.keys(header.refsByName);
42
42
  }
43
+ async getRefNameAliases(opts) {
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({
46
+ assemblyName: '',
47
+ refName: r,
48
+ start: 0,
49
+ end: 1,
50
+ }).pipe((0, rxjs_2.toArray)())))[0]));
51
+ return ret
52
+ .map(r => r.toJSON())
53
+ .map(r => ({
54
+ refName: r.ucsc,
55
+ aliases: [r.ncbi, r.refseq, r.genbank],
56
+ override: true,
57
+ }));
58
+ }
43
59
  async getData() {
44
60
  const refNames = await this.getRefNames();
45
61
  const features = [];
@@ -67,46 +83,15 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
67
83
  }
68
84
  async getFeaturesHelper({ query, opts, observer, allowRedispatch, originalQuery = query, }) {
69
85
  var _a;
70
- const { stopToken, statusCallback = () => { } } = opts;
86
+ const { statusCallback = () => { } } = opts;
71
87
  const scoreColumn = this.getConf('scoreColumn');
72
88
  const aggregateField = this.getConf('aggregateField');
73
89
  const { parser, bigbed } = await (0, util_1.updateStatus)('Downloading header', statusCallback, () => this.configure(opts));
74
90
  const feats = await (0, util_1.updateStatus)('Downloading features', statusCallback, () => bigbed.getFeatures(query.refName, query.start, query.end, {
75
- stopToken,
76
91
  basesPerSpan: query.end - query.start,
77
92
  }));
78
- if (allowRedispatch && feats.length) {
79
- let minStart = Number.POSITIVE_INFINITY;
80
- let maxEnd = Number.NEGATIVE_INFINITY;
81
- let hasAnyAggregationField = false;
82
- for (const feat of feats) {
83
- if (feat.start < minStart) {
84
- minStart = feat.start;
85
- }
86
- if (feat.end > maxEnd) {
87
- maxEnd = feat.end;
88
- }
89
- if (feat[aggregateField]) {
90
- hasAnyAggregationField = true;
91
- }
92
- }
93
- if (hasAnyAggregationField &&
94
- (maxEnd > query.end || minStart < query.start)) {
95
- await this.getFeaturesHelper({
96
- query: {
97
- ...query,
98
- start: minStart,
99
- end: maxEnd,
100
- },
101
- opts,
102
- observer,
103
- allowRedispatch: false,
104
- originalQuery: query,
105
- });
106
- return;
107
- }
108
- }
109
93
  const parentAggregation = {};
94
+ const parentAggregationFlat = [];
110
95
  if (feats.some(f => f.uniqueId === undefined)) {
111
96
  throw new Error('found uniqueId undefined');
112
97
  }
@@ -137,6 +122,7 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
137
122
  });
138
123
  if (aggr) {
139
124
  parentAggregation[aggr].push(f);
125
+ parentAggregationFlat.push(f);
140
126
  }
141
127
  else {
142
128
  if ((0, util_1.doesIntersect2)(f.start, f.end, originalQuery.start, originalQuery.end)) {
@@ -147,17 +133,44 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
147
133
  }
148
134
  }
149
135
  }
136
+ if (allowRedispatch && parentAggregationFlat.length) {
137
+ let minStart = Number.POSITIVE_INFINITY;
138
+ let maxEnd = Number.NEGATIVE_INFINITY;
139
+ for (const feat of parentAggregationFlat) {
140
+ if (feat.start < minStart) {
141
+ minStart = feat.start;
142
+ }
143
+ if (feat.end > maxEnd) {
144
+ maxEnd = feat.end;
145
+ }
146
+ }
147
+ if (maxEnd > query.end || minStart < query.start) {
148
+ await this.getFeaturesHelper({
149
+ query: {
150
+ ...query,
151
+ start: minStart - 500000,
152
+ end: maxEnd + 500000,
153
+ },
154
+ opts,
155
+ observer,
156
+ allowRedispatch: false,
157
+ originalQuery: query,
158
+ });
159
+ return;
160
+ }
161
+ }
150
162
  Object.entries(parentAggregation).map(([name, subfeatures]) => {
163
+ var _a, _b;
151
164
  const s = (0, util_1.min)(subfeatures.map(f => f.start));
152
165
  const e = (0, util_1.max)(subfeatures.map(f => f.end));
153
166
  if ((0, util_1.doesIntersect2)(s, e, originalQuery.start, originalQuery.end)) {
154
- const { uniqueId, strand } = subfeatures[0];
167
+ const subs = subfeatures.sort((a, b) => a.uniqueId.localeCompare(b.uniqueId));
155
168
  observer.next(new util_1.SimpleFeature({
156
- id: `${this.id}-${uniqueId}-parent`,
169
+ id: `${this.id}-${(_a = subs[0]) === null || _a === void 0 ? void 0 : _a.uniqueId}-parent`,
157
170
  data: {
158
171
  type: 'gene',
159
- subfeatures,
160
- strand,
172
+ subfeatures: subs,
173
+ strand: ((_b = subs[0]) === null || _b === void 0 ? void 0 : _b.strand) || 1,
161
174
  name,
162
175
  start: s,
163
176
  end: e,
@@ -172,7 +185,11 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
172
185
  return (0, rxjs_1.ObservableCreate)(async (observer) => {
173
186
  try {
174
187
  await this.getFeaturesHelper({
175
- query,
188
+ query: {
189
+ ...query,
190
+ start: query.start,
191
+ end: query.end,
192
+ },
176
193
  opts,
177
194
  observer,
178
195
  allowRedispatch: true,
@@ -1,6 +1,7 @@
1
1
  declare const BedAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
2
  bedLocation: {
3
3
  type: string;
4
+ description: string;
4
5
  defaultValue: {
5
6
  uri: string;
6
7
  locationType: string;
@@ -3,6 +3,7 @@ function x() { }
3
3
  const BedAdapter = ConfigurationSchema('BedAdapter', {
4
4
  bedLocation: {
5
5
  type: 'fileLocation',
6
+ description: 'path to bed file, also allows gzipped bed',
6
7
  defaultValue: {
7
8
  uri: '/path/to/my.bed.gz',
8
9
  locationType: 'UriLocation',
@@ -114,9 +114,9 @@ export default class BedGraphAdapter extends BaseFeatureDataAdapter {
114
114
  return ObservableCreate(async (observer) => {
115
115
  const { start, end, refName } = query;
116
116
  const intervalTree = await this.loadFeatureIntervalTree(refName);
117
- intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]).forEach(f => {
118
- observer.next(f);
119
- });
117
+ for (const feature of (intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end])) || []) {
118
+ observer.next(feature);
119
+ }
120
120
  observer.complete();
121
121
  });
122
122
  }
@@ -40,5 +40,4 @@ export default class BedTabixAdapter extends BaseFeatureDataAdapter {
40
40
  }>;
41
41
  getNames(): Promise<string[] | undefined>;
42
42
  getFeatures(query: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
43
- freeResources(): void;
44
43
  }
@@ -94,7 +94,6 @@ class BedTabixAdapter extends BaseFeatureDataAdapter {
94
94
  observer.complete();
95
95
  }, stopToken);
96
96
  }
97
- freeResources() { }
98
97
  }
99
98
  BedTabixAdapter.capabilities = ['getFeatures', 'getRefNames'];
100
99
  export default BedTabixAdapter;
@@ -98,9 +98,9 @@ class BedpeAdapter extends BaseFeatureDataAdapter {
98
98
  return ObservableCreate(async (observer) => {
99
99
  const { start, end, refName } = query;
100
100
  const intervalTree = await this.loadFeatureTree(refName);
101
- intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]).forEach(f => {
101
+ for (const f of (intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end])) || []) {
102
102
  observer.next(f);
103
- });
103
+ }
104
104
  observer.complete();
105
105
  }, opts.stopToken);
106
106
  }
@@ -1,6 +1,7 @@
1
1
  declare const BedpeAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
2
  bedpeLocation: {
3
3
  type: string;
4
+ description: string;
4
5
  defaultValue: {
5
6
  uri: string;
6
7
  locationType: string;
@@ -3,6 +3,7 @@ function x() { }
3
3
  const BedpeAdapter = ConfigurationSchema('BedpeAdapter', {
4
4
  bedpeLocation: {
5
5
  type: 'fileLocation',
6
+ description: 'can be plaintext or gzipped, not indexed so loaded into memory on startup',
6
7
  defaultValue: {
7
8
  uri: '/path/to/my.bedpe.gz',
8
9
  locationType: 'UriLocation',
@@ -9,7 +9,7 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
9
9
  private cachedP?;
10
10
  configurePre(opts?: BaseOptions): Promise<{
11
11
  bigbed: BigBed;
12
- header: import("@gmod/bbi").Header;
12
+ header: import("@gmod/bbi/dist/types").BigWigHeaderWithRefNames;
13
13
  parser: BED;
14
14
  }>;
15
15
  configure(opts?: BaseOptions): Promise<{
@@ -18,6 +18,11 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
18
18
  parser: BED;
19
19
  }>;
20
20
  getRefNames(opts?: BaseOptions): Promise<string[]>;
21
+ getRefNameAliases(opts?: BaseOptions): Promise<{
22
+ refName: unknown;
23
+ aliases: unknown[];
24
+ override: boolean;
25
+ }[]>;
21
26
  getData(): Promise<Feature[]>;
22
27
  getHeader(opts?: BaseOptions): Promise<{
23
28
  version: number;
@@ -35,6 +35,22 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
35
35
  const { header } = await this.configure(opts);
36
36
  return Object.keys(header.refsByName);
37
37
  }
38
+ async getRefNameAliases(opts) {
39
+ const { header } = await this.configure(opts);
40
+ const ret = await Promise.all(Object.keys(header.refsByName).map(async (r) => (await firstValueFrom(this.getFeatures({
41
+ assemblyName: '',
42
+ refName: r,
43
+ start: 0,
44
+ end: 1,
45
+ }).pipe(toArray())))[0]));
46
+ return ret
47
+ .map(r => r.toJSON())
48
+ .map(r => ({
49
+ refName: r.ucsc,
50
+ aliases: [r.ncbi, r.refseq, r.genbank],
51
+ override: true,
52
+ }));
53
+ }
38
54
  async getData() {
39
55
  const refNames = await this.getRefNames();
40
56
  const features = [];
@@ -62,46 +78,15 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
62
78
  }
63
79
  async getFeaturesHelper({ query, opts, observer, allowRedispatch, originalQuery = query, }) {
64
80
  var _a;
65
- const { stopToken, statusCallback = () => { } } = opts;
81
+ const { statusCallback = () => { } } = opts;
66
82
  const scoreColumn = this.getConf('scoreColumn');
67
83
  const aggregateField = this.getConf('aggregateField');
68
84
  const { parser, bigbed } = await updateStatus('Downloading header', statusCallback, () => this.configure(opts));
69
85
  const feats = await updateStatus('Downloading features', statusCallback, () => bigbed.getFeatures(query.refName, query.start, query.end, {
70
- stopToken,
71
86
  basesPerSpan: query.end - query.start,
72
87
  }));
73
- if (allowRedispatch && feats.length) {
74
- let minStart = Number.POSITIVE_INFINITY;
75
- let maxEnd = Number.NEGATIVE_INFINITY;
76
- let hasAnyAggregationField = false;
77
- for (const feat of feats) {
78
- if (feat.start < minStart) {
79
- minStart = feat.start;
80
- }
81
- if (feat.end > maxEnd) {
82
- maxEnd = feat.end;
83
- }
84
- if (feat[aggregateField]) {
85
- hasAnyAggregationField = true;
86
- }
87
- }
88
- if (hasAnyAggregationField &&
89
- (maxEnd > query.end || minStart < query.start)) {
90
- await this.getFeaturesHelper({
91
- query: {
92
- ...query,
93
- start: minStart,
94
- end: maxEnd,
95
- },
96
- opts,
97
- observer,
98
- allowRedispatch: false,
99
- originalQuery: query,
100
- });
101
- return;
102
- }
103
- }
104
88
  const parentAggregation = {};
89
+ const parentAggregationFlat = [];
105
90
  if (feats.some(f => f.uniqueId === undefined)) {
106
91
  throw new Error('found uniqueId undefined');
107
92
  }
@@ -132,6 +117,7 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
132
117
  });
133
118
  if (aggr) {
134
119
  parentAggregation[aggr].push(f);
120
+ parentAggregationFlat.push(f);
135
121
  }
136
122
  else {
137
123
  if (doesIntersect2(f.start, f.end, originalQuery.start, originalQuery.end)) {
@@ -142,17 +128,44 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
142
128
  }
143
129
  }
144
130
  }
131
+ if (allowRedispatch && parentAggregationFlat.length) {
132
+ let minStart = Number.POSITIVE_INFINITY;
133
+ let maxEnd = Number.NEGATIVE_INFINITY;
134
+ for (const feat of parentAggregationFlat) {
135
+ if (feat.start < minStart) {
136
+ minStart = feat.start;
137
+ }
138
+ if (feat.end > maxEnd) {
139
+ maxEnd = feat.end;
140
+ }
141
+ }
142
+ if (maxEnd > query.end || minStart < query.start) {
143
+ await this.getFeaturesHelper({
144
+ query: {
145
+ ...query,
146
+ start: minStart - 500000,
147
+ end: maxEnd + 500000,
148
+ },
149
+ opts,
150
+ observer,
151
+ allowRedispatch: false,
152
+ originalQuery: query,
153
+ });
154
+ return;
155
+ }
156
+ }
145
157
  Object.entries(parentAggregation).map(([name, subfeatures]) => {
158
+ var _a, _b;
146
159
  const s = min(subfeatures.map(f => f.start));
147
160
  const e = max(subfeatures.map(f => f.end));
148
161
  if (doesIntersect2(s, e, originalQuery.start, originalQuery.end)) {
149
- const { uniqueId, strand } = subfeatures[0];
162
+ const subs = subfeatures.sort((a, b) => a.uniqueId.localeCompare(b.uniqueId));
150
163
  observer.next(new SimpleFeature({
151
- id: `${this.id}-${uniqueId}-parent`,
164
+ id: `${this.id}-${(_a = subs[0]) === null || _a === void 0 ? void 0 : _a.uniqueId}-parent`,
152
165
  data: {
153
166
  type: 'gene',
154
- subfeatures,
155
- strand,
167
+ subfeatures: subs,
168
+ strand: ((_b = subs[0]) === null || _b === void 0 ? void 0 : _b.strand) || 1,
156
169
  name,
157
170
  start: s,
158
171
  end: e,
@@ -167,7 +180,11 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
167
180
  return ObservableCreate(async (observer) => {
168
181
  try {
169
182
  await this.getFeaturesHelper({
170
- query,
183
+ query: {
184
+ ...query,
185
+ start: query.start,
186
+ end: query.end,
187
+ },
171
188
  opts,
172
189
  observer,
173
190
  allowRedispatch: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-bed",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "JBrowse 2 bed adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -41,7 +41,7 @@
41
41
  "@gmod/bed": "^2.1.2",
42
42
  "@gmod/bgzf-filehandle": "^2.0.1",
43
43
  "@gmod/tabix": "^2.0.0",
44
- "@jbrowse/core": "^3.1.0",
44
+ "@jbrowse/core": "^3.3.0",
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": "91492049ddea0aed90eb24d3c066c2d9f5a6b189"
56
+ "gitHead": "0bb64d8cc7ecdd167515308b31eec3d9acbc59e4"
57
57
  }