@jbrowse/plugin-bed 5.0.0-beta.13 → 5.0.0-beta.14

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.
@@ -10,6 +10,17 @@ export default class BedAdapter extends BaseFeatureDataAdapter<BedAdapterConfig>
10
10
  private getParser;
11
11
  static capabilities: string[];
12
12
  private loadDataP;
13
+ /** Each column the parser reads, as its autoSql or the header declares it. */
14
+ getAutoSqlFields(): Promise<{
15
+ isArray: boolean;
16
+ arrayIsNumeric: boolean;
17
+ isNumeric: boolean;
18
+ size?: number | string;
19
+ type: string;
20
+ name: string;
21
+ comment: string;
22
+ vals?: string[];
23
+ }[]>;
13
24
  getRefNames(opts?: BaseOptions): Promise<string[]>;
14
25
  getHeader(opts?: BaseOptions): Promise<string>;
15
26
  getNames(): Promise<string[] | undefined>;
@@ -19,6 +19,10 @@ export default class BedAdapter extends BaseFeatureDataAdapter {
19
19
  const buffer = await fetchAndMaybeUnzip(openLocation(this.getConf('bedLocation'), this.pluginManager), opts);
20
20
  return bucketBedLines(buffer, opts?.statusCallback);
21
21
  }
22
+ /** Each column the parser reads, as its autoSql or the header declares it. */
23
+ async getAutoSqlFields() {
24
+ return (await this.getParser()).autoSql.fields;
25
+ }
22
26
  async getRefNames(opts = {}) {
23
27
  const { features } = await this.loadData(opts);
24
28
  return Object.keys(features);
@@ -11,8 +11,8 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
11
11
  * ... and a jexl callback reading `feature.itemRgb` gets `undefined`. Set
12
12
  * `columnNames` to refer to them by name.
13
13
  *
14
- * used to load plain-text BED files. Loads the whole file into memory, so
15
- * prefer the BedTabixAdapter for large files.
14
+ * Reads plain-text BED files. The adapter loads the whole file into memory, so
15
+ * use `BedTabixAdapter` for large files.
16
16
  *
17
17
  * #example
18
18
  * ```js
@@ -13,8 +13,8 @@ export function normalizeSnapshot(snap) {
13
13
  * ... and a jexl callback reading `feature.itemRgb` gets `undefined`. Set
14
14
  * `columnNames` to refer to them by name.
15
15
  *
16
- * used to load plain-text BED files. Loads the whole file into memory, so
17
- * prefer the BedTabixAdapter for large files.
16
+ * Reads plain-text BED files. The adapter loads the whole file into memory, so
17
+ * use `BedTabixAdapter` for large files.
18
18
  *
19
19
  * #example
20
20
  * ```js
@@ -94,6 +94,7 @@ const BedAdapter = ConfigurationSchema('BedAdapter', {
94
94
  },
95
95
  }, {
96
96
  explicitlyTyped: true,
97
+ closed: true,
97
98
  /**
98
99
  * #preProcessSnapshot
99
100
  *
@@ -4,8 +4,9 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
4
4
  * #config BedGraphAdapter
5
5
  * #trackType QuantitativeTrack
6
6
  * #fileFormat quantitative | BedGraph (plain) | Loaded entirely into memory; for small files
7
- * used to load plain-text bedGraph signal files. Loads the whole file into
8
- * memory, so prefer the BedGraphTabixAdapter for large files.
7
+ * Reads plain-text bedGraph signal files. The adapter loads the whole file into
8
+ * memory, so use `BedGraphTabixAdapter` for large files.
9
+ *
9
10
  * Several signals in one file are a `MultiQuantitativeTrack`'s subtracks:
10
11
  * one value column each, named by the header, or a `source` column naming each
11
12
  * row's, which is the form Save track data writes.
@@ -6,8 +6,9 @@ export function normalizeSnapshot(snap) {
6
6
  * #config BedGraphAdapter
7
7
  * #trackType QuantitativeTrack
8
8
  * #fileFormat quantitative | BedGraph (plain) | Loaded entirely into memory; for small files
9
- * used to load plain-text bedGraph signal files. Loads the whole file into
10
- * memory, so prefer the BedGraphTabixAdapter for large files.
9
+ * Reads plain-text bedGraph signal files. The adapter loads the whole file into
10
+ * memory, so use `BedGraphTabixAdapter` for large files.
11
+ *
11
12
  * Several signals in one file are a `MultiQuantitativeTrack`'s subtracks:
12
13
  * one value column each, named by the header, or a `source` column naming each
13
14
  * row's, which is the form Save track data writes.
@@ -43,6 +44,7 @@ const BedGraphAdapter = ConfigurationSchema('BedGraphAdapter', {
43
44
  },
44
45
  }, {
45
46
  explicitlyTyped: true,
47
+ closed: true,
46
48
  /**
47
49
  * #preProcessSnapshot
48
50
  *
@@ -4,6 +4,8 @@ import type { BedGraphTabixAdapterConfig } from './configSchema.ts';
4
4
  import type { BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
5
5
  import type { Feature, Region } from '@jbrowse/core/util';
6
6
  export default class BedGraphTabixAdapter extends BaseFeatureDataAdapter<BedGraphTabixAdapterConfig> {
7
+ private file?;
8
+ freeResources(): void;
7
9
  protected configure: (opts?: BaseOptions) => Promise<{
8
10
  columnNames: string[];
9
11
  bedGraph: TabixIndexedFile;
@@ -9,6 +9,11 @@ import { readTabixHeaderLines } from '@jbrowse/core/util/tabix';
9
9
  import { makeBedGraphFeature } from '../bedGraphUtil.js';
10
10
  import { parseNamesFromHeader } from '../util.js';
11
11
  export default class BedGraphTabixAdapter extends BaseFeatureDataAdapter {
12
+ // set once the file is open, for dataAdapterCache's eviction to clear
13
+ file;
14
+ freeResources() {
15
+ this.file?.clearChunkCache();
16
+ }
12
17
  // `label` because the index setup narrates nothing itself; the helper shows
13
18
  // it only while the first attempt is in flight, so pan/zoom re-entry (every
14
19
  // getFeatures/byte-estimate awaits it) doesn't re-flash "Downloading index"
@@ -27,6 +32,7 @@ export default class BedGraphTabixAdapter extends BaseFeatureDataAdapter {
27
32
  chunkCacheBudget: decompressedBytesBudget,
28
33
  bgzfWorkerPool: sharedBgzfWorkerPool(),
29
34
  });
35
+ this.file = bedGraph;
30
36
  const columnNames = this.getConf('columnNames');
31
37
  // Not bedGraph.getHeader(): that returns only a `#`-commented header, so a
32
38
  // file whose header is a plain row skipped via `tabix -S 1` reported none
@@ -53,8 +59,7 @@ export default class BedGraphTabixAdapter extends BaseFeatureDataAdapter {
53
59
  getFeatures(query, opts = {}) {
54
60
  return ObservableCreate(async (observer) => {
55
61
  const { bedGraph } = await this.configure(opts);
56
- const meta = await bedGraph.getMetadata();
57
- const { columnNumbers } = meta;
62
+ const { columnNumbers } = await bedGraph.getMetadata();
58
63
  const colRef = columnNumbers.ref - 1;
59
64
  const colStart = columnNumbers.start - 1;
60
65
  const colEnd = columnNumbers.end - 1;
@@ -4,7 +4,8 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
4
4
  * #config BedGraphTabixAdapter
5
5
  * #trackType QuantitativeTrack
6
6
  * #fileFormat quantitative | BedGraph (tabix)
7
- * used to load bgzip-compressed, tabix-indexed bedGraph signal files.
7
+ * Reads bgzip-compressed, tabix-indexed bedGraph signal files.
8
+ *
8
9
  * Several signals in one file are a `MultiQuantitativeTrack`'s subtracks:
9
10
  * one value column each, named by the header, or a `source` column naming each
10
11
  * row's, which is the form Save track data writes.
@@ -6,7 +6,8 @@ export function normalizeSnapshot(snap) {
6
6
  * #config BedGraphTabixAdapter
7
7
  * #trackType QuantitativeTrack
8
8
  * #fileFormat quantitative | BedGraph (tabix)
9
- * used to load bgzip-compressed, tabix-indexed bedGraph signal files.
9
+ * Reads bgzip-compressed, tabix-indexed bedGraph signal files.
10
+ *
10
11
  * Several signals in one file are a `MultiQuantitativeTrack`'s subtracks:
11
12
  * one value column each, named by the header, or a `source` column naming each
12
13
  * row's, which is the form Save track data writes.
@@ -36,7 +37,7 @@ const BedGraphTabixAdapter = ConfigurationSchema('BedGraphTabixAdapter', {
36
37
  },
37
38
  /**
38
39
  * #slot
39
- * where the tabix index is and which kind it is. The `uri` shorthand derives
40
+ * The tabix index location and its kind. The `uri` shorthand derives
40
41
  * both, so a config using it states neither.
41
42
  */
42
43
  index: tabixIndexSchema(),
@@ -50,6 +51,7 @@ const BedGraphTabixAdapter = ConfigurationSchema('BedGraphTabixAdapter', {
50
51
  },
51
52
  }, {
52
53
  explicitlyTyped: true,
54
+ closed: true,
53
55
  /**
54
56
  * #preProcessSnapshot
55
57
  *
@@ -34,6 +34,18 @@ export default class BedTabixAdapter extends BaseFeatureDataAdapter<BedTabixAdap
34
34
  }>;
35
35
  getNames: (opts?: BaseOptions) => Promise<string[] | undefined>;
36
36
  constructor(config: BedTabixAdapterConfig, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
37
+ freeResources(): void;
38
+ /** Each column the parser reads, as its autoSql or the header declares it. */
39
+ getAutoSqlFields(): Promise<{
40
+ isArray: boolean;
41
+ arrayIsNumeric: boolean;
42
+ isNumeric: boolean;
43
+ size?: number | string;
44
+ type: string;
45
+ name: string;
46
+ comment: string;
47
+ vals?: string[];
48
+ }[]>;
37
49
  getRefNames(opts?: BaseOptions): Promise<string[]>;
38
50
  getHeader(opts?: BaseOptions): Promise<string>;
39
51
  /**
@@ -47,6 +47,13 @@ export default class BedTabixAdapter extends BaseFeatureDataAdapter {
47
47
  bgzfWorkerPool: sharedBgzfWorkerPool(),
48
48
  });
49
49
  }
50
+ freeResources() {
51
+ this.bed.clearChunkCache();
52
+ }
53
+ /** Each column the parser reads, as its autoSql or the header declares it. */
54
+ async getAutoSqlFields() {
55
+ return (await this.getParser()).autoSql.fields;
56
+ }
50
57
  async getRefNames(opts = {}) {
51
58
  return downloadStatus('Downloading index', opts.statusCallback, onProgress => this.bed.getReferenceSequenceNames({ ...opts, onProgress }));
52
59
  }
@@ -77,37 +84,54 @@ export default class BedTabixAdapter extends BaseFeatureDataAdapter {
77
84
  // warms the index under its own status label — getLines would otherwise
78
85
  // download it under "Downloading features"
79
86
  await this.getMetadata(opts);
80
- const names = await this.getNames();
81
- const parser = await this.getParser();
82
87
  const scoreColumn = readConfObject(this.config, 'scoreColumn');
83
88
  const disableGeneHeuristic = readConfObject(this.config, 'disableGeneHeuristic');
89
+ let ready;
90
+ const early = [];
91
+ const emit = ({ names, parser }, { splitLine, start, end, offset }) => {
92
+ observer.next(new SimpleFeature(featureData({
93
+ splitLine,
94
+ refName: query.refName,
95
+ start,
96
+ end,
97
+ scoreColumn,
98
+ parser,
99
+ uniqueId: `${this.id}-${offset}`,
100
+ names,
101
+ disableGeneHeuristic,
102
+ })));
103
+ };
104
+ const loaded = Promise.all([this.getNames(), this.getParser()]).then(([names, parser]) => {
105
+ ready = { names, parser };
106
+ for (const row of early.splice(0)) {
107
+ emit(ready, row);
108
+ }
109
+ });
84
110
  checkAbortSignal(signal);
85
- await downloadStatus('Downloading features', statusCallback, onProgress =>
86
- // start/end come from @gmod/tabix rather than being re-derived from
87
- // the line: it located the coordinate columns to find these lines at
88
- // all, and already applied the index's coordinate offset (-1 for a
89
- // 1-based-closed preset) and its no-end-column convention (a single
90
- // position becomes start..start+1). refName is likewise the query's
91
- // — getLines only calls back for lines whose ref column matches it.
92
- this.bed.getLines(query.refName, query.start, query.end, {
93
- lineCallback: (line, fileOffset, start, end) => {
94
- checkAbortSignal(signal);
95
- const splitLine = line.split('\t');
96
- observer.next(new SimpleFeature(featureData({
97
- splitLine,
98
- refName: query.refName,
99
- start,
100
- end,
101
- scoreColumn,
102
- parser,
103
- uniqueId: `${this.id}-${fileOffset}`,
104
- names,
105
- disableGeneHeuristic,
106
- })));
107
- },
108
- onProgress,
109
- signal,
110
- }));
111
+ await Promise.all([
112
+ loaded,
113
+ downloadStatus('Downloading features', statusCallback, onProgress =>
114
+ // start/end come from @gmod/tabix rather than being re-derived from
115
+ // the line: it located the coordinate columns to find these lines at
116
+ // all, and already applied the index's coordinate offset (-1 for a
117
+ // 1-based-closed preset) and its no-end-column convention (a single
118
+ // position becomes start..start+1). refName is likewise the query's
119
+ // — getLines only calls back for lines whose ref column matches it.
120
+ this.bed.getLines(query.refName, query.start, query.end, {
121
+ lineCallback: (line, offset, start, end) => {
122
+ checkAbortSignal(signal);
123
+ const row = { splitLine: line.split('\t'), start, end, offset };
124
+ if (ready) {
125
+ emit(ready, row);
126
+ }
127
+ else {
128
+ early.push(row);
129
+ }
130
+ },
131
+ onProgress,
132
+ signal,
133
+ })),
134
+ ]);
111
135
  observer.complete();
112
136
  }, signal);
113
137
  }
@@ -4,6 +4,7 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
4
4
  * #config BedTabixAdapter
5
5
  * #trackType FeatureTrack
6
6
  * #fileFormat feature | BED (tabix)
7
+ * Reads bgzip-compressed, tabix-indexed BED files.
7
8
  *
8
9
  * #example
9
10
  * The `uri` shorthand auto-resolves the `.tbi` index; add `csi: true` for a
@@ -16,9 +17,6 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
16
17
  * ```
17
18
  */
18
19
  declare const BedTabixAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
19
- readonly densityAdapter: {
20
- type: "maybeFrozen";
21
- };
22
20
  type: {
23
21
  type: "string";
24
22
  } & {
@@ -1,5 +1,4 @@
1
1
  import { ConfigurationSchema, expandTabixShorthand, tabixIndexSchema, } from '@jbrowse/core/configuration';
2
- import { densityAdapterConfigSchemaFields } from '@jbrowse/core/data_adapters/BaseAdapter';
3
2
  export function normalizeSnapshot(snap) {
4
3
  return expandTabixShorthand(snap, 'bedGzLocation');
5
4
  }
@@ -7,6 +6,7 @@ export function normalizeSnapshot(snap) {
7
6
  * #config BedTabixAdapter
8
7
  * #trackType FeatureTrack
9
8
  * #fileFormat feature | BED (tabix)
9
+ * Reads bgzip-compressed, tabix-indexed BED files.
10
10
  *
11
11
  * #example
12
12
  * The `uri` shorthand auto-resolves the `.tbi` index; add `csi: true` for a
@@ -33,7 +33,7 @@ const BedTabixAdapter = ConfigurationSchema('BedTabixAdapter', {
33
33
  },
34
34
  /**
35
35
  * #slot
36
- * where the tabix index is and which kind it is. The `uri` shorthand derives
36
+ * The tabix index location and its kind. The `uri` shorthand derives
37
37
  * both, so a config using it states neither.
38
38
  */
39
39
  index: tabixIndexSchema(),
@@ -69,9 +69,9 @@ const BedTabixAdapter = ConfigurationSchema('BedTabixAdapter', {
69
69
  description: 'Disable the heuristic that auto-detects BED12 features as gene/transcript structures. Useful for files that have BED12-like structure but are not genes (e.g. tandem duplications)',
70
70
  defaultValue: false,
71
71
  },
72
- ...densityAdapterConfigSchemaFields,
73
72
  }, {
74
73
  explicitlyTyped: true,
74
+ closed: true,
75
75
  /**
76
76
  * #preProcessSnapshot
77
77
  *
@@ -4,7 +4,8 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
4
4
  * #config BedpeAdapter
5
5
  * #trackType VariantTrack
6
6
  * #fileFormat variants | BEDPE | Paired/breakend records, e.g. SV calls or Hi-C loops
7
- * intended for SVs in a single assembly
7
+ * Reads BEDPE files of paired breakends, such as structural variant calls
8
+ * within a single assembly.
8
9
  *
9
10
  * #example
10
11
  * ```js
@@ -6,7 +6,8 @@ export function normalizeSnapshot(snap) {
6
6
  * #config BedpeAdapter
7
7
  * #trackType VariantTrack
8
8
  * #fileFormat variants | BEDPE | Paired/breakend records, e.g. SV calls or Hi-C loops
9
- * intended for SVs in a single assembly
9
+ * Reads BEDPE files of paired breakends, such as structural variant calls
10
+ * within a single assembly.
10
11
  *
11
12
  * #example
12
13
  * ```js
@@ -38,6 +39,7 @@ const BedpeAdapter = ConfigurationSchema('BedpeAdapter', {
38
39
  },
39
40
  }, {
40
41
  explicitlyTyped: true,
42
+ closed: true,
41
43
  /**
42
44
  * #preProcessSnapshot
43
45
  *
@@ -11,13 +11,21 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter<BigBedAdapterC
11
11
  bigbed: BigBed;
12
12
  header: import("@gmod/bbi").BigWigHeaderWithRefNames;
13
13
  parser: BED;
14
+ positionalItemRgb: string | undefined;
14
15
  }>;
15
16
  configurePre(opts?: BaseOptions): Promise<{
16
17
  bigbed: BigBed;
17
18
  header: import("@gmod/bbi").BigWigHeaderWithRefNames;
18
19
  parser: BED;
20
+ positionalItemRgb: string | undefined;
19
21
  }>;
20
22
  getRefNames(opts?: BaseOptions): Promise<string[]>;
23
+ /** Each contig's length off the chrom table, which lists empty contigs too. */
24
+ getContigs(opts?: BaseOptions): Promise<{
25
+ refName: string;
26
+ length: number | undefined;
27
+ hasData: null;
28
+ }[]>;
21
29
  getRegionByteSize(regions: Region[], opts?: BaseOptions): Promise<number>;
22
30
  getRefNameAliases(opts?: BaseOptions): Promise<{
23
31
  refName: unknown;
@@ -28,11 +36,26 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter<BigBedAdapterC
28
36
  getHeader(opts?: BaseOptions): Promise<{
29
37
  version: number;
30
38
  fileType: "bigbed" | "bigwig";
31
- autoSql: {};
39
+ autoSql: {
40
+ type?: string;
41
+ name?: string;
42
+ comment?: string;
43
+ };
32
44
  fields: {
33
45
  [k: string]: string;
34
46
  };
35
47
  }>;
48
+ /** Each column the file's autoSql declares, with its type and comment. */
49
+ getAutoSqlFields(opts?: BaseOptions): Promise<{
50
+ isArray: boolean;
51
+ arrayIsNumeric: boolean;
52
+ isNumeric: boolean;
53
+ size?: number | string;
54
+ type: string;
55
+ name: string;
56
+ comment: string;
57
+ vals?: string[];
58
+ }[]>;
36
59
  getMetadata(opts?: BaseOptions): Promise<{
37
60
  [k: string]: string;
38
61
  }>;
@@ -6,6 +6,12 @@ import { openLocation } from '@jbrowse/core/util/io';
6
6
  import { ObservableCreate } from '@jbrowse/core/util/rxjs';
7
7
  import { firstValueFrom, toArray } from 'rxjs';
8
8
  import { featureData } from '../util.js';
9
+ // UCSC reads column 9 of a bed9+ bigBed as itemRgb whatever its autoSql calls
10
+ // it (spliceVarDb calls it `color`); colorBits reads only the standard names.
11
+ function positionalItemRgbField(definedFieldCount, fields) {
12
+ const name = definedFieldCount >= 9 ? fields[8]?.name : undefined;
13
+ return name && name !== 'itemRgb' && name !== 'reserved' ? name : undefined;
14
+ }
9
15
  export default class BigBedAdapter extends BaseFeatureDataAdapter {
10
16
  // `label` on cachedSetup so "Downloading header" shows only while the first
11
17
  // fetch is in flight; every later getFeatures resolves from the memo with no
@@ -27,12 +33,22 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
27
33
  bigbed,
28
34
  header,
29
35
  parser,
36
+ positionalItemRgb: positionalItemRgbField(header.definedFieldCount, parser.autoSql.fields),
30
37
  };
31
38
  }
32
39
  async getRefNames(opts) {
33
40
  const { header } = await this.configure(opts);
34
41
  return Object.keys(header.refsByName);
35
42
  }
43
+ /** Each contig's length off the chrom table, which lists empty contigs too. */
44
+ async getContigs(opts) {
45
+ const { header } = await this.configure(opts);
46
+ return Object.entries(header.refsByName).map(([refName, id]) => ({
47
+ refName,
48
+ length: header.refsByNumber[id]?.length,
49
+ hasData: null,
50
+ }));
51
+ }
36
52
  // Compressed download-size estimate straight from the bbi R-tree index (block
37
53
  // byte lengths, no data blocks read), so a display can byte-gate an over-large
38
54
  // BigBed fetch before it starts. Overrides the base no-estimate default, which
@@ -81,6 +97,11 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
81
97
  fields: await this.getMetadata(opts),
82
98
  };
83
99
  }
100
+ /** Each column the file's autoSql declares, with its type and comment. */
101
+ async getAutoSqlFields(opts) {
102
+ const { parser } = await this.configure(opts);
103
+ return parser.autoSql.fields;
104
+ }
84
105
  async getMetadata(opts) {
85
106
  const { parser } = await this.configure(opts);
86
107
  const { fields } = parser.autoSql;
@@ -91,7 +112,7 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
91
112
  const scoreColumn = this.getConf('scoreColumn');
92
113
  const aggregateField = this.getConf('aggregateField');
93
114
  const disableGeneHeuristic = this.getConf('disableGeneHeuristic');
94
- const { parser, bigbed } = await this.configure(opts);
115
+ const { parser, bigbed, positionalItemRgb } = await this.configure(opts);
95
116
  // downloadStatus, not updateStatus: bbi knows the total block bytes up front
96
117
  // (they come from the R-tree index) so this reports a determinate fraction
97
118
  // rather than an indeterminate spinner. Matters most here — BigBed is a
@@ -121,6 +142,9 @@ export default class BigBedAdapter extends BaseFeatureDataAdapter {
121
142
  refName: query.refName,
122
143
  disableGeneHeuristic,
123
144
  });
145
+ if (positionalItemRgb) {
146
+ f.itemRgb ??= f[positionalItemRgb];
147
+ }
124
148
  const aggr = f[aggregateField];
125
149
  const aggrIsNotNone = typeof aggr === 'string' && aggr && aggr !== 'none';
126
150
  if (aggrIsNotNone) {
@@ -4,6 +4,7 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
4
4
  * #config BigBedAdapter
5
5
  * #trackType FeatureTrack
6
6
  * #fileFormat feature | BigBed
7
+ * Reads BigBed files, the indexed binary form of BED.
7
8
  *
8
9
  * #example
9
10
  * ```js
@@ -14,9 +15,6 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
14
15
  * ```
15
16
  */
16
17
  declare const BigBedAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
17
- readonly densityAdapter: {
18
- type: "maybeFrozen";
19
- };
20
18
  type: {
21
19
  type: "string";
22
20
  } & {
@@ -1,5 +1,4 @@
1
1
  import { ConfigurationSchema, expandUriShorthand, } from '@jbrowse/core/configuration';
2
- import { densityAdapterConfigSchemaFields } from '@jbrowse/core/data_adapters/BaseAdapter';
3
2
  export function normalizeSnapshot(snap) {
4
3
  return expandUriShorthand(snap, 'bigBedLocation');
5
4
  }
@@ -7,6 +6,7 @@ export function normalizeSnapshot(snap) {
7
6
  * #config BigBedAdapter
8
7
  * #trackType FeatureTrack
9
8
  * #fileFormat feature | BigBed
9
+ * Reads BigBed files, the indexed binary form of BED.
10
10
  *
11
11
  * #example
12
12
  * ```js
@@ -53,9 +53,9 @@ const BigBedAdapter = ConfigurationSchema('BigBedAdapter', {
53
53
  description: 'Disable the heuristic that auto-detects BED12 features as gene/transcript structures. Useful for files that have BED12-like structure but are not genes (e.g. tandem duplications)',
54
54
  defaultValue: false,
55
55
  },
56
- ...densityAdapterConfigSchemaFields,
57
56
  }, {
58
57
  explicitlyTyped: true,
58
+ closed: true,
59
59
  /**
60
60
  * #preProcessSnapshot
61
61
  *
@@ -4,7 +4,8 @@ export declare function normalizeSnapshot(snap: Record<string, unknown>): Record
4
4
  * #config StarFusionAdapter
5
5
  * #trackType VariantTrack
6
6
  * #fileFormat variants | STAR-Fusion
7
- * used to load STAR-Fusion `star-fusion.fusion_predictions.tsv` output
7
+ * Reads the gene fusions that STAR-Fusion predicts, from its
8
+ * `star-fusion.fusion_predictions.tsv` output.
8
9
  *
9
10
  * #example
10
11
  * ```js
@@ -6,7 +6,8 @@ export function normalizeSnapshot(snap) {
6
6
  * #config StarFusionAdapter
7
7
  * #trackType VariantTrack
8
8
  * #fileFormat variants | STAR-Fusion
9
- * used to load STAR-Fusion `star-fusion.fusion_predictions.tsv` output
9
+ * Reads the gene fusions that STAR-Fusion predicts, from its
10
+ * `star-fusion.fusion_predictions.tsv` output.
10
11
  *
11
12
  * #example
12
13
  * ```js
@@ -30,6 +31,7 @@ const StarFusionAdapter = ConfigurationSchema('StarFusionAdapter', {
30
31
  },
31
32
  }, {
32
33
  explicitlyTyped: true,
34
+ closed: true,
33
35
  /**
34
36
  * #preProcessSnapshot
35
37
  *
@@ -1,4 +1,5 @@
1
1
  import { copyExcept } from './copyExcept.js';
2
+ import { toNumberList } from './numberColumns.js';
2
3
  // type guard: narrows input fields to required when true
3
4
  // strand===0 means unstranded — likely not a gene
4
5
  //
@@ -42,11 +43,6 @@ function calculatePhasesFromCds(cdsRegions, strand) {
42
43
  function frameToPhase(frame) {
43
44
  return (3 - frame) % 3;
44
45
  }
45
- function parseFrames(frames) {
46
- return typeof frames === 'string'
47
- ? frames.replace(/,$/, '').split(',').map(Number)
48
- : frames;
49
- }
50
46
  const TRANSCRIPT_OWN = new Set([
51
47
  'strand',
52
48
  'uniqueId',
@@ -70,7 +66,7 @@ export function generateUcscTranscript(data) {
70
66
  // exonFrames from bigGenePred - the @gmod/bed parser returns it in genomic order.
71
67
  // _exonFrames fallback supports BED files that use the underscore-prefixed column
72
68
  // name, which the parser leaves as raw text because it is not a standard column.
73
- const exonFrames = parseFrames(rest.exonFrames ?? rest._exonFrames);
69
+ const exonFrames = toNumberList((rest.exonFrames ?? rest._exonFrames));
74
70
  const feats = oldSubfeatures
75
71
  .filter(child => child.type === 'block')
76
72
  .sort((a, b) => a.start - b.start);
@@ -0,0 +1,4 @@
1
+ export type NumberColumn = number | string;
2
+ export type NumberListColumn = number[] | string[] | string;
3
+ export declare function toNumber(value: NumberColumn | undefined): number | undefined;
4
+ export declare function toNumberList(value: NumberListColumn | undefined): number[] | undefined;
@@ -0,0 +1,17 @@
1
+ export function toNumber(value) {
2
+ if (value === undefined || value === '') {
3
+ return undefined;
4
+ }
5
+ const n = Number(value);
6
+ return Number.isNaN(n) ? undefined : n;
7
+ }
8
+ export function toNumberList(value) {
9
+ return typeof value === 'string'
10
+ ? value
11
+ .split(',')
12
+ .filter(s => s !== '')
13
+ .map(Number)
14
+ : typeof value?.[0] === 'string'
15
+ ? value.map(Number)
16
+ : value;
17
+ }
package/esm/util.js CHANGED
@@ -5,6 +5,7 @@ import { generateBedMethylFeature, isBedMethylFeature, } from './generateBedMeth
5
5
  import { generateRastairMethylFeature, isRastairMethylFeature, } from './generateRastairMethylFeature.js';
6
6
  import { parseRepeatMaskerDescription } from './generateRepeatMaskerFeature.js';
7
7
  import { generateUcscTranscript, isUcscTranscript, } from './generateUcscTranscript.js';
8
+ import { toNumber, toNumberList } from './numberColumns.js';
8
9
  // Heuristically split features and header from a buffered BED file, bucketing
9
10
  // data lines by the first tab-separated column (refName).
10
11
  export function bucketBedLines(buffer, statusCallback) {
@@ -151,22 +152,23 @@ export function featureData({ splitLine, refName, start, end, parser, uniqueId,
151
152
  };
152
153
  }
153
154
  const rest = copyExcept(data, BED_OWN);
154
- const subfeatures = data.blockCount
155
+ const blockCount = toNumber(data.blockCount);
156
+ const subfeatures = blockCount
155
157
  ? makeBlocks({
156
158
  start,
157
159
  uniqueId,
158
160
  refName,
159
- chromStarts: data.chromStarts,
160
- blockCount: data.blockCount,
161
- blockSizes: data.blockSizes,
162
- blockStarts: data.blockStarts,
161
+ chromStarts: toNumberList(data.chromStarts),
162
+ blockCount,
163
+ blockSizes: toNumberList(data.blockSizes),
164
+ blockStarts: toNumberList(data.blockStarts),
163
165
  })
164
166
  : undefined;
165
167
  const transcriptCheck = {
166
168
  strand,
167
- blockCount: data.blockCount,
168
- thickStart: data.thickStart,
169
- thickEnd: data.thickEnd,
169
+ blockCount,
170
+ thickStart: toNumber(data.thickStart),
171
+ thickEnd: toNumber(data.thickEnd),
170
172
  };
171
173
  if (!disableGeneHeuristic &&
172
174
  subfeatures &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-bed",
3
- "version": "5.0.0-beta.13",
3
+ "version": "5.0.0-beta.14",
4
4
  "type": "module",
5
5
  "description": "JBrowse 2 bed adapters, tracks, etc.",
6
6
  "keywords": [
@@ -21,14 +21,14 @@
21
21
  "esm"
22
22
  ],
23
23
  "dependencies": {
24
- "@gmod/bbi": "^11.3.0",
25
- "@gmod/bed": "^2.3.1",
26
- "@gmod/tabix": "^3.9.1",
27
- "@gmod/trix": "^3.0.22",
28
- "@jbrowse/mobx-state-tree": "^6.7.0",
24
+ "@gmod/bbi": "^11.3.2",
25
+ "@gmod/bed": "^2.3.3",
26
+ "@gmod/tabix": "^3.11.0",
27
+ "@gmod/trix": "^3.1.0",
28
+ "@jbrowse/mobx-state-tree": "^6.9.0",
29
29
  "mobx": "^7.0.6",
30
30
  "rxjs": "^7.8.2",
31
- "@jbrowse/core": "^5.0.0-beta.13"
31
+ "@jbrowse/core": "^5.0.0-beta.14"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": ">=19.0.0",