@jbrowse/plugin-gff3 5.0.0-beta.1 → 5.0.0-beta.2
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.
|
@@ -22,17 +22,16 @@ export default class Gff3Adapter extends BaseFeatureDataAdapter {
|
|
|
22
22
|
// that resident set small (8.5x on GENCODE-shaped input), and the
|
|
23
23
|
// render path reads only a handful of attributes anyway — see
|
|
24
24
|
// Gff3Feature.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
}, 'Parsing GFF data');
|
|
25
|
+
//
|
|
26
|
+
// The id the tree entry carries is minted here, beside the feature
|
|
27
|
+
// rather than stamped onto it, so the parsed feature is the library's
|
|
28
|
+
// shape and Gff3Feature serializes it identically for both adapters.
|
|
29
|
+
(lines, refName) => parseLinesLazy(lines).map((feature, i) => ({
|
|
30
|
+
start: feature.start,
|
|
31
|
+
end: feature.end,
|
|
32
|
+
feature,
|
|
33
|
+
uniqueId: `${this.id}-${refName}-${i}`,
|
|
34
|
+
})), 'Parsing GFF data');
|
|
36
35
|
return { header: headerLines.join('\n'), intervalTreeMap };
|
|
37
36
|
},
|
|
38
37
|
});
|
|
@@ -52,8 +51,11 @@ export default class Gff3Adapter extends BaseFeatureDataAdapter {
|
|
|
52
51
|
const { intervalTreeMap } = await this.loadData(opts);
|
|
53
52
|
const tree = intervalTreeMap[refName];
|
|
54
53
|
if (tree) {
|
|
55
|
-
for (const
|
|
56
|
-
|
|
54
|
+
for (const { feature, uniqueId } of tree(opts.statusCallback).search([
|
|
55
|
+
start,
|
|
56
|
+
end,
|
|
57
|
+
])) {
|
|
58
|
+
observer.next(new Gff3Feature(feature, uniqueId));
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
observer.complete();
|
package/esm/Gff3Feature.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import type { Feature, SimpleFeatureSerialized } from '@jbrowse/core/util/simpleFeature';
|
|
2
2
|
import type { LazyGffFeature } from 'gff-nostream';
|
|
3
|
-
/** A parsed GFF3 feature carrying the id the adapter minted for it. */
|
|
4
|
-
export type IdentifiedGffFeature = LazyGffFeature & {
|
|
5
|
-
uniqueId: string;
|
|
6
|
-
};
|
|
7
3
|
/**
|
|
8
4
|
* A {@link Feature} over a GFF3 feature whose attributes are still raw column-9
|
|
9
5
|
* text, resolving each one only when something asks for it.
|
|
@@ -26,7 +22,7 @@ export declare class Gff3Feature implements Feature {
|
|
|
26
22
|
private uniqueId;
|
|
27
23
|
private parentFeature?;
|
|
28
24
|
private inflated?;
|
|
29
|
-
constructor(data:
|
|
25
|
+
constructor(data: LazyGffFeature, uniqueId: string, parentFeature?: Feature | undefined);
|
|
30
26
|
/**
|
|
31
27
|
* A switch rather than a lookup table or a `data[name]` fallthrough: the
|
|
32
28
|
* fixed columns are read tens of times per feature by the layout pass, and
|
|
@@ -7,7 +7,7 @@ import { openLocation, openTabixIndexFilehandle } from '@jbrowse/core/util/io';
|
|
|
7
7
|
import { doesIntersect2 } from '@jbrowse/core/util/range';
|
|
8
8
|
import { ObservableCreate } from '@jbrowse/core/util/rxjs';
|
|
9
9
|
import { readTabixLinesRedispatched } from '@jbrowse/core/util/tabix';
|
|
10
|
-
import { parseRecordsLazy } from 'gff-nostream';
|
|
10
|
+
import { hasIdAttribute, parseRecordsLazy } from 'gff-nostream';
|
|
11
11
|
import { Gff3Feature } from '../Gff3Feature.js';
|
|
12
12
|
export default class Gff3TabixAdapter extends BaseFeatureDataAdapter {
|
|
13
13
|
configure = cachedSetup({
|
|
@@ -47,7 +47,26 @@ export default class Gff3TabixAdapter extends BaseFeatureDataAdapter {
|
|
|
47
47
|
return ObservableCreate(async (observer) => {
|
|
48
48
|
try {
|
|
49
49
|
const { gff, dontRedispatchSet } = await this.configure(opts);
|
|
50
|
-
|
|
50
|
+
// The bound exists to reach a record's children, so what disqualifies a
|
|
51
|
+
// record is having none. `ID` answers that exactly — nothing can name a
|
|
52
|
+
// parent that has no name — and gff-nostream decides it with the scan
|
|
53
|
+
// its linker uses, so a record the tree would attach children to is
|
|
54
|
+
// never one the bound leaves out. `dontRedispatch` can only approximate
|
|
55
|
+
// the same question by type: every NCBI `GCF_*_genomic.gff.gz` opens
|
|
56
|
+
// each reference with a chromosome-long `match` record no list named,
|
|
57
|
+
// and none of them has an `ID`. The list covers what `ID` cannot see: a
|
|
58
|
+
// record carrying an `ID` that nothing references, which hosted hg19
|
|
59
|
+
// RefSeq's chromosome-long `region` is.
|
|
60
|
+
const canHaveChildren = (line) => hasIdAttribute(line.line) && !dontRedispatchSet.has(line.type);
|
|
61
|
+
const lines = await readTabixLinesRedispatched(gff, query,
|
|
62
|
+
// A caller reading only top-level features is owed nothing by the
|
|
63
|
+
// flanks and pays for them anyway: they complete SUBFEATURE lists, and
|
|
64
|
+
// a top-level feature overlapping the query is in the query's own read
|
|
65
|
+
// already, since tabix returns every overlapping line and a child is
|
|
66
|
+
// contained in its parent. On an NCBI `GCF_*_genomic.gff.gz`, whose
|
|
67
|
+
// chromosome-long `match` widens the bound at every window, that is
|
|
68
|
+
// 193,008 lines parsed to keep 3 features — 2734 ms against 8 ms.
|
|
69
|
+
opts.topLevelOnly ? () => false : canHaveChildren, opts);
|
|
51
70
|
// emit only top-level features intersecting the original query. the
|
|
52
71
|
// byte offset stays on our own record and is used purely to mint a
|
|
53
72
|
// stable id, so it never pollutes the feature's data
|
|
@@ -18,6 +18,11 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
|
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
declare const Gff3TabixAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
21
|
+
readonly densityAdapter: {
|
|
22
|
+
readonly type: 'frozen';
|
|
23
|
+
readonly defaultValue: null;
|
|
24
|
+
readonly description: 'optional quantitative sub-adapter (e.g. a BigWigAdapter over a features-per-bin bigWig) drawn as a density band where the region is too large to fetch features; null disables it';
|
|
25
|
+
};
|
|
21
26
|
/**
|
|
22
27
|
* #slot
|
|
23
28
|
* location of the bgzip-compressed GFF3, sorted by position. Must be bgzip
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ConfigurationSchema, expandTabixShorthand, tabixIndexFields, } from '@jbrowse/core/configuration';
|
|
2
|
+
import { densityAdapterConfigSchemaFields } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
2
3
|
export function normalizeSnapshot(snap) {
|
|
3
4
|
return expandTabixShorthand(snap, 'gffGzLocation');
|
|
4
5
|
}
|
|
@@ -56,6 +57,7 @@ const Gff3TabixAdapter = ConfigurationSchema('Gff3TabixAdapter', {
|
|
|
56
57
|
'scaffold',
|
|
57
58
|
],
|
|
58
59
|
},
|
|
60
|
+
...densityAdapterConfigSchemaFields,
|
|
59
61
|
}, {
|
|
60
62
|
explicitlyTyped: true,
|
|
61
63
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-gff3",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "JBrowse 2 gff3.",
|
|
6
6
|
"keywords": [
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@gmod/tabix": "^3.8.2",
|
|
25
25
|
"@jbrowse/mobx-state-tree": "^6.5.1",
|
|
26
|
-
"gff-nostream": "^5.
|
|
26
|
+
"gff-nostream": "^5.4.0",
|
|
27
27
|
"mobx": "^7.0.3",
|
|
28
28
|
"rxjs": "^7.8.2",
|
|
29
|
-
"@jbrowse/core": "^5.0.0-beta.
|
|
29
|
+
"@jbrowse/core": "^5.0.0-beta.2"
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|