@jbrowse/plugin-bed 4.3.0 → 5.0.0-beta.10

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.
Files changed (64) hide show
  1. package/esm/BedAdapter/BedAdapter.d.ts +5 -22
  2. package/esm/BedAdapter/BedAdapter.js +29 -93
  3. package/esm/BedAdapter/configSchema.d.ts +59 -32
  4. package/esm/BedAdapter/configSchema.js +64 -14
  5. package/esm/BedAdapter/index.js +4 -2
  6. package/esm/BedGraphAdapter/BedGraphAdapter.d.ts +5 -12
  7. package/esm/BedGraphAdapter/BedGraphAdapter.js +33 -89
  8. package/esm/BedGraphAdapter/configSchema.d.ts +35 -11
  9. package/esm/BedGraphAdapter/configSchema.js +43 -13
  10. package/esm/BedGraphAdapter/index.js +3 -2
  11. package/esm/BedGraphTabixAdapter/BedGraphTabixAdapter.d.ts +5 -5
  12. package/esm/BedGraphTabixAdapter/BedGraphTabixAdapter.js +65 -57
  13. package/esm/BedGraphTabixAdapter/configSchema.d.ts +46 -22
  14. package/esm/BedGraphTabixAdapter/configSchema.js +50 -34
  15. package/esm/BedGraphTabixAdapter/index.js +3 -2
  16. package/esm/BedTabixAdapter/BedTabixAdapter.d.ts +34 -38
  17. package/esm/BedTabixAdapter/BedTabixAdapter.js +82 -72
  18. package/esm/BedTabixAdapter/configSchema.d.ts +55 -31
  19. package/esm/BedTabixAdapter/configSchema.js +58 -35
  20. package/esm/BedTabixAdapter/index.js +4 -2
  21. package/esm/BedpeAdapter/BedpeAdapter.d.ts +6 -13
  22. package/esm/BedpeAdapter/BedpeAdapter.js +26 -74
  23. package/esm/BedpeAdapter/configSchema.d.ts +31 -12
  24. package/esm/BedpeAdapter/configSchema.js +37 -13
  25. package/esm/BedpeAdapter/index.js +4 -2
  26. package/esm/BedpeAdapter/util.js +25 -25
  27. package/esm/BigBedAdapter/BigBedAdapter.d.ts +8 -7
  28. package/esm/BigBedAdapter/BigBedAdapter.js +99 -107
  29. package/esm/BigBedAdapter/configSchema.d.ts +38 -16
  30. package/esm/BigBedAdapter/configSchema.js +46 -13
  31. package/esm/BigBedAdapter/index.js +3 -2
  32. package/esm/BigBedTextSearchAdapter/BigBedTextSearchAdapter.d.ts +27 -0
  33. package/esm/BigBedTextSearchAdapter/BigBedTextSearchAdapter.js +128 -0
  34. package/esm/BigBedTextSearchAdapter/configSchema.d.ts +51 -0
  35. package/esm/BigBedTextSearchAdapter/configSchema.js +57 -0
  36. package/esm/BigBedTextSearchAdapter/index.d.ts +2 -0
  37. package/esm/BigBedTextSearchAdapter/index.js +11 -0
  38. package/esm/StarFusionAdapter/StarFusionAdapter.d.ts +14 -0
  39. package/esm/StarFusionAdapter/StarFusionAdapter.js +66 -0
  40. package/esm/StarFusionAdapter/configSchema.d.ts +30 -0
  41. package/esm/StarFusionAdapter/configSchema.js +43 -0
  42. package/esm/StarFusionAdapter/index.d.ts +2 -0
  43. package/esm/StarFusionAdapter/index.js +12 -0
  44. package/esm/adapterUtil.d.ts +5 -0
  45. package/esm/adapterUtil.js +43 -0
  46. package/esm/bedGraphUtil.d.ts +11 -0
  47. package/esm/bedGraphUtil.js +20 -0
  48. package/esm/copyExcept.d.ts +1 -0
  49. package/esm/copyExcept.js +11 -0
  50. package/esm/generateBedMethylFeature.d.ts +1 -1
  51. package/esm/generateBedMethylFeature.js +24 -6
  52. package/esm/generateRastairMethylFeature.d.ts +28 -0
  53. package/esm/generateRastairMethylFeature.js +38 -0
  54. package/esm/generateRepeatMaskerFeature.d.ts +17 -51
  55. package/esm/generateRepeatMaskerFeature.js +27 -37
  56. package/esm/generateUcscTranscript.d.ts +15 -7
  57. package/esm/generateUcscTranscript.js +106 -29
  58. package/esm/index.d.ts +2 -0
  59. package/esm/index.js +12 -8
  60. package/esm/util.d.ts +32 -27
  61. package/esm/util.js +139 -98
  62. package/package.json +10 -13
  63. package/esm/GuessAdapter/index.d.ts +0 -2
  64. package/esm/GuessAdapter/index.js +0 -71
@@ -1,10 +1,11 @@
1
1
  import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType';
2
- import configSchema from "./configSchema.js";
2
+ import configSchema, { normalizeSnapshot } from './configSchema.js';
3
3
  export default function BigBedAdapterF(pluginManager) {
4
4
  pluginManager.addAdapterType(() => new AdapterType({
5
5
  name: 'BigBedAdapter',
6
6
  displayName: 'BigBed adapter',
7
+ normalizeSnapshot,
7
8
  configSchema,
8
- getAdapterClass: () => import("./BigBedAdapter.js").then(r => r.default),
9
+ getAdapterClass: () => import('./BigBedAdapter.js').then(r => r.default),
9
10
  }));
10
11
  }
@@ -0,0 +1,27 @@
1
+ import { BigBed } from '@gmod/bbi';
2
+ import Trix from '@gmod/trix';
3
+ import BaseResult from '@jbrowse/core/TextSearch/BaseResults';
4
+ import { BaseAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
5
+ import type { BigBedTextSearchAdapterConfig } from './configSchema.ts';
6
+ import type PluginManager from '@jbrowse/core/PluginManager';
7
+ import type { BaseTextSearchAdapter, BaseTextSearchArgs } from '@jbrowse/core/data_adapters/BaseAdapter';
8
+ import type { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
9
+ interface Hit {
10
+ label: string;
11
+ refName: string;
12
+ start: number;
13
+ end: number;
14
+ }
15
+ export declare function mergeTranscripts(hits: Hit[]): Hit[];
16
+ export default class BigBedTextSearchAdapter extends BaseAdapter<BigBedTextSearchAdapterConfig> implements BaseTextSearchAdapter {
17
+ bigbed: BigBed;
18
+ trix?: Trix;
19
+ constructor(config: BigBedTextSearchAdapterConfig, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
20
+ names(query: string, exactOnly: boolean, signal?: AbortSignal): Promise<{
21
+ exact: string[];
22
+ prefixed: (readonly [string, string])[];
23
+ }>;
24
+ lookUp(name: string, word: string, signal?: AbortSignal): Promise<Hit[]>;
25
+ searchIndex({ queryString, searchType, signal }: BaseTextSearchArgs): Promise<BaseResult[]>;
26
+ }
27
+ export {};
@@ -0,0 +1,128 @@
1
+ import { BigBed } from '@gmod/bbi';
2
+ import Trix from '@gmod/trix';
3
+ import BaseResult from '@jbrowse/core/TextSearch/BaseResults';
4
+ import { BaseAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
5
+ import { checkAbortSignal } from '@jbrowse/core/util/aborting';
6
+ import { openLocation } from '@jbrowse/core/util/io';
7
+ // each name a query resolves costs a walk of the BigBed's B+ tree, so a query
8
+ // resolves every name its exact word carries up to one cap, and the words it
9
+ // only prefixes, each whole, while their names fit the other
10
+ const MAX_EXACT_NAMES = 50;
11
+ const MAX_PREFIX_NAMES = 50;
12
+ const MAX_TRIX_HITS = 500;
13
+ function isSet(location) {
14
+ return 'uri' in location
15
+ ? !!location.uri
16
+ : 'localPath' in location
17
+ ? !!location.localPath
18
+ : true;
19
+ }
20
+ // the column that matched is the name the hit goes by: a gene symbol for a
21
+ // search by symbol, the accession for a search by accession
22
+ function hitFor({ refName, start, end, rest = '', }, word) {
23
+ const fields = rest.split('\t');
24
+ const label = fields.find(f => f.toLowerCase() === word) ?? fields[0];
25
+ return refName && label ? { label, refName, start, end } : undefined;
26
+ }
27
+ // Transcripts sharing the name that matched and overlapping on one sequence
28
+ // are one gene, the rule BigBedAdapter draws them by, so a search for a gene
29
+ // lands on the gene rather than asking which of its transcripts
30
+ export function mergeTranscripts(hits) {
31
+ const merged = [];
32
+ const sorted = hits.toSorted((a, b) => a.label.localeCompare(b.label) ||
33
+ a.refName.localeCompare(b.refName) ||
34
+ a.start - b.start);
35
+ for (const hit of sorted) {
36
+ const last = merged.at(-1);
37
+ if (last?.label === hit.label &&
38
+ last.refName === hit.refName &&
39
+ hit.start <= last.end) {
40
+ last.end = Math.max(last.end, hit.end);
41
+ }
42
+ else {
43
+ merged.push({ ...hit });
44
+ }
45
+ }
46
+ return merged;
47
+ }
48
+ // A word is resolved whole or not at all, since a word missing some of its
49
+ // names would land on part of its gene
50
+ function prefixedNames(byWord, word) {
51
+ const pairs = [];
52
+ for (const [term, names] of byWord) {
53
+ if (term !== word && term.startsWith(word)) {
54
+ if (pairs.length + names.length > MAX_PREFIX_NAMES) {
55
+ break;
56
+ }
57
+ pairs.push(...names.map(name => [term, name]));
58
+ }
59
+ }
60
+ return pairs;
61
+ }
62
+ export default class BigBedTextSearchAdapter extends BaseAdapter {
63
+ bigbed;
64
+ trix;
65
+ constructor(config, getSubAdapter, pluginManager) {
66
+ super(config, getSubAdapter, pluginManager);
67
+ this.bigbed = new BigBed({
68
+ filehandle: openLocation(this.getConf('bigBedLocation'), pluginManager),
69
+ });
70
+ const ix = this.getConf('ixFilePath');
71
+ const ixx = this.getConf('ixxFilePath');
72
+ if (isSet(ix) && isSet(ixx)) {
73
+ this.trix = new Trix(openLocation(ixx, pluginManager), openLocation(ix, pluginManager), MAX_TRIX_HITS);
74
+ }
75
+ }
76
+ // The names to look up: the query as spelled, which the extra index answers
77
+ // however the trix split it into words, then the names the trix finds for
78
+ // its word. GenArk's trix drops an accession's version, so a versioned query
79
+ // asks for the bare word and keeps the names spelling the query
80
+ async names(query, exactOnly, signal) {
81
+ const word = query.toLowerCase();
82
+ if (!this.trix) {
83
+ return { exact: [query], prefixed: [] };
84
+ }
85
+ const trixWord = word.replace(/\.\d+$/, '');
86
+ const byWord = new Map();
87
+ for (const [term, name] of await this.trix.search(trixWord, { signal })) {
88
+ const names = byWord.get(term);
89
+ if (names) {
90
+ names.push(name);
91
+ }
92
+ else {
93
+ byWord.set(term, [name]);
94
+ }
95
+ }
96
+ const exact = trixWord === word
97
+ ? (byWord.get(word) ?? [])
98
+ : (byWord.get(trixWord) ?? []).filter(n => n.toLowerCase() === word);
99
+ return {
100
+ exact: [...new Set([query, ...exact])].slice(0, MAX_EXACT_NAMES),
101
+ prefixed: exactOnly ? [] : prefixedNames(byWord, word),
102
+ };
103
+ }
104
+ async lookUp(name, word, signal) {
105
+ return (await this.bigbed.searchExtraIndex(name, { signal }))
106
+ .map(f => hitFor(f, word))
107
+ .filter(h => h !== undefined);
108
+ }
109
+ async searchIndex({ queryString, searchType, signal }) {
110
+ const query = queryString.trim();
111
+ const word = query.toLowerCase();
112
+ const { exact, prefixed } = await this.names(query, searchType === 'exact', signal);
113
+ const [exactHits, prefixHits] = await Promise.all([
114
+ Promise.all(exact.map(name => this.lookUp(name, word, signal))),
115
+ Promise.all(prefixed.map(([term, name]) => this.lookUp(name, term, signal))),
116
+ ]);
117
+ checkAbortSignal(signal);
118
+ const results = (hits, exact) => mergeTranscripts(hits).map(({ label, refName, start, end }) => new BaseResult({
119
+ label,
120
+ locString: `${refName}:${start + 1}..${end}`,
121
+ exact,
122
+ }));
123
+ return [
124
+ ...results(exactHits.flat(), true),
125
+ ...results(prefixHits.flat(), false),
126
+ ];
127
+ }
128
+ }
@@ -0,0 +1,51 @@
1
+ import type { Instance } from '@jbrowse/mobx-state-tree';
2
+ /**
3
+ * #config BigBedTextSearchAdapter
4
+ * #trackType TextSearchAdapter
5
+ *
6
+ * Finds features by the names a BigBed was built to look up, its
7
+ * `bedToBigBed -extraIndex` columns, which a UCSC hub declares with
8
+ * `searchIndex`. The hub's `searchTrix` index, when given, adds prefix and
9
+ * case-insensitive matching. A UCSC track hub connection configures one for
10
+ * its first gene track declaring a `searchIndex`, GenArk's `ncbiRefSeq`.
11
+ *
12
+ * #example
13
+ * ```js
14
+ * {
15
+ * type: 'BigBedTextSearchAdapter',
16
+ * bigBedLocation: { uri: 'bbi/ncbiRefSeq.bb' },
17
+ * ixFilePath: { uri: 'ixIxx/ncbiRefSeq.ix' },
18
+ * ixxFilePath: { uri: 'ixIxx/ncbiRefSeq.ixx' },
19
+ * }
20
+ * ```
21
+ */
22
+ declare const BigBedTextSearchAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
23
+ type: {
24
+ type: "string";
25
+ } & {
26
+ defaultValue: string;
27
+ };
28
+ readonly bigBedLocation: {
29
+ type: "fileLocation";
30
+ } & {
31
+ defaultValue: unknown;
32
+ };
33
+ readonly ixFilePath: {
34
+ type: "fileLocation";
35
+ } & {
36
+ defaultValue: unknown;
37
+ };
38
+ readonly ixxFilePath: {
39
+ type: "fileLocation";
40
+ } & {
41
+ defaultValue: unknown;
42
+ };
43
+ readonly assemblyNames: {
44
+ type: "stringArray";
45
+ } & {
46
+ defaultValue: unknown;
47
+ };
48
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined, true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>;
49
+ export interface BigBedTextSearchAdapterConfig extends Instance<typeof BigBedTextSearchAdapter> {
50
+ }
51
+ export default BigBedTextSearchAdapter;
@@ -0,0 +1,57 @@
1
+ import { ConfigurationSchema } from '@jbrowse/core/configuration';
2
+ /**
3
+ * #config BigBedTextSearchAdapter
4
+ * #trackType TextSearchAdapter
5
+ *
6
+ * Finds features by the names a BigBed was built to look up, its
7
+ * `bedToBigBed -extraIndex` columns, which a UCSC hub declares with
8
+ * `searchIndex`. The hub's `searchTrix` index, when given, adds prefix and
9
+ * case-insensitive matching. A UCSC track hub connection configures one for
10
+ * its first gene track declaring a `searchIndex`, GenArk's `ncbiRefSeq`.
11
+ *
12
+ * #example
13
+ * ```js
14
+ * {
15
+ * type: 'BigBedTextSearchAdapter',
16
+ * bigBedLocation: { uri: 'bbi/ncbiRefSeq.bb' },
17
+ * ixFilePath: { uri: 'ixIxx/ncbiRefSeq.ix' },
18
+ * ixxFilePath: { uri: 'ixIxx/ncbiRefSeq.ixx' },
19
+ * }
20
+ * ```
21
+ */
22
+ const BigBedTextSearchAdapter = ConfigurationSchema('BigBedTextSearchAdapter', {
23
+ /**
24
+ * #slot
25
+ * the BigBed whose extra indexes resolve a name to its features
26
+ */
27
+ bigBedLocation: {
28
+ type: 'fileLocation',
29
+ defaultValue: { uri: '/path/to/my.bb', locationType: 'UriLocation' },
30
+ },
31
+ /**
32
+ * #slot
33
+ * a UCSC `searchTrix` `.ix`, whose records are the names the extra
34
+ * indexes hold. Unset, a search matches a name exactly as typed
35
+ */
36
+ ixFilePath: {
37
+ type: 'fileLocation',
38
+ defaultValue: { uri: '', locationType: 'UriLocation' },
39
+ },
40
+ /**
41
+ * #slot
42
+ * the `.ixx` beside `ixFilePath`
43
+ */
44
+ ixxFilePath: {
45
+ type: 'fileLocation',
46
+ defaultValue: { uri: '', locationType: 'UriLocation' },
47
+ },
48
+ /**
49
+ * #slot
50
+ */
51
+ assemblyNames: {
52
+ type: 'stringArray',
53
+ defaultValue: [],
54
+ description: 'List of assemblies covered by text search adapter',
55
+ },
56
+ }, { explicitlyTyped: true });
57
+ export default BigBedTextSearchAdapter;
@@ -0,0 +1,2 @@
1
+ import type PluginManager from '@jbrowse/core/PluginManager';
2
+ export default function BigBedTextSearchAdapterF(pluginManager: PluginManager): void;
@@ -0,0 +1,11 @@
1
+ import TextSearchAdapterType from '@jbrowse/core/pluggableElementTypes/TextSearchAdapterType';
2
+ import configSchema from './configSchema.js';
3
+ export default function BigBedTextSearchAdapterF(pluginManager) {
4
+ pluginManager.addTextSearchAdapterType(() => new TextSearchAdapterType({
5
+ name: 'BigBedTextSearchAdapter',
6
+ displayName: 'BigBed text search adapter',
7
+ description: 'Searches a BigBed by its extra-indexed names',
8
+ configSchema,
9
+ getAdapterClass: () => import('./BigBedTextSearchAdapter.js').then(r => r.default),
10
+ }));
11
+ }
@@ -0,0 +1,14 @@
1
+ import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
2
+ import type { StarFusionAdapterConfig } from './configSchema.ts';
3
+ import type { BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
4
+ import type { Feature, Region } from '@jbrowse/core/util';
5
+ export default class StarFusionAdapter extends BaseFeatureDataAdapter<StarFusionAdapterConfig> {
6
+ private loadData;
7
+ static capabilities: string[];
8
+ private loadDataP;
9
+ getRefNames(opts?: BaseOptions): Promise<string[]>;
10
+ private featureFromLine;
11
+ private loadFeatureTreeP;
12
+ private treeFeatures;
13
+ getFeatures(query: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
14
+ }
@@ -0,0 +1,66 @@
1
+ import { BaseFeatureDataAdapter, cachedSetup, } from '@jbrowse/core/data_adapters/BaseAdapter';
2
+ import { SimpleFeature, fetchAndMaybeUnzip } from '@jbrowse/core/util';
3
+ import { openLocation } from '@jbrowse/core/util/io';
4
+ import { parseLineByLine } from '@jbrowse/core/util/parseLineByLine';
5
+ import { parseStarFusionBreakpoint, starFusionColumns, } from '@jbrowse/core/util/starFusion';
6
+ import { buildPairedIntervalTree, intervalTreeFeatures, } from '../adapterUtil.js';
7
+ export default class StarFusionAdapter extends BaseFeatureDataAdapter {
8
+ loadData = cachedSetup({ setup: opts => this.loadDataP(opts) });
9
+ static capabilities = ['getFeatures', 'getRefNames'];
10
+ async loadDataP(opts) {
11
+ const buffer = await fetchAndMaybeUnzip(openLocation(this.getConf('starFusionLocation'), this.pluginManager), opts);
12
+ let columnNames = [];
13
+ let leftIdx = -1;
14
+ let rightIdx = -1;
15
+ const feats1 = {};
16
+ const feats2 = {};
17
+ parseLineByLine(buffer, (line, lineIndex) => {
18
+ if (lineIndex === 0) {
19
+ columnNames = starFusionColumns(line);
20
+ leftIdx = columnNames.indexOf('LeftBreakpoint');
21
+ rightIdx = columnNames.indexOf('RightBreakpoint');
22
+ }
23
+ else if (!line.startsWith('#')) {
24
+ const cols = line.split('\t');
25
+ const left = cols[leftIdx];
26
+ const right = cols[rightIdx];
27
+ if (left && right) {
28
+ const leftRef = parseStarFusionBreakpoint(left, true).refName;
29
+ const rightRef = parseStarFusionBreakpoint(right, false).refName;
30
+ (feats1[leftRef] ??= []).push(line);
31
+ (feats2[rightRef] ??= []).push(line);
32
+ }
33
+ }
34
+ return true;
35
+ }, opts?.statusCallback);
36
+ return { columnNames, feats1, feats2 };
37
+ }
38
+ async getRefNames(opts = {}) {
39
+ const { feats1, feats2 } = await this.loadData(opts);
40
+ return [...new Set([...Object.keys(feats1), ...Object.keys(feats2)])];
41
+ }
42
+ featureFromLine(line, columnNames, uniqueId, flip) {
43
+ const cols = line.split('\t');
44
+ const row = Object.fromEntries(columnNames.map((name, i) => [name, cols[i]]));
45
+ const donor = parseStarFusionBreakpoint(row.LeftBreakpoint, true);
46
+ const acceptor = parseStarFusionBreakpoint(row.RightBreakpoint, false);
47
+ const [primary, mate] = flip ? [acceptor, donor] : [donor, acceptor];
48
+ return new SimpleFeature({
49
+ uniqueId,
50
+ ...primary,
51
+ name: row.FusionName,
52
+ score: row.JunctionReadCount ? +row.JunctionReadCount : undefined,
53
+ type: 'fusion',
54
+ mate,
55
+ ...row,
56
+ });
57
+ }
58
+ async loadFeatureTreeP(refName) {
59
+ const { columnNames, feats1, feats2 } = await this.loadData();
60
+ return buildPairedIntervalTree(feats1, feats2, refName, this.id, (line, uniqueId, flip) => this.featureFromLine(line, columnNames, uniqueId, flip));
61
+ }
62
+ treeFeatures = intervalTreeFeatures(opts => this.loadData(opts), refName => this.loadFeatureTreeP(refName));
63
+ getFeatures(query, opts) {
64
+ return this.treeFeatures(query, opts);
65
+ }
66
+ }
@@ -0,0 +1,30 @@
1
+ import type { Instance } from '@jbrowse/mobx-state-tree';
2
+ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record<string, unknown>;
3
+ /**
4
+ * #config StarFusionAdapter
5
+ * #trackType VariantTrack
6
+ * #fileFormat variants | STAR-Fusion
7
+ * used to load STAR-Fusion `star-fusion.fusion_predictions.tsv` output
8
+ *
9
+ * #example
10
+ * ```js
11
+ * {
12
+ * type: 'StarFusionAdapter',
13
+ * uri: 'https://example.com/star-fusion.fusion_predictions.tsv',
14
+ * }
15
+ * ```
16
+ */
17
+ declare const StarFusionAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
18
+ type: {
19
+ type: "string";
20
+ } & {
21
+ defaultValue: string;
22
+ };
23
+ readonly starFusionLocation: {
24
+ type: "fileLocation";
25
+ } & {
26
+ defaultValue: unknown;
27
+ };
28
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined, true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>;
29
+ export type StarFusionAdapterConfig = Instance<typeof StarFusionAdapter>;
30
+ export default StarFusionAdapter;
@@ -0,0 +1,43 @@
1
+ import { ConfigurationSchema, expandUriShorthand, } from '@jbrowse/core/configuration';
2
+ export function normalizeSnapshot(snap) {
3
+ return expandUriShorthand(snap, 'starFusionLocation');
4
+ }
5
+ /**
6
+ * #config StarFusionAdapter
7
+ * #trackType VariantTrack
8
+ * #fileFormat variants | STAR-Fusion
9
+ * used to load STAR-Fusion `star-fusion.fusion_predictions.tsv` output
10
+ *
11
+ * #example
12
+ * ```js
13
+ * {
14
+ * type: 'StarFusionAdapter',
15
+ * uri: 'https://example.com/star-fusion.fusion_predictions.tsv',
16
+ * }
17
+ * ```
18
+ */
19
+ const StarFusionAdapter = ConfigurationSchema('StarFusionAdapter', {
20
+ /**
21
+ * #slot
22
+ */
23
+ starFusionLocation: {
24
+ type: 'fileLocation',
25
+ description: 'STAR-Fusion TSV output file (plain text or gzipped)',
26
+ defaultValue: {
27
+ uri: '/path/to/star-fusion.fusion_predictions.tsv',
28
+ locationType: 'UriLocation',
29
+ },
30
+ },
31
+ }, {
32
+ explicitlyTyped: true,
33
+ /**
34
+ * #preProcessSnapshot
35
+ *
36
+ * Allows minimal config:
37
+ * ```json
38
+ * { "type": "StarFusionAdapter", "uri": "star-fusion.tsv" }
39
+ * ```
40
+ */
41
+ preProcessSnapshot: normalizeSnapshot,
42
+ });
43
+ export default StarFusionAdapter;
@@ -0,0 +1,2 @@
1
+ import type PluginManager from '@jbrowse/core/PluginManager';
2
+ export default function StarFusionAdapterF(pluginManager: PluginManager): void;
@@ -0,0 +1,12 @@
1
+ import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType';
2
+ import configSchema, { normalizeSnapshot } from './configSchema.js';
3
+ export default function StarFusionAdapterF(pluginManager) {
4
+ pluginManager.addAdapterType(() => new AdapterType({
5
+ name: 'StarFusionAdapter',
6
+ displayName: 'STAR-Fusion adapter',
7
+ configSchema,
8
+ getAdapterClass: () => import('./StarFusionAdapter.js').then(r => r.default),
9
+ locationKey: 'starFusionLocation',
10
+ normalizeSnapshot,
11
+ }));
12
+ }
@@ -0,0 +1,5 @@
1
+ import { IntervalTree } from '@jbrowse/core/util';
2
+ import type { BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
3
+ import type { Feature, Region } from '@jbrowse/core/util';
4
+ export declare function intervalTreeFeatures(loadData: (opts: BaseOptions) => Promise<unknown>, buildTree: (refName: string) => Promise<IntervalTree<Feature> | undefined>): (query: Region, opts?: BaseOptions) => import("rxjs").Observable<Feature>;
5
+ export declare function buildPairedIntervalTree(feats1: Record<string, string[]>, feats2: Record<string, string[]>, refName: string, idPrefix: string, makeFeature: (line: string, uniqueId: string, flip: boolean) => Feature): IntervalTree<Feature>;
@@ -0,0 +1,43 @@
1
+ import { IntervalTree } from '@jbrowse/core/util';
2
+ import { ObservableCreate } from '@jbrowse/core/util/rxjs';
3
+ // `getFeatures` for an in-memory interval-tree adapter: one tree per refName,
4
+ // built once and rebuilt after a failure. `loadData` is awaited with each
5
+ // caller's opts ahead of the tree, so every fetch joins the whole-file load's
6
+ // progress rather than only the one that started it.
7
+ export function intervalTreeFeatures(loadData, buildTree) {
8
+ const trees = new Map();
9
+ const loadTree = (refName) => {
10
+ let tree = trees.get(refName);
11
+ if (tree === undefined) {
12
+ tree = buildTree(refName).catch((e) => {
13
+ trees.delete(refName);
14
+ throw e;
15
+ });
16
+ trees.set(refName, tree);
17
+ }
18
+ return tree;
19
+ };
20
+ return (query, opts = {}) => ObservableCreate(async (observer) => {
21
+ await loadData(opts);
22
+ const tree = await loadTree(query.refName);
23
+ for (const f of tree?.search([query.start, query.end]) ?? []) {
24
+ observer.next(f);
25
+ }
26
+ observer.complete();
27
+ }, opts.signal);
28
+ }
29
+ // Build one interval tree for a refName from paired-feature buckets, inserting
30
+ // the records that start on this ref (feats1, flip=false) and those whose mate
31
+ // starts here (feats2, flip=true). Shared by BedpeAdapter and StarFusionAdapter.
32
+ export function buildPairedIntervalTree(feats1, feats2, refName, idPrefix, makeFeature) {
33
+ const tree = new IntervalTree();
34
+ for (const [i, line] of (feats1[refName] ?? []).entries()) {
35
+ const f = makeFeature(line, `${idPrefix}-${refName}-${i}-r1`, false);
36
+ tree.insert([f.get('start'), f.get('end')], f);
37
+ }
38
+ for (const [i, line] of (feats2[refName] ?? []).entries()) {
39
+ const f = makeFeature(line, `${idPrefix}-${refName}-${i}-r2`, true);
40
+ tree.insert([f.get('start'), f.get('end')], f);
41
+ }
42
+ return tree;
43
+ }
@@ -0,0 +1,11 @@
1
+ import type { Feature } from '@jbrowse/core/util';
2
+ export declare function makeBedGraphFeature({ uniqueId, refName, start, end, names, j, value, rowSource, }: {
3
+ uniqueId: string;
4
+ refName: string;
5
+ start: number;
6
+ end: number;
7
+ names: string[];
8
+ j: number;
9
+ value: string;
10
+ rowSource?: string;
11
+ }): Feature | undefined;
@@ -0,0 +1,20 @@
1
+ import { SimpleFeature } from '@jbrowse/core/util';
2
+ // Build a single-score bedGraph feature for value column j, or undefined when
3
+ // the value is not numeric. A wide file names each value column's source in
4
+ // its header; a tidy one has a `source` column naming each row's instead.
5
+ // Shared by BedGraphAdapter and BedGraphTabixAdapter.
6
+ export function makeBedGraphFeature({ uniqueId, refName, start, end, names, j, value, rowSource, }) {
7
+ const score = +value;
8
+ return Number.isNaN(score)
9
+ ? undefined
10
+ : new SimpleFeature({
11
+ id: uniqueId,
12
+ data: {
13
+ refName,
14
+ start,
15
+ end,
16
+ score,
17
+ source: rowSource ?? (names[j] || `col${j}`),
18
+ },
19
+ });
20
+ }
@@ -0,0 +1 @@
1
+ export declare function copyExcept(data: Record<string, unknown>, excluded: ReadonlySet<string>): Record<string, unknown>;
@@ -0,0 +1,11 @@
1
+ // `const { a, b, ...rest } = data` in the same key order, which measured
2
+ // slower on every BED line shape (benches/featureData.bench.ts)
3
+ export function copyExcept(data, excluded) {
4
+ const out = {};
5
+ for (const key in data) {
6
+ if (!excluded.has(key)) {
7
+ out[key] = data[key];
8
+ }
9
+ }
10
+ return out;
11
+ }
@@ -16,7 +16,7 @@ export declare function generateBedMethylFeature({ splitLine, uniqueId, refName,
16
16
  end: number;
17
17
  code: string | undefined;
18
18
  score: number;
19
- strand: string | undefined;
19
+ strand: number;
20
20
  color: string | undefined;
21
21
  source: string | undefined;
22
22
  n_valid_cov: string | undefined;
@@ -1,19 +1,37 @@
1
+ import { parseStrand } from './util.js';
2
+ // this uses modkit bedMethyl. unclear how to reliably detect minimal 9+2 bedMethyl
1
3
  export function isBedMethylFeature({ splitLine, start, end, }) {
2
- return (+(splitLine[6] || 0) === start &&
3
- +(splitLine[7] || 0) === end &&
4
- [9, 10, 11, 12, 13, 14, 15, 16, 17].every(r => splitLine[r] && !Number.isNaN(+splitLine[r])));
4
+ if (splitLine.length < 18 ||
5
+ +splitLine[6] !== start ||
6
+ +splitLine[7] !== end) {
7
+ return false;
8
+ }
9
+ // columns 9-17 are the nine numeric methylation stats
10
+ for (let i = 9; i < 18; i++) {
11
+ const x = splitLine[i];
12
+ if (!x || Number.isNaN(+x)) {
13
+ return false;
14
+ }
15
+ }
16
+ return true;
5
17
  }
6
18
  export function generateBedMethylFeature({ splitLine, uniqueId, refName, start, end, }) {
7
- const [, , , code, , strand, , , color, n_valid_cov, fraction_modified, n_mod, n_canonical, n_other_mod, n_delete, n_fail, n_diff, n_nocall,] = splitLine;
19
+ // see
20
+ // https://github.com/nanoporetech/modkit?tab=readme-ov-file#description-of-bedmethyl-output
21
+ const code = splitLine[3];
22
+ const strandRaw = splitLine[5];
23
+ const color = splitLine[8];
24
+ const [n_valid_cov, fraction_modified, n_mod, n_canonical, n_other_mod, n_delete, n_fail, n_diff, n_nocall,] = splitLine.slice(9);
8
25
  return {
9
26
  uniqueId,
10
27
  refName,
11
28
  start,
12
29
  end,
13
30
  code,
14
- score: +fraction_modified || 0,
15
- strand,
31
+ score: +fraction_modified,
32
+ strand: parseStrand(strandRaw),
16
33
  color,
34
+ // source mirrors code so MultiQuantitativeTrack groups by modification code
17
35
  source: code,
18
36
  n_valid_cov,
19
37
  fraction_modified,
@@ -0,0 +1,28 @@
1
+ export declare function isRastairMethylFeature(names: string[]): boolean;
2
+ export declare function generateRastairMethylFeature({ splitLine, names, uniqueId, refName, start, end, }: {
3
+ splitLine: string[];
4
+ names: string[];
5
+ uniqueId: string;
6
+ refName: string;
7
+ start: number;
8
+ end: number;
9
+ }): {
10
+ uniqueId: string;
11
+ refName: string;
12
+ start: number;
13
+ end: number;
14
+ code: string;
15
+ source: string;
16
+ score: number;
17
+ fraction_modified: number;
18
+ strand: number;
19
+ n_valid_cov: string | undefined;
20
+ n_mod: string | undefined;
21
+ n_canonical: string | undefined;
22
+ beta_est: string | undefined;
23
+ no_snp: string | undefined;
24
+ snp: string | undefined;
25
+ coverage: string | undefined;
26
+ genotype: string | undefined;
27
+ gt_conf_score: string | undefined;
28
+ };