@jbrowse/plugin-bed 2.11.2 → 2.12.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.
- package/dist/BedAdapter/index.js +1 -1
- package/dist/BedTabixAdapter/index.js +1 -1
- package/dist/BedpeAdapter/BedpeAdapter.js +1 -2
- package/dist/BedpeAdapter/index.js +1 -1
- package/dist/BigBedAdapter/BigBedAdapter.d.ts +8 -6
- package/dist/BigBedAdapter/BigBedAdapter.js +111 -60
- package/dist/BigBedAdapter/configSchema.d.ts +8 -0
- package/dist/BigBedAdapter/configSchema.js +8 -0
- package/dist/BigBedAdapter/index.js +1 -1
- package/dist/util.d.ts +6 -5
- package/dist/util.js +6 -7
- package/esm/BigBedAdapter/BigBedAdapter.d.ts +8 -6
- package/esm/BigBedAdapter/BigBedAdapter.js +111 -60
- package/esm/BigBedAdapter/configSchema.d.ts +8 -0
- package/esm/BigBedAdapter/configSchema.js +8 -0
- package/esm/util.d.ts +6 -5
- package/esm/util.js +2 -2
- package/package.json +2 -2
package/dist/BedAdapter/index.js
CHANGED
|
@@ -26,6 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.default = BedAdapterF;
|
|
29
30
|
const AdapterType_1 = __importDefault(require("@jbrowse/core/pluggableElementTypes/AdapterType"));
|
|
30
31
|
const configSchema_1 = __importDefault(require("./configSchema"));
|
|
31
32
|
function BedAdapterF(pluginManager) {
|
|
@@ -36,4 +37,3 @@ function BedAdapterF(pluginManager) {
|
|
|
36
37
|
getAdapterClass: () => Promise.resolve().then(() => __importStar(require('./BedAdapter'))).then(r => r.default),
|
|
37
38
|
}));
|
|
38
39
|
}
|
|
39
|
-
exports.default = BedAdapterF;
|
|
@@ -26,6 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.default = BedTabixAdapterF;
|
|
29
30
|
const AdapterType_1 = __importDefault(require("@jbrowse/core/pluggableElementTypes/AdapterType"));
|
|
30
31
|
const configSchema_1 = __importDefault(require("./configSchema"));
|
|
31
32
|
function BedTabixAdapterF(pluginManager) {
|
|
@@ -36,4 +37,3 @@ function BedTabixAdapterF(pluginManager) {
|
|
|
36
37
|
getAdapterClass: () => Promise.resolve().then(() => __importStar(require('./BedTabixAdapter'))).then(r => r.default),
|
|
37
38
|
}));
|
|
38
39
|
}
|
|
39
|
-
exports.default = BedTabixAdapterF;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.featureData =
|
|
6
|
+
exports.featureData = featureData;
|
|
7
7
|
const BaseAdapter_1 = require("@jbrowse/core/data_adapters/BaseAdapter");
|
|
8
8
|
const io_1 = require("@jbrowse/core/util/io");
|
|
9
9
|
const rxjs_1 = require("@jbrowse/core/util/rxjs");
|
|
@@ -46,7 +46,6 @@ function featureData(line, uniqueId, flip, names) {
|
|
|
46
46
|
mate: { refName: ref2, start: start2, end: end2, strand: strand2 },
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
|
-
exports.featureData = featureData;
|
|
50
49
|
function parseStrand(strand) {
|
|
51
50
|
if (strand === '+') {
|
|
52
51
|
return 1;
|
|
@@ -26,6 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.default = BedpeAdapterF;
|
|
29
30
|
const AdapterType_1 = __importDefault(require("@jbrowse/core/pluggableElementTypes/AdapterType"));
|
|
30
31
|
const configSchema_1 = __importDefault(require("./configSchema"));
|
|
31
32
|
function BedpeAdapterF(pluginManager) {
|
|
@@ -36,4 +37,3 @@ function BedpeAdapterF(pluginManager) {
|
|
|
36
37
|
getAdapterClass: () => Promise.resolve().then(() => __importStar(require('./BedpeAdapter'))).then(r => r.default),
|
|
37
38
|
}));
|
|
38
39
|
}
|
|
39
|
-
exports.default = BedpeAdapterF;
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import { BigBed
|
|
1
|
+
import { BigBed } from '@gmod/bbi';
|
|
2
2
|
import BED from '@gmod/bed';
|
|
3
3
|
import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
4
4
|
import { Region } from '@jbrowse/core/util/types';
|
|
5
|
-
import { Feature } from '@jbrowse/core/util
|
|
5
|
+
import { Feature } from '@jbrowse/core/util';
|
|
6
|
+
import { Observer } from 'rxjs';
|
|
6
7
|
export default class BigBedAdapter extends BaseFeatureDataAdapter {
|
|
7
8
|
private cached?;
|
|
8
9
|
configurePre(opts?: BaseOptions): Promise<{
|
|
9
10
|
bigbed: BigBed;
|
|
10
|
-
header: Header;
|
|
11
|
+
header: import("@gmod/bbi").Header;
|
|
11
12
|
parser: BED;
|
|
12
13
|
}>;
|
|
13
14
|
configure(opts?: BaseOptions): Promise<{
|
|
14
15
|
bigbed: BigBed;
|
|
15
|
-
header:
|
|
16
|
+
header: Awaited<ReturnType<BigBed["getHeader"]>>;
|
|
16
17
|
parser: BED;
|
|
17
18
|
}>;
|
|
18
19
|
getRefNames(opts?: BaseOptions): Promise<string[]>;
|
|
19
20
|
getHeader(opts?: BaseOptions): Promise<{
|
|
20
|
-
version:
|
|
21
|
+
version: number;
|
|
21
22
|
fileType: string;
|
|
22
23
|
autoSql: {};
|
|
23
24
|
fields: {
|
|
24
25
|
[k: string]: string;
|
|
25
26
|
};
|
|
26
27
|
}>;
|
|
27
|
-
|
|
28
|
+
getFeaturesHelper(query: Region, opts: BaseOptions | undefined, observer: Observer<Feature>, allowRedispatch: boolean, originalQuery?: Region): Promise<void>;
|
|
29
|
+
getFeatures(query: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
|
|
28
30
|
freeResources(): void;
|
|
29
31
|
}
|
|
@@ -8,10 +8,9 @@ const bed_1 = __importDefault(require("@gmod/bed"));
|
|
|
8
8
|
const BaseAdapter_1 = require("@jbrowse/core/data_adapters/BaseAdapter");
|
|
9
9
|
const io_1 = require("@jbrowse/core/util/io");
|
|
10
10
|
const rxjs_1 = require("@jbrowse/core/util/rxjs");
|
|
11
|
-
const
|
|
12
|
-
const operators_1 = require("rxjs/operators");
|
|
11
|
+
const util_1 = require("@jbrowse/core/util");
|
|
13
12
|
// locals
|
|
14
|
-
const
|
|
13
|
+
const util_2 = require("../util");
|
|
15
14
|
class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
|
|
16
15
|
async configurePre(opts) {
|
|
17
16
|
const pm = this.pluginManager;
|
|
@@ -37,7 +36,6 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
|
|
|
37
36
|
}
|
|
38
37
|
async getHeader(opts) {
|
|
39
38
|
const { parser, header } = await this.configure(opts);
|
|
40
|
-
// @ts-expect-error
|
|
41
39
|
const { version, fileType } = header;
|
|
42
40
|
const { fields, ...rest } = parser.autoSql;
|
|
43
41
|
return {
|
|
@@ -47,68 +45,121 @@ class BigBedAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
|
|
|
47
45
|
fields: Object.fromEntries(fields.map(({ name, comment }) => [name, comment])),
|
|
48
46
|
};
|
|
49
47
|
}
|
|
50
|
-
|
|
48
|
+
async getFeaturesHelper(query, opts = {}, observer, allowRedispatch, originalQuery = query) {
|
|
51
49
|
const { signal } = opts;
|
|
52
50
|
const scoreColumn = this.getConf('scoreColumn');
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
const aggregateField = this.getConf('aggregateField');
|
|
52
|
+
const { parser, bigbed } = await this.configure(opts);
|
|
53
|
+
const feats = await bigbed.getFeatures(query.refName, query.start, query.end, {
|
|
54
|
+
signal,
|
|
55
|
+
basesPerSpan: query.end - query.start,
|
|
56
|
+
});
|
|
57
|
+
if (allowRedispatch && feats.length) {
|
|
58
|
+
let minStart = Infinity;
|
|
59
|
+
let maxEnd = -Infinity;
|
|
60
|
+
for (const feat of feats) {
|
|
61
|
+
if (feat.start < minStart) {
|
|
62
|
+
minStart = feat.start;
|
|
63
|
+
}
|
|
64
|
+
if (feat.end > maxEnd) {
|
|
65
|
+
maxEnd = feat.end;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (maxEnd > query.end || minStart < query.start) {
|
|
69
|
+
await this.getFeaturesHelper({ ...query, start: minStart, end: maxEnd }, opts, observer, false, query);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const parentAggregation = {};
|
|
74
|
+
if (feats.some(f => f.uniqueId === undefined)) {
|
|
75
|
+
throw new Error('found uniqueId undefined');
|
|
76
|
+
}
|
|
77
|
+
for (const feat of feats) {
|
|
78
|
+
const data = parser.parseLine(`${query.refName}\t${feat.start}\t${feat.end}\t${feat.rest}`, { uniqueId: feat.uniqueId });
|
|
79
|
+
const aggr = data[aggregateField];
|
|
80
|
+
if (!parentAggregation[aggr]) {
|
|
81
|
+
parentAggregation[aggr] = [];
|
|
82
|
+
}
|
|
83
|
+
const { uniqueId, type, chromStart, chromStarts, blockStarts, blockCount, blockSizes, chromEnd, thickStart, thickEnd, chrom, score, ...rest } = data;
|
|
84
|
+
const subfeatures = blockCount
|
|
85
|
+
? (0, util_2.makeBlocks)({
|
|
86
|
+
chromStarts,
|
|
87
|
+
blockStarts,
|
|
88
|
+
blockCount,
|
|
89
|
+
blockSizes,
|
|
90
|
+
uniqueId,
|
|
91
|
+
refName: query.refName,
|
|
92
|
+
start: feat.start,
|
|
93
|
+
})
|
|
94
|
+
: [];
|
|
95
|
+
if ((0, util_2.isUcscProcessedTranscript)(data)) {
|
|
96
|
+
const f = (0, util_2.ucscProcessedTranscript)({
|
|
97
|
+
...rest,
|
|
98
|
+
uniqueId,
|
|
99
|
+
type,
|
|
100
|
+
start: feat.start,
|
|
101
|
+
end: feat.end,
|
|
102
|
+
refName: query.refName,
|
|
103
|
+
score: scoreColumn ? +data[scoreColumn] : score,
|
|
104
|
+
chromStarts,
|
|
105
|
+
blockCount,
|
|
106
|
+
blockSizes,
|
|
107
|
+
thickStart,
|
|
108
|
+
thickEnd,
|
|
109
|
+
subfeatures,
|
|
59
110
|
});
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
111
|
+
if (aggr) {
|
|
112
|
+
parentAggregation[aggr].push(f);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
if ((0, util_1.doesIntersect2)(f.start, f.end, originalQuery.start, originalQuery.end)) {
|
|
116
|
+
observer.next(new util_1.SimpleFeature({ id: `${this.id}-${uniqueId}`, data: f }));
|
|
66
117
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
if ((0, util_1.doesIntersect2)(feat.start, feat.end, originalQuery.start, originalQuery.end)) {
|
|
122
|
+
observer.next(new util_1.SimpleFeature({
|
|
123
|
+
id: `${this.id}-${uniqueId}`,
|
|
124
|
+
data: {
|
|
125
|
+
...rest,
|
|
74
126
|
uniqueId,
|
|
75
|
-
|
|
127
|
+
type,
|
|
76
128
|
start: feat.start,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
})).subscribe(observer);
|
|
129
|
+
score: scoreColumn ? +data[scoreColumn] : score,
|
|
130
|
+
end: feat.end,
|
|
131
|
+
refName: query.refName,
|
|
132
|
+
subfeatures,
|
|
133
|
+
},
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
Object.entries(parentAggregation).map(([name, subfeatures]) => {
|
|
139
|
+
const s = (0, util_1.min)(subfeatures.map(f => f.start));
|
|
140
|
+
const e = (0, util_1.max)(subfeatures.map(f => f.end));
|
|
141
|
+
if ((0, util_1.doesIntersect2)(s, e, originalQuery.start, originalQuery.end)) {
|
|
142
|
+
const { uniqueId, strand } = subfeatures[0];
|
|
143
|
+
observer.next(new util_1.SimpleFeature({
|
|
144
|
+
id: `${this.id}-${uniqueId}-parent`,
|
|
145
|
+
data: {
|
|
146
|
+
type: 'gene',
|
|
147
|
+
subfeatures,
|
|
148
|
+
strand,
|
|
149
|
+
name,
|
|
150
|
+
start: s,
|
|
151
|
+
end: e,
|
|
152
|
+
refName: query.refName,
|
|
153
|
+
},
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
observer.complete();
|
|
158
|
+
}
|
|
159
|
+
getFeatures(query, opts = {}) {
|
|
160
|
+
return (0, rxjs_1.ObservableCreate)(async (observer) => {
|
|
161
|
+
try {
|
|
162
|
+
await this.getFeaturesHelper(query, opts, observer, true);
|
|
112
163
|
}
|
|
113
164
|
catch (e) {
|
|
114
165
|
observer.error(e);
|
|
@@ -17,5 +17,13 @@ declare const BigBedAdapter: import("@jbrowse/core/configuration/configurationSc
|
|
|
17
17
|
description: string;
|
|
18
18
|
defaultValue: string;
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* #slot
|
|
22
|
+
*/
|
|
23
|
+
aggregateField: {
|
|
24
|
+
type: string;
|
|
25
|
+
description: string;
|
|
26
|
+
defaultValue: string;
|
|
27
|
+
};
|
|
20
28
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
|
|
21
29
|
export default BigBedAdapter;
|
|
@@ -21,5 +21,13 @@ const BigBedAdapter = (0, configuration_1.ConfigurationSchema)('BigBedAdapter',
|
|
|
21
21
|
description: 'The column to use as a "score" attribute',
|
|
22
22
|
defaultValue: '',
|
|
23
23
|
},
|
|
24
|
+
/**
|
|
25
|
+
* #slot
|
|
26
|
+
*/
|
|
27
|
+
aggregateField: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
description: 'An attribute to aggregate features with',
|
|
30
|
+
defaultValue: 'geneName',
|
|
31
|
+
},
|
|
24
32
|
}, { explicitlyTyped: true });
|
|
25
33
|
exports.default = BigBedAdapter;
|
|
@@ -26,6 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.default = BigBedAdapterF;
|
|
29
30
|
const AdapterType_1 = __importDefault(require("@jbrowse/core/pluggableElementTypes/AdapterType"));
|
|
30
31
|
const configSchema_1 = __importDefault(require("./configSchema"));
|
|
31
32
|
function BigBedAdapterF(pluginManager) {
|
|
@@ -36,4 +37,3 @@ function BigBedAdapterF(pluginManager) {
|
|
|
36
37
|
getAdapterClass: () => Promise.resolve().then(() => __importStar(require('./BigBedAdapter'))).then(r => r.default),
|
|
37
38
|
}));
|
|
38
39
|
}
|
|
39
|
-
exports.default = BigBedAdapterF;
|
package/dist/util.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import BED from '@gmod/bed';
|
|
2
2
|
import { SimpleFeature } from '@jbrowse/core/util';
|
|
3
|
-
interface MinimalFeature {
|
|
3
|
+
export interface MinimalFeature {
|
|
4
4
|
type: string;
|
|
5
5
|
start: number;
|
|
6
6
|
end: number;
|
|
7
7
|
refName: string;
|
|
8
|
+
[key: string]: unknown;
|
|
8
9
|
}
|
|
9
|
-
interface TranscriptFeat {
|
|
10
|
+
export interface TranscriptFeat extends MinimalFeature {
|
|
10
11
|
thickStart: number;
|
|
11
12
|
thickEnd: number;
|
|
12
13
|
blockCount: number;
|
|
@@ -15,13 +16,14 @@ interface TranscriptFeat {
|
|
|
15
16
|
refName: string;
|
|
16
17
|
strand?: number;
|
|
17
18
|
subfeatures: MinimalFeature[];
|
|
18
|
-
[key: string]: unknown;
|
|
19
19
|
}
|
|
20
20
|
export declare function ucscProcessedTranscript(feature: TranscriptFeat): TranscriptFeat | {
|
|
21
21
|
strand: number;
|
|
22
22
|
type: string;
|
|
23
23
|
refName: string;
|
|
24
24
|
subfeatures: MinimalFeature[];
|
|
25
|
+
start: number;
|
|
26
|
+
end: number;
|
|
25
27
|
};
|
|
26
28
|
export declare function makeBlocks({ start, uniqueId, refName, chromStarts, blockCount, blockSizes, blockStarts, }: {
|
|
27
29
|
blockCount: number;
|
|
@@ -39,9 +41,8 @@ export declare function makeBlocks({ start, uniqueId, refName, chromStarts, bloc
|
|
|
39
41
|
type: string;
|
|
40
42
|
}[];
|
|
41
43
|
export declare function featureData(line: string, colRef: number, colStart: number, colEnd: number, scoreColumn: string, parser: BED, uniqueId: string, names?: string[]): SimpleFeature;
|
|
42
|
-
export declare function
|
|
44
|
+
export declare function isUcscProcessedTranscript(f: {
|
|
43
45
|
thickStart?: number;
|
|
44
46
|
blockCount?: number;
|
|
45
47
|
strand?: number;
|
|
46
48
|
}): boolean | 0 | undefined;
|
|
47
|
-
export {};
|
package/dist/util.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ucscProcessedTranscript = ucscProcessedTranscript;
|
|
4
|
+
exports.makeBlocks = makeBlocks;
|
|
5
|
+
exports.featureData = featureData;
|
|
6
|
+
exports.isUcscProcessedTranscript = isUcscProcessedTranscript;
|
|
4
7
|
const util_1 = require("@jbrowse/core/util");
|
|
5
8
|
function ucscProcessedTranscript(feature) {
|
|
6
9
|
var _a;
|
|
@@ -97,7 +100,6 @@ function ucscProcessedTranscript(feature) {
|
|
|
97
100
|
});
|
|
98
101
|
return { ...rest, strand, type: 'mRNA', refName, subfeatures };
|
|
99
102
|
}
|
|
100
|
-
exports.ucscProcessedTranscript = ucscProcessedTranscript;
|
|
101
103
|
function defaultParser(fields, line) {
|
|
102
104
|
const { blockStarts, blockCount, chromStarts, thickEnd, thickStart, blockSizes, ...rest } = Object.fromEntries(line.split('\t').map((f, i) => [fields[i], f]));
|
|
103
105
|
return {
|
|
@@ -126,7 +128,6 @@ function makeBlocks({ start, uniqueId, refName, chromStarts, blockCount, blockSi
|
|
|
126
128
|
}
|
|
127
129
|
return subfeatures;
|
|
128
130
|
}
|
|
129
|
-
exports.makeBlocks = makeBlocks;
|
|
130
131
|
function featureData(line, colRef, colStart, colEnd, scoreColumn, parser, uniqueId, names) {
|
|
131
132
|
const l = line.split('\t');
|
|
132
133
|
const refName = l[colRef];
|
|
@@ -160,7 +161,7 @@ function featureData(line, colRef, colStart, colEnd, scoreColumn, parser, unique
|
|
|
160
161
|
};
|
|
161
162
|
return new util_1.SimpleFeature({
|
|
162
163
|
id: uniqueId,
|
|
163
|
-
data:
|
|
164
|
+
data: isUcscProcessedTranscript(data)
|
|
164
165
|
? ucscProcessedTranscript({
|
|
165
166
|
thickStart,
|
|
166
167
|
thickEnd,
|
|
@@ -172,8 +173,6 @@ function featureData(line, colRef, colStart, colEnd, scoreColumn, parser, unique
|
|
|
172
173
|
: f,
|
|
173
174
|
});
|
|
174
175
|
}
|
|
175
|
-
|
|
176
|
-
function isUCSC(f) {
|
|
176
|
+
function isUcscProcessedTranscript(f) {
|
|
177
177
|
return f.thickStart && f.blockCount && f.strand !== 0;
|
|
178
178
|
}
|
|
179
|
-
exports.isUCSC = isUCSC;
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import { BigBed
|
|
1
|
+
import { BigBed } from '@gmod/bbi';
|
|
2
2
|
import BED from '@gmod/bed';
|
|
3
3
|
import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
4
4
|
import { Region } from '@jbrowse/core/util/types';
|
|
5
|
-
import { Feature } from '@jbrowse/core/util
|
|
5
|
+
import { Feature } from '@jbrowse/core/util';
|
|
6
|
+
import { Observer } from 'rxjs';
|
|
6
7
|
export default class BigBedAdapter extends BaseFeatureDataAdapter {
|
|
7
8
|
private cached?;
|
|
8
9
|
configurePre(opts?: BaseOptions): Promise<{
|
|
9
10
|
bigbed: BigBed;
|
|
10
|
-
header: Header;
|
|
11
|
+
header: import("@gmod/bbi").Header;
|
|
11
12
|
parser: BED;
|
|
12
13
|
}>;
|
|
13
14
|
configure(opts?: BaseOptions): Promise<{
|
|
14
15
|
bigbed: BigBed;
|
|
15
|
-
header:
|
|
16
|
+
header: Awaited<ReturnType<BigBed["getHeader"]>>;
|
|
16
17
|
parser: BED;
|
|
17
18
|
}>;
|
|
18
19
|
getRefNames(opts?: BaseOptions): Promise<string[]>;
|
|
19
20
|
getHeader(opts?: BaseOptions): Promise<{
|
|
20
|
-
version:
|
|
21
|
+
version: number;
|
|
21
22
|
fileType: string;
|
|
22
23
|
autoSql: {};
|
|
23
24
|
fields: {
|
|
24
25
|
[k: string]: string;
|
|
25
26
|
};
|
|
26
27
|
}>;
|
|
27
|
-
|
|
28
|
+
getFeaturesHelper(query: Region, opts: BaseOptions | undefined, observer: Observer<Feature>, allowRedispatch: boolean, originalQuery?: Region): Promise<void>;
|
|
29
|
+
getFeatures(query: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
|
|
28
30
|
freeResources(): void;
|
|
29
31
|
}
|
|
@@ -3,10 +3,9 @@ import BED from '@gmod/bed';
|
|
|
3
3
|
import { BaseFeatureDataAdapter, } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
4
4
|
import { openLocation } from '@jbrowse/core/util/io';
|
|
5
5
|
import { ObservableCreate } from '@jbrowse/core/util/rxjs';
|
|
6
|
-
import SimpleFeature from '@jbrowse/core/util
|
|
7
|
-
import { map, mergeAll } from 'rxjs/operators';
|
|
6
|
+
import { doesIntersect2, max, min, SimpleFeature, } from '@jbrowse/core/util';
|
|
8
7
|
// locals
|
|
9
|
-
import {
|
|
8
|
+
import { isUcscProcessedTranscript, makeBlocks, ucscProcessedTranscript, } from '../util';
|
|
10
9
|
export default class BigBedAdapter extends BaseFeatureDataAdapter {
|
|
11
10
|
async configurePre(opts) {
|
|
12
11
|
const pm = this.pluginManager;
|
|
@@ -32,7 +31,6 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
|
|
|
32
31
|
}
|
|
33
32
|
async getHeader(opts) {
|
|
34
33
|
const { parser, header } = await this.configure(opts);
|
|
35
|
-
// @ts-expect-error
|
|
36
34
|
const { version, fileType } = header;
|
|
37
35
|
const { fields, ...rest } = parser.autoSql;
|
|
38
36
|
return {
|
|
@@ -42,68 +40,121 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
|
|
|
42
40
|
fields: Object.fromEntries(fields.map(({ name, comment }) => [name, comment])),
|
|
43
41
|
};
|
|
44
42
|
}
|
|
45
|
-
|
|
43
|
+
async getFeaturesHelper(query, opts = {}, observer, allowRedispatch, originalQuery = query) {
|
|
46
44
|
const { signal } = opts;
|
|
47
45
|
const scoreColumn = this.getConf('scoreColumn');
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
const aggregateField = this.getConf('aggregateField');
|
|
47
|
+
const { parser, bigbed } = await this.configure(opts);
|
|
48
|
+
const feats = await bigbed.getFeatures(query.refName, query.start, query.end, {
|
|
49
|
+
signal,
|
|
50
|
+
basesPerSpan: query.end - query.start,
|
|
51
|
+
});
|
|
52
|
+
if (allowRedispatch && feats.length) {
|
|
53
|
+
let minStart = Infinity;
|
|
54
|
+
let maxEnd = -Infinity;
|
|
55
|
+
for (const feat of feats) {
|
|
56
|
+
if (feat.start < minStart) {
|
|
57
|
+
minStart = feat.start;
|
|
58
|
+
}
|
|
59
|
+
if (feat.end > maxEnd) {
|
|
60
|
+
maxEnd = feat.end;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (maxEnd > query.end || minStart < query.start) {
|
|
64
|
+
await this.getFeaturesHelper({ ...query, start: minStart, end: maxEnd }, opts, observer, false, query);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const parentAggregation = {};
|
|
69
|
+
if (feats.some(f => f.uniqueId === undefined)) {
|
|
70
|
+
throw new Error('found uniqueId undefined');
|
|
71
|
+
}
|
|
72
|
+
for (const feat of feats) {
|
|
73
|
+
const data = parser.parseLine(`${query.refName}\t${feat.start}\t${feat.end}\t${feat.rest}`, { uniqueId: feat.uniqueId });
|
|
74
|
+
const aggr = data[aggregateField];
|
|
75
|
+
if (!parentAggregation[aggr]) {
|
|
76
|
+
parentAggregation[aggr] = [];
|
|
77
|
+
}
|
|
78
|
+
const { uniqueId, type, chromStart, chromStarts, blockStarts, blockCount, blockSizes, chromEnd, thickStart, thickEnd, chrom, score, ...rest } = data;
|
|
79
|
+
const subfeatures = blockCount
|
|
80
|
+
? makeBlocks({
|
|
81
|
+
chromStarts,
|
|
82
|
+
blockStarts,
|
|
83
|
+
blockCount,
|
|
84
|
+
blockSizes,
|
|
85
|
+
uniqueId,
|
|
86
|
+
refName: query.refName,
|
|
87
|
+
start: feat.start,
|
|
88
|
+
})
|
|
89
|
+
: [];
|
|
90
|
+
if (isUcscProcessedTranscript(data)) {
|
|
91
|
+
const f = ucscProcessedTranscript({
|
|
92
|
+
...rest,
|
|
93
|
+
uniqueId,
|
|
94
|
+
type,
|
|
95
|
+
start: feat.start,
|
|
96
|
+
end: feat.end,
|
|
97
|
+
refName: query.refName,
|
|
98
|
+
score: scoreColumn ? +data[scoreColumn] : score,
|
|
99
|
+
chromStarts,
|
|
100
|
+
blockCount,
|
|
101
|
+
blockSizes,
|
|
102
|
+
thickStart,
|
|
103
|
+
thickEnd,
|
|
104
|
+
subfeatures,
|
|
54
105
|
});
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
106
|
+
if (aggr) {
|
|
107
|
+
parentAggregation[aggr].push(f);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
if (doesIntersect2(f.start, f.end, originalQuery.start, originalQuery.end)) {
|
|
111
|
+
observer.next(new SimpleFeature({ id: `${this.id}-${uniqueId}`, data: f }));
|
|
61
112
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
if (doesIntersect2(feat.start, feat.end, originalQuery.start, originalQuery.end)) {
|
|
117
|
+
observer.next(new SimpleFeature({
|
|
118
|
+
id: `${this.id}-${uniqueId}`,
|
|
119
|
+
data: {
|
|
120
|
+
...rest,
|
|
69
121
|
uniqueId,
|
|
70
|
-
|
|
122
|
+
type,
|
|
71
123
|
start: feat.start,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
})).subscribe(observer);
|
|
124
|
+
score: scoreColumn ? +data[scoreColumn] : score,
|
|
125
|
+
end: feat.end,
|
|
126
|
+
refName: query.refName,
|
|
127
|
+
subfeatures,
|
|
128
|
+
},
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
Object.entries(parentAggregation).map(([name, subfeatures]) => {
|
|
134
|
+
const s = min(subfeatures.map(f => f.start));
|
|
135
|
+
const e = max(subfeatures.map(f => f.end));
|
|
136
|
+
if (doesIntersect2(s, e, originalQuery.start, originalQuery.end)) {
|
|
137
|
+
const { uniqueId, strand } = subfeatures[0];
|
|
138
|
+
observer.next(new SimpleFeature({
|
|
139
|
+
id: `${this.id}-${uniqueId}-parent`,
|
|
140
|
+
data: {
|
|
141
|
+
type: 'gene',
|
|
142
|
+
subfeatures,
|
|
143
|
+
strand,
|
|
144
|
+
name,
|
|
145
|
+
start: s,
|
|
146
|
+
end: e,
|
|
147
|
+
refName: query.refName,
|
|
148
|
+
},
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
observer.complete();
|
|
153
|
+
}
|
|
154
|
+
getFeatures(query, opts = {}) {
|
|
155
|
+
return ObservableCreate(async (observer) => {
|
|
156
|
+
try {
|
|
157
|
+
await this.getFeaturesHelper(query, opts, observer, true);
|
|
107
158
|
}
|
|
108
159
|
catch (e) {
|
|
109
160
|
observer.error(e);
|
|
@@ -17,5 +17,13 @@ declare const BigBedAdapter: import("@jbrowse/core/configuration/configurationSc
|
|
|
17
17
|
description: string;
|
|
18
18
|
defaultValue: string;
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* #slot
|
|
22
|
+
*/
|
|
23
|
+
aggregateField: {
|
|
24
|
+
type: string;
|
|
25
|
+
description: string;
|
|
26
|
+
defaultValue: string;
|
|
27
|
+
};
|
|
20
28
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
|
|
21
29
|
export default BigBedAdapter;
|
|
@@ -19,5 +19,13 @@ const BigBedAdapter = ConfigurationSchema('BigBedAdapter', {
|
|
|
19
19
|
description: 'The column to use as a "score" attribute',
|
|
20
20
|
defaultValue: '',
|
|
21
21
|
},
|
|
22
|
+
/**
|
|
23
|
+
* #slot
|
|
24
|
+
*/
|
|
25
|
+
aggregateField: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: 'An attribute to aggregate features with',
|
|
28
|
+
defaultValue: 'geneName',
|
|
29
|
+
},
|
|
22
30
|
}, { explicitlyTyped: true });
|
|
23
31
|
export default BigBedAdapter;
|
package/esm/util.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import BED from '@gmod/bed';
|
|
2
2
|
import { SimpleFeature } from '@jbrowse/core/util';
|
|
3
|
-
interface MinimalFeature {
|
|
3
|
+
export interface MinimalFeature {
|
|
4
4
|
type: string;
|
|
5
5
|
start: number;
|
|
6
6
|
end: number;
|
|
7
7
|
refName: string;
|
|
8
|
+
[key: string]: unknown;
|
|
8
9
|
}
|
|
9
|
-
interface TranscriptFeat {
|
|
10
|
+
export interface TranscriptFeat extends MinimalFeature {
|
|
10
11
|
thickStart: number;
|
|
11
12
|
thickEnd: number;
|
|
12
13
|
blockCount: number;
|
|
@@ -15,13 +16,14 @@ interface TranscriptFeat {
|
|
|
15
16
|
refName: string;
|
|
16
17
|
strand?: number;
|
|
17
18
|
subfeatures: MinimalFeature[];
|
|
18
|
-
[key: string]: unknown;
|
|
19
19
|
}
|
|
20
20
|
export declare function ucscProcessedTranscript(feature: TranscriptFeat): TranscriptFeat | {
|
|
21
21
|
strand: number;
|
|
22
22
|
type: string;
|
|
23
23
|
refName: string;
|
|
24
24
|
subfeatures: MinimalFeature[];
|
|
25
|
+
start: number;
|
|
26
|
+
end: number;
|
|
25
27
|
};
|
|
26
28
|
export declare function makeBlocks({ start, uniqueId, refName, chromStarts, blockCount, blockSizes, blockStarts, }: {
|
|
27
29
|
blockCount: number;
|
|
@@ -39,9 +41,8 @@ export declare function makeBlocks({ start, uniqueId, refName, chromStarts, bloc
|
|
|
39
41
|
type: string;
|
|
40
42
|
}[];
|
|
41
43
|
export declare function featureData(line: string, colRef: number, colStart: number, colEnd: number, scoreColumn: string, parser: BED, uniqueId: string, names?: string[]): SimpleFeature;
|
|
42
|
-
export declare function
|
|
44
|
+
export declare function isUcscProcessedTranscript(f: {
|
|
43
45
|
thickStart?: number;
|
|
44
46
|
blockCount?: number;
|
|
45
47
|
strand?: number;
|
|
46
48
|
}): boolean | 0 | undefined;
|
|
47
|
-
export {};
|
package/esm/util.js
CHANGED
|
@@ -155,7 +155,7 @@ export function featureData(line, colRef, colStart, colEnd, scoreColumn, parser,
|
|
|
155
155
|
};
|
|
156
156
|
return new SimpleFeature({
|
|
157
157
|
id: uniqueId,
|
|
158
|
-
data:
|
|
158
|
+
data: isUcscProcessedTranscript(data)
|
|
159
159
|
? ucscProcessedTranscript({
|
|
160
160
|
thickStart,
|
|
161
161
|
thickEnd,
|
|
@@ -167,6 +167,6 @@ export function featureData(line, colRef, colStart, colEnd, scoreColumn, parser,
|
|
|
167
167
|
: f,
|
|
168
168
|
});
|
|
169
169
|
}
|
|
170
|
-
export function
|
|
170
|
+
export function isUcscProcessedTranscript(f) {
|
|
171
171
|
return f.thickStart && f.blockCount && f.strand !== 0;
|
|
172
172
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-bed",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.1",
|
|
4
4
|
"description": "JBrowse 2 bed adapters, tracks, etc.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"distModule": "esm/index.js",
|
|
56
56
|
"srcModule": "src/index.ts",
|
|
57
57
|
"module": "esm/index.js",
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "20f16ae5a56ae5e4806aaa373131e540b0b5b0fd"
|
|
59
59
|
}
|