@jbrowse/plugin-bed 3.0.1 → 3.0.3

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.
@@ -127,9 +127,12 @@ class BedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
127
127
  return (0, rxjs_1.ObservableCreate)(async (observer) => {
128
128
  const { start, end, refName } = query;
129
129
  const intervalTree = await this.loadFeatureIntervalTree(refName);
130
- intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]).forEach(f => {
131
- observer.next(f);
132
- });
130
+ const features = intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]);
131
+ if (features) {
132
+ for (const f of features) {
133
+ observer.next(f);
134
+ }
135
+ }
133
136
  observer.complete();
134
137
  }, opts.stopToken);
135
138
  }
@@ -11,9 +11,33 @@ export default class BedTabixAdapter extends BaseFeatureDataAdapter {
11
11
  protected columnNames: string[];
12
12
  protected scoreColumn: string;
13
13
  static capabilities: string[];
14
+ setupP?: Promise<{
15
+ meta: Awaited<ReturnType<TabixIndexedFile['getMetadata']>>;
16
+ }>;
14
17
  constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
15
18
  getRefNames(opts?: BaseOptions): Promise<string[]>;
16
- getHeader(): Promise<string>;
19
+ getHeader(opts?: BaseOptions): Promise<string>;
20
+ getMetadataPre2(_opts?: BaseOptions): Promise<{
21
+ meta: Awaited<ReturnType<TabixIndexedFile["getMetadata"]>>;
22
+ }>;
23
+ getMetadataPre(): Promise<{
24
+ meta: {
25
+ [key: string]: any;
26
+ refNameToId: Record<string, number>;
27
+ refIdToName: string[];
28
+ metaChar: string | null;
29
+ columnNumbers: {
30
+ ref: number;
31
+ start: number;
32
+ end: number;
33
+ };
34
+ coordinateType: string;
35
+ format: string;
36
+ };
37
+ }>;
38
+ getMetadata(opts?: BaseOptions): Promise<{
39
+ meta: Awaited<ReturnType<TabixIndexedFile["getMetadata"]>>;
40
+ }>;
17
41
  getNames(): Promise<string[] | undefined>;
18
42
  getFeatures(query: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
19
43
  freeResources(): void;
@@ -32,14 +32,31 @@ class BedTabixAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
32
32
  async getRefNames(opts = {}) {
33
33
  return this.bed.getReferenceSequenceNames(opts);
34
34
  }
35
- async getHeader() {
36
- return this.bed.getHeader();
35
+ async getHeader(opts) {
36
+ return this.bed.getHeader(opts);
37
+ }
38
+ async getMetadataPre2(_opts) {
39
+ if (!this.setupP) {
40
+ this.setupP = this.getMetadataPre().catch((e) => {
41
+ this.setupP = undefined;
42
+ throw e;
43
+ });
44
+ }
45
+ return this.setupP;
46
+ }
47
+ async getMetadataPre() {
48
+ const meta = await this.bed.getMetadata();
49
+ return { meta };
50
+ }
51
+ async getMetadata(opts) {
52
+ const { statusCallback = () => { } } = opts || {};
53
+ return (0, util_1.updateStatus)('Downloading index', statusCallback, () => this.getMetadataPre2(opts));
37
54
  }
38
55
  async getNames() {
39
56
  if (this.columnNames.length) {
40
57
  return this.columnNames;
41
58
  }
42
- const header = await this.bed.getHeader();
59
+ const header = await this.getHeader();
43
60
  const defs = header.split(/\n|\r\n|\r/).filter(f => !!f);
44
61
  const defline = defs.at(-1);
45
62
  return (defline === null || defline === void 0 ? void 0 : defline.includes('\t'))
@@ -49,10 +66,10 @@ class BedTabixAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
49
66
  .map(f => f.trim())
50
67
  : undefined;
51
68
  }
52
- getFeatures(query, opts = {}) {
53
- const { stopToken } = opts;
69
+ getFeatures(query, opts) {
70
+ const { stopToken, statusCallback = () => { } } = opts || {};
54
71
  return (0, rxjs_1.ObservableCreate)(async (observer) => {
55
- const meta = await this.bed.getMetadata();
72
+ const { meta } = await this.getMetadata();
56
73
  const { columnNumbers } = meta;
57
74
  const colRef = columnNumbers.ref - 1;
58
75
  const colStart = columnNumbers.start - 1;
@@ -60,7 +77,7 @@ class BedTabixAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
60
77
  const names = await this.getNames();
61
78
  let start = performance.now();
62
79
  (0, stopToken_1.checkStopToken)(stopToken);
63
- await this.bed.getLines(query.refName, query.start, query.end, {
80
+ await (0, util_1.updateStatus)('Downloading features', statusCallback, () => this.bed.getLines(query.refName, query.start, query.end, {
64
81
  lineCallback: (line, fileOffset) => {
65
82
  if (performance.now() - start > 200) {
66
83
  (0, stopToken_1.checkStopToken)(stopToken);
@@ -77,10 +94,10 @@ class BedTabixAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
77
94
  names,
78
95
  })));
79
96
  },
80
- stopToken: opts.stopToken,
81
- });
97
+ stopToken,
98
+ }));
82
99
  observer.complete();
83
- }, opts.stopToken);
100
+ }, stopToken);
84
101
  }
85
102
  freeResources() { }
86
103
  }
@@ -67,17 +67,18 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
67
67
  }
68
68
  async getFeaturesHelper({ query, opts, observer, allowRedispatch, originalQuery = query, }) {
69
69
  var _a;
70
- const { stopToken } = opts;
70
+ const { stopToken, statusCallback = () => { } } = opts;
71
71
  const scoreColumn = this.getConf('scoreColumn');
72
72
  const aggregateField = this.getConf('aggregateField');
73
- const { parser, bigbed } = await this.configure(opts);
74
- const feats = await bigbed.getFeatures(query.refName, query.start, query.end, {
73
+ const { parser, bigbed } = await (0, util_1.updateStatus)('Downloading header', statusCallback, () => this.configure(opts));
74
+ const feats = await (0, util_1.updateStatus)('Downloading features', statusCallback, () => bigbed.getFeatures(query.refName, query.start, query.end, {
75
75
  stopToken,
76
76
  basesPerSpan: query.end - query.start,
77
- });
77
+ }));
78
78
  if (allowRedispatch && feats.length) {
79
79
  let minStart = Number.POSITIVE_INFINITY;
80
80
  let maxEnd = Number.NEGATIVE_INFINITY;
81
+ let hasAnyAggregationField = false;
81
82
  for (const feat of feats) {
82
83
  if (feat.start < minStart) {
83
84
  minStart = feat.start;
@@ -85,8 +86,12 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
85
86
  if (feat.end > maxEnd) {
86
87
  maxEnd = feat.end;
87
88
  }
89
+ if (feat[aggregateField]) {
90
+ hasAnyAggregationField = true;
91
+ }
88
92
  }
89
- if (maxEnd > query.end || minStart < query.start) {
93
+ if (hasAnyAggregationField &&
94
+ (maxEnd > query.end || minStart < query.start)) {
90
95
  await this.getFeaturesHelper({
91
96
  query: {
92
97
  ...query,
@@ -112,7 +117,9 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
112
117
  `${feat.end}`,
113
118
  ...(((_a = feat.rest) === null || _a === void 0 ? void 0 : _a.split('\t')) || []),
114
119
  ];
115
- const data = parser.parseLine(splitLine, { uniqueId: feat.uniqueId });
120
+ const data = parser.parseLine(splitLine, {
121
+ uniqueId: feat.uniqueId,
122
+ });
116
123
  const aggr = data[aggregateField];
117
124
  if (!parentAggregation[aggr]) {
118
125
  parentAggregation[aggr] = [];
@@ -122,9 +122,12 @@ class BedAdapter extends BaseFeatureDataAdapter {
122
122
  return ObservableCreate(async (observer) => {
123
123
  const { start, end, refName } = query;
124
124
  const intervalTree = await this.loadFeatureIntervalTree(refName);
125
- intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]).forEach(f => {
126
- observer.next(f);
127
- });
125
+ const features = intervalTree === null || intervalTree === void 0 ? void 0 : intervalTree.search([start, end]);
126
+ if (features) {
127
+ for (const f of features) {
128
+ observer.next(f);
129
+ }
130
+ }
128
131
  observer.complete();
129
132
  }, opts.stopToken);
130
133
  }
@@ -11,9 +11,33 @@ export default class BedTabixAdapter extends BaseFeatureDataAdapter {
11
11
  protected columnNames: string[];
12
12
  protected scoreColumn: string;
13
13
  static capabilities: string[];
14
+ setupP?: Promise<{
15
+ meta: Awaited<ReturnType<TabixIndexedFile['getMetadata']>>;
16
+ }>;
14
17
  constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
15
18
  getRefNames(opts?: BaseOptions): Promise<string[]>;
16
- getHeader(): Promise<string>;
19
+ getHeader(opts?: BaseOptions): Promise<string>;
20
+ getMetadataPre2(_opts?: BaseOptions): Promise<{
21
+ meta: Awaited<ReturnType<TabixIndexedFile["getMetadata"]>>;
22
+ }>;
23
+ getMetadataPre(): Promise<{
24
+ meta: {
25
+ [key: string]: any;
26
+ refNameToId: Record<string, number>;
27
+ refIdToName: string[];
28
+ metaChar: string | null;
29
+ columnNumbers: {
30
+ ref: number;
31
+ start: number;
32
+ end: number;
33
+ };
34
+ coordinateType: string;
35
+ format: string;
36
+ };
37
+ }>;
38
+ getMetadata(opts?: BaseOptions): Promise<{
39
+ meta: Awaited<ReturnType<TabixIndexedFile["getMetadata"]>>;
40
+ }>;
17
41
  getNames(): Promise<string[] | undefined>;
18
42
  getFeatures(query: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
19
43
  freeResources(): void;
@@ -1,7 +1,7 @@
1
1
  import BED from '@gmod/bed';
2
2
  import { TabixIndexedFile } from '@gmod/tabix';
3
3
  import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
4
- import { SimpleFeature } from '@jbrowse/core/util';
4
+ import { SimpleFeature, updateStatus } from '@jbrowse/core/util';
5
5
  import { openLocation } from '@jbrowse/core/util/io';
6
6
  import { ObservableCreate } from '@jbrowse/core/util/rxjs';
7
7
  import { checkStopToken } from '@jbrowse/core/util/stopToken';
@@ -27,14 +27,31 @@ class BedTabixAdapter extends BaseFeatureDataAdapter {
27
27
  async getRefNames(opts = {}) {
28
28
  return this.bed.getReferenceSequenceNames(opts);
29
29
  }
30
- async getHeader() {
31
- return this.bed.getHeader();
30
+ async getHeader(opts) {
31
+ return this.bed.getHeader(opts);
32
+ }
33
+ async getMetadataPre2(_opts) {
34
+ if (!this.setupP) {
35
+ this.setupP = this.getMetadataPre().catch((e) => {
36
+ this.setupP = undefined;
37
+ throw e;
38
+ });
39
+ }
40
+ return this.setupP;
41
+ }
42
+ async getMetadataPre() {
43
+ const meta = await this.bed.getMetadata();
44
+ return { meta };
45
+ }
46
+ async getMetadata(opts) {
47
+ const { statusCallback = () => { } } = opts || {};
48
+ return updateStatus('Downloading index', statusCallback, () => this.getMetadataPre2(opts));
32
49
  }
33
50
  async getNames() {
34
51
  if (this.columnNames.length) {
35
52
  return this.columnNames;
36
53
  }
37
- const header = await this.bed.getHeader();
54
+ const header = await this.getHeader();
38
55
  const defs = header.split(/\n|\r\n|\r/).filter(f => !!f);
39
56
  const defline = defs.at(-1);
40
57
  return (defline === null || defline === void 0 ? void 0 : defline.includes('\t'))
@@ -44,10 +61,10 @@ class BedTabixAdapter extends BaseFeatureDataAdapter {
44
61
  .map(f => f.trim())
45
62
  : undefined;
46
63
  }
47
- getFeatures(query, opts = {}) {
48
- const { stopToken } = opts;
64
+ getFeatures(query, opts) {
65
+ const { stopToken, statusCallback = () => { } } = opts || {};
49
66
  return ObservableCreate(async (observer) => {
50
- const meta = await this.bed.getMetadata();
67
+ const { meta } = await this.getMetadata();
51
68
  const { columnNumbers } = meta;
52
69
  const colRef = columnNumbers.ref - 1;
53
70
  const colStart = columnNumbers.start - 1;
@@ -55,7 +72,7 @@ class BedTabixAdapter extends BaseFeatureDataAdapter {
55
72
  const names = await this.getNames();
56
73
  let start = performance.now();
57
74
  checkStopToken(stopToken);
58
- await this.bed.getLines(query.refName, query.start, query.end, {
75
+ await updateStatus('Downloading features', statusCallback, () => this.bed.getLines(query.refName, query.start, query.end, {
59
76
  lineCallback: (line, fileOffset) => {
60
77
  if (performance.now() - start > 200) {
61
78
  checkStopToken(stopToken);
@@ -72,10 +89,10 @@ class BedTabixAdapter extends BaseFeatureDataAdapter {
72
89
  names,
73
90
  })));
74
91
  },
75
- stopToken: opts.stopToken,
76
- });
92
+ stopToken,
93
+ }));
77
94
  observer.complete();
78
- }, opts.stopToken);
95
+ }, stopToken);
79
96
  }
80
97
  freeResources() { }
81
98
  }
@@ -1,7 +1,7 @@
1
1
  import { BigBed } from '@gmod/bbi';
2
2
  import BED from '@gmod/bed';
3
3
  import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
4
- import { SimpleFeature, doesIntersect2, max, min } from '@jbrowse/core/util';
4
+ import { SimpleFeature, doesIntersect2, max, min, updateStatus, } from '@jbrowse/core/util';
5
5
  import { openLocation } from '@jbrowse/core/util/io';
6
6
  import { ObservableCreate } from '@jbrowse/core/util/rxjs';
7
7
  import { firstValueFrom, toArray } from 'rxjs';
@@ -62,17 +62,18 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
62
62
  }
63
63
  async getFeaturesHelper({ query, opts, observer, allowRedispatch, originalQuery = query, }) {
64
64
  var _a;
65
- const { stopToken } = opts;
65
+ const { stopToken, statusCallback = () => { } } = opts;
66
66
  const scoreColumn = this.getConf('scoreColumn');
67
67
  const aggregateField = this.getConf('aggregateField');
68
- const { parser, bigbed } = await this.configure(opts);
69
- const feats = await bigbed.getFeatures(query.refName, query.start, query.end, {
68
+ const { parser, bigbed } = await updateStatus('Downloading header', statusCallback, () => this.configure(opts));
69
+ const feats = await updateStatus('Downloading features', statusCallback, () => bigbed.getFeatures(query.refName, query.start, query.end, {
70
70
  stopToken,
71
71
  basesPerSpan: query.end - query.start,
72
- });
72
+ }));
73
73
  if (allowRedispatch && feats.length) {
74
74
  let minStart = Number.POSITIVE_INFINITY;
75
75
  let maxEnd = Number.NEGATIVE_INFINITY;
76
+ let hasAnyAggregationField = false;
76
77
  for (const feat of feats) {
77
78
  if (feat.start < minStart) {
78
79
  minStart = feat.start;
@@ -80,8 +81,12 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
80
81
  if (feat.end > maxEnd) {
81
82
  maxEnd = feat.end;
82
83
  }
84
+ if (feat[aggregateField]) {
85
+ hasAnyAggregationField = true;
86
+ }
83
87
  }
84
- if (maxEnd > query.end || minStart < query.start) {
88
+ if (hasAnyAggregationField &&
89
+ (maxEnd > query.end || minStart < query.start)) {
85
90
  await this.getFeaturesHelper({
86
91
  query: {
87
92
  ...query,
@@ -107,7 +112,9 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
107
112
  `${feat.end}`,
108
113
  ...(((_a = feat.rest) === null || _a === void 0 ? void 0 : _a.split('\t')) || []),
109
114
  ];
110
- const data = parser.parseLine(splitLine, { uniqueId: feat.uniqueId });
115
+ const data = parser.parseLine(splitLine, {
116
+ uniqueId: feat.uniqueId,
117
+ });
111
118
  const aggr = data[aggregateField];
112
119
  if (!parentAggregation[aggr]) {
113
120
  parentAggregation[aggr] = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-bed",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
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.0.1",
44
+ "@jbrowse/core": "^3.0.3",
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": "aa2f1d1a89d2361c7fd1a93fe29506fa4554f5cc"
56
+ "gitHead": "f516540428282351d26e46743e69a724651bfb2c"
57
57
  }