@jbrowse/plugin-comparative-adapters 2.8.0 → 2.10.0

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 (29) hide show
  1. package/dist/PAFAdapter/PAFAdapter.js +9 -8
  2. package/dist/PAFAdapter/util.d.ts +0 -3
  3. package/dist/PAFAdapter/util.js +1 -48
  4. package/dist/PairwiseIndexedPAFAdapter/PairwiseIndexedPAFAdapter.d.ts +24 -0
  5. package/dist/PairwiseIndexedPAFAdapter/PairwiseIndexedPAFAdapter.js +107 -0
  6. package/dist/PairwiseIndexedPAFAdapter/configSchema.d.ts +61 -0
  7. package/dist/PairwiseIndexedPAFAdapter/configSchema.js +69 -0
  8. package/dist/PairwiseIndexedPAFAdapter/index.d.ts +3 -0
  9. package/dist/PairwiseIndexedPAFAdapter/index.js +41 -0
  10. package/dist/index.js +5 -6
  11. package/dist/util.d.ts +3 -0
  12. package/dist/util.js +48 -1
  13. package/esm/PAFAdapter/PAFAdapter.js +8 -7
  14. package/esm/PAFAdapter/util.d.ts +0 -3
  15. package/esm/PAFAdapter/util.js +0 -44
  16. package/esm/PairwiseIndexedPAFAdapter/PairwiseIndexedPAFAdapter.d.ts +24 -0
  17. package/esm/PairwiseIndexedPAFAdapter/PairwiseIndexedPAFAdapter.js +102 -0
  18. package/esm/PairwiseIndexedPAFAdapter/configSchema.d.ts +61 -0
  19. package/esm/PairwiseIndexedPAFAdapter/configSchema.js +67 -0
  20. package/esm/PairwiseIndexedPAFAdapter/index.d.ts +3 -0
  21. package/esm/PairwiseIndexedPAFAdapter/index.js +13 -0
  22. package/esm/index.js +5 -6
  23. package/esm/util.d.ts +3 -0
  24. package/esm/util.js +44 -0
  25. package/package.json +3 -2
  26. /package/dist/{PAFAdapter/SyntenyFeature.d.ts → SyntenyFeature/index.d.ts} +0 -0
  27. /package/dist/{PAFAdapter/SyntenyFeature.js → SyntenyFeature/index.js} +0 -0
  28. /package/esm/{PAFAdapter/SyntenyFeature.d.ts → SyntenyFeature/index.d.ts} +0 -0
  29. /package/esm/{PAFAdapter/SyntenyFeature.js → SyntenyFeature/index.js} +0 -0
@@ -11,7 +11,7 @@ const configuration_1 = require("@jbrowse/core/configuration");
11
11
  const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
12
12
  const plugin_alignments_1 = require("@jbrowse/plugin-alignments");
13
13
  // locals
14
- const SyntenyFeature_1 = __importDefault(require("./SyntenyFeature"));
14
+ const SyntenyFeature_1 = __importDefault(require("../SyntenyFeature"));
15
15
  const util_1 = require("../util");
16
16
  const util_2 = require("./util");
17
17
  const { parseCigar } = plugin_alignments_1.MismatchParser;
@@ -30,7 +30,7 @@ class PAFAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
30
30
  const pafLocation = (0, io_1.openLocation)(this.getConf('pafLocation'), pm);
31
31
  const buffer = (await pafLocation.readFile(opts));
32
32
  const buf = (0, util_1.isGzip)(buffer) ? await (0, bgzf_filehandle_1.unzip)(buffer) : buffer;
33
- return (0, util_1.parseLineByLine)(buf, util_2.parsePAFLine);
33
+ return (0, util_1.parseLineByLine)(buf, util_1.parsePAFLine);
34
34
  }
35
35
  async hasDataForRefName() {
36
36
  // determining this properly is basically a call to getFeatures
@@ -75,8 +75,11 @@ class PAFAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
75
75
  const assemblyNames = this.getAssemblyNames();
76
76
  // The index of the assembly name in the query list corresponds to the
77
77
  // adapter in the subadapters list
78
- const index = assemblyNames.indexOf(query.assemblyName);
79
78
  const { start: qstart, end: qend, refName: qref, assemblyName } = query;
79
+ const index = assemblyNames.indexOf(assemblyName);
80
+ // if the getFeatures::query is on the query assembly, flip orientation
81
+ // of data
82
+ const flip = index === 0;
80
83
  if (index === -1) {
81
84
  console.warn(`${assemblyName} not found in this adapter`);
82
85
  observer.complete();
@@ -89,9 +92,7 @@ class PAFAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
89
92
  let mateName = '';
90
93
  let mateStart = 0;
91
94
  let mateEnd = 0;
92
- const flip = index === 0;
93
- const assemblyName = assemblyNames[+!flip];
94
- if (index === 0) {
95
+ if (flip) {
95
96
  start = r.qstart;
96
97
  end = r.qend;
97
98
  refName = r.qname;
@@ -113,10 +114,10 @@ class PAFAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
113
114
  let CIGAR = extra.cg;
114
115
  if (extra.cg) {
115
116
  if (flip && strand === -1) {
116
- CIGAR = (0, util_2.flipCigar)(parseCigar(extra.cg)).join('');
117
+ CIGAR = (0, util_1.flipCigar)(parseCigar(extra.cg)).join('');
117
118
  }
118
119
  else if (flip) {
119
- CIGAR = (0, util_2.swapIndelCigar)(extra.cg);
120
+ CIGAR = (0, util_1.swapIndelCigar)(extra.cg);
120
121
  }
121
122
  }
122
123
  observer.next(new SyntenyFeature_1.default({
@@ -15,6 +15,3 @@ export interface PAFRecord {
15
15
  };
16
16
  }
17
17
  export declare function getWeightedMeans(ret: PAFRecord[]): PAFRecord[];
18
- export declare function parsePAFLine(line: string): PAFRecord;
19
- export declare function flipCigar(cigar: string[]): string[];
20
- export declare function swapIndelCigar(cigar: string): string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.swapIndelCigar = exports.flipCigar = exports.parsePAFLine = exports.getWeightedMeans = void 0;
3
+ exports.getWeightedMeans = void 0;
4
4
  const util_1 = require("../util");
5
5
  // based on "weighted mean" method from https://github.com/tpoorten/dotPlotly
6
6
  // License reproduced here
@@ -80,50 +80,3 @@ function weightedMean(tuples) {
80
80
  ], [0, 0]);
81
81
  return valueSum / weightSum;
82
82
  }
83
- function parsePAFLine(line) {
84
- const [qname, , qstart, qend, strand, tname, , tstart, tend, numMatches, blockLen, mappingQual, ...fields] = line.split('\t');
85
- const rest = Object.fromEntries(fields.map(field => {
86
- const r = field.indexOf(':');
87
- const fieldName = field.slice(0, r);
88
- const fieldValue = field.slice(r + 3);
89
- return [fieldName, fieldValue];
90
- }));
91
- return {
92
- tname,
93
- tstart: +tstart,
94
- tend: +tend,
95
- qname,
96
- qstart: +qstart,
97
- qend: +qend,
98
- strand: strand === '-' ? -1 : 1,
99
- extra: {
100
- numMatches: +numMatches,
101
- blockLen: +blockLen,
102
- mappingQual: +mappingQual,
103
- ...rest,
104
- },
105
- };
106
- }
107
- exports.parsePAFLine = parsePAFLine;
108
- function flipCigar(cigar) {
109
- const arr = [];
110
- for (let i = cigar.length - 2; i >= 0; i -= 2) {
111
- arr.push(cigar[i]);
112
- const op = cigar[i + 1];
113
- if (op === 'D') {
114
- arr.push('I');
115
- }
116
- else if (op === 'I') {
117
- arr.push('D');
118
- }
119
- else {
120
- arr.push(op);
121
- }
122
- }
123
- return arr;
124
- }
125
- exports.flipCigar = flipCigar;
126
- function swapIndelCigar(cigar) {
127
- return cigar.replaceAll('D', 'K').replaceAll('I', 'D').replaceAll('K', 'I');
128
- }
129
- exports.swapIndelCigar = swapIndelCigar;
@@ -0,0 +1,24 @@
1
+ import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
2
+ import { Region } from '@jbrowse/core/util/types';
3
+ import { Feature } from '@jbrowse/core/util';
4
+ import { AnyConfigurationModel } from '@jbrowse/core/configuration';
5
+ import { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
6
+ import PluginManager from '@jbrowse/core/PluginManager';
7
+ import { TabixIndexedFile } from '@gmod/tabix';
8
+ interface PAFOptions extends BaseOptions {
9
+ config?: AnyConfigurationModel;
10
+ }
11
+ export default class PAFAdapter extends BaseFeatureDataAdapter {
12
+ static capabilities: string[];
13
+ protected pif: TabixIndexedFile;
14
+ constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
15
+ getHeader(): Promise<string>;
16
+ getAssemblyNames(): string[];
17
+ hasDataForRefName(): Promise<boolean>;
18
+ getRefNames(opts?: BaseOptions & {
19
+ regions?: Region[];
20
+ }): Promise<string[]>;
21
+ getFeatures(query: Region, opts?: PAFOptions): import("rxjs").Observable<Feature>;
22
+ freeResources(): void;
23
+ }
24
+ export {};
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const BaseAdapter_1 = require("@jbrowse/core/data_adapters/BaseAdapter");
7
+ const rxjs_1 = require("@jbrowse/core/util/rxjs");
8
+ const io_1 = require("@jbrowse/core/util/io");
9
+ const tabix_1 = require("@gmod/tabix");
10
+ // locals
11
+ const util_1 = require("../util");
12
+ const SyntenyFeature_1 = __importDefault(require("../SyntenyFeature"));
13
+ class PAFAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
14
+ constructor(config, getSubAdapter, pluginManager) {
15
+ super(config, getSubAdapter, pluginManager);
16
+ const pifGzLoc = this.getConf('pifGzLocation');
17
+ const type = this.getConf(['index', 'indexType']);
18
+ const loc = this.getConf(['index', 'location']);
19
+ const pm = this.pluginManager;
20
+ this.pif = new tabix_1.TabixIndexedFile({
21
+ filehandle: (0, io_1.openLocation)(pifGzLoc, pm),
22
+ csiFilehandle: type === 'CSI' ? (0, io_1.openLocation)(loc, pm) : undefined,
23
+ tbiFilehandle: type !== 'CSI' ? (0, io_1.openLocation)(loc, pm) : undefined,
24
+ chunkCacheSize: 50 * 2 ** 20,
25
+ });
26
+ }
27
+ async getHeader() {
28
+ return this.pif.getHeader();
29
+ }
30
+ getAssemblyNames() {
31
+ const assemblyNames = this.getConf('assemblyNames');
32
+ if (assemblyNames.length === 0) {
33
+ return [
34
+ this.getConf('queryAssembly'),
35
+ this.getConf('targetAssembly'),
36
+ ];
37
+ }
38
+ return assemblyNames;
39
+ }
40
+ async hasDataForRefName() {
41
+ return true;
42
+ }
43
+ async getRefNames(opts = {}) {
44
+ var _a;
45
+ const r1 = (_a = opts.regions) === null || _a === void 0 ? void 0 : _a[0].assemblyName;
46
+ if (!r1) {
47
+ throw new Error('no assembly name provided');
48
+ }
49
+ const idx = this.getAssemblyNames().indexOf(r1);
50
+ const names = await this.pif.getReferenceSequenceNames(opts);
51
+ if (idx === 0) {
52
+ return names.filter(n => n.startsWith('q')).map(n => n.slice(1));
53
+ }
54
+ else if (idx === 1) {
55
+ return names.filter(n => n.startsWith('t')).map(n => n.slice(1));
56
+ }
57
+ return [];
58
+ }
59
+ getFeatures(query, opts = {}) {
60
+ return (0, rxjs_1.ObservableCreate)(async (observer) => {
61
+ const { assemblyName } = query;
62
+ const assemblyNames = this.getAssemblyNames();
63
+ const index = assemblyNames.indexOf(assemblyName);
64
+ const flip = index === 0;
65
+ const letter = flip ? 'q' : 't';
66
+ await this.pif.getLines(letter + query.refName, query.start, query.end, {
67
+ lineCallback: (line, fileOffset) => {
68
+ const r = (0, util_1.parsePAFLine)(line);
69
+ const refName = r.qname.slice(1);
70
+ const start = r.qstart;
71
+ const end = r.qend;
72
+ const mateName = r.tname;
73
+ const mateStart = r.tstart;
74
+ const mateEnd = r.tend;
75
+ const { extra, strand } = r;
76
+ const { numMatches = 0, blockLen = 1, cg, ...rest } = extra;
77
+ observer.next(new SyntenyFeature_1.default({
78
+ uniqueId: fileOffset + assemblyName,
79
+ assemblyName,
80
+ start,
81
+ end,
82
+ type: 'match',
83
+ refName,
84
+ strand,
85
+ ...rest,
86
+ CIGAR: extra.cg,
87
+ syntenyId: fileOffset,
88
+ identity: numMatches / blockLen,
89
+ numMatches,
90
+ blockLen,
91
+ mate: {
92
+ start: mateStart,
93
+ end: mateEnd,
94
+ refName: mateName,
95
+ assemblyName: assemblyNames[+flip],
96
+ },
97
+ }));
98
+ },
99
+ signal: opts.signal,
100
+ });
101
+ observer.complete();
102
+ });
103
+ }
104
+ freeResources( /* { query } */) { }
105
+ }
106
+ PAFAdapter.capabilities = ['getFeatures', 'getRefNames'];
107
+ exports.default = PAFAdapter;
@@ -0,0 +1,61 @@
1
+ declare const PairwiseIndexedPAFAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
+ /**
3
+ * #slot
4
+ */
5
+ assemblyNames: {
6
+ type: string;
7
+ defaultValue: never[];
8
+ description: string;
9
+ };
10
+ /**
11
+ * #slot
12
+ */
13
+ targetAssembly: {
14
+ type: string;
15
+ defaultValue: string;
16
+ description: string;
17
+ };
18
+ /**
19
+ * #slot
20
+ */
21
+ queryAssembly: {
22
+ type: string;
23
+ defaultValue: string;
24
+ description: string;
25
+ };
26
+ /**
27
+ * #slot
28
+ */
29
+ pifGzLocation: {
30
+ type: string;
31
+ description: string;
32
+ defaultValue: {
33
+ uri: string;
34
+ locationType: string;
35
+ };
36
+ };
37
+ /**
38
+ * #slot
39
+ */
40
+ index: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
41
+ /**
42
+ * #slot index.indexType
43
+ */
44
+ indexType: {
45
+ model: import("mobx-state-tree").ISimpleType<string>;
46
+ type: string;
47
+ defaultValue: string;
48
+ };
49
+ /**
50
+ * #slot index.location
51
+ */
52
+ location: {
53
+ type: string;
54
+ defaultValue: {
55
+ uri: string;
56
+ locationType: string;
57
+ };
58
+ };
59
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
60
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
61
+ export default PairwiseIndexedPAFAdapter;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const configuration_1 = require("@jbrowse/core/configuration");
4
+ const mobx_state_tree_1 = require("mobx-state-tree");
5
+ /**
6
+ * #config PairwiseIndexedPAFAdapter
7
+ */
8
+ function x() { } // eslint-disable-line @typescript-eslint/no-unused-vars
9
+ const PairwiseIndexedPAFAdapter = (0, configuration_1.ConfigurationSchema)('PairwiseIndexedPAFAdapter', {
10
+ /**
11
+ * #slot
12
+ */
13
+ assemblyNames: {
14
+ type: 'stringArray',
15
+ defaultValue: [],
16
+ description: 'Array of assembly names to use for this file. The target assembly name is the first value in the array, query assembly name is the second',
17
+ },
18
+ /**
19
+ * #slot
20
+ */
21
+ targetAssembly: {
22
+ type: 'string',
23
+ defaultValue: '',
24
+ description: 'Alternative to assemblyNames: the target assembly name',
25
+ },
26
+ /**
27
+ * #slot
28
+ */
29
+ queryAssembly: {
30
+ type: 'string',
31
+ defaultValue: '',
32
+ description: 'Alternative to assemblyNames: the query assembly name',
33
+ },
34
+ /**
35
+ * #slot
36
+ */
37
+ pifGzLocation: {
38
+ type: 'fileLocation',
39
+ description: 'location of pairwise tabix indexed PAF (pif)',
40
+ defaultValue: {
41
+ uri: '/path/to/data/file.pif.gz',
42
+ locationType: 'UriLocation',
43
+ },
44
+ },
45
+ /**
46
+ * #slot
47
+ */
48
+ index: (0, configuration_1.ConfigurationSchema)('TabixIndex', {
49
+ /**
50
+ * #slot index.indexType
51
+ */
52
+ indexType: {
53
+ model: mobx_state_tree_1.types.enumeration('IndexType', ['TBI', 'CSI']),
54
+ type: 'stringEnum',
55
+ defaultValue: 'TBI',
56
+ },
57
+ /**
58
+ * #slot index.location
59
+ */
60
+ location: {
61
+ type: 'fileLocation',
62
+ defaultValue: {
63
+ uri: '/path/to/my.paf.gz.tbi',
64
+ locationType: 'UriLocation',
65
+ },
66
+ },
67
+ }),
68
+ }, { explicitlyTyped: true });
69
+ exports.default = PairwiseIndexedPAFAdapter;
@@ -0,0 +1,3 @@
1
+ import PluginManager from '@jbrowse/core/PluginManager';
2
+ declare const _default: (pluginManager: PluginManager) => void;
3
+ export default _default;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const AdapterType_1 = __importDefault(require("@jbrowse/core/pluggableElementTypes/AdapterType"));
30
+ const configSchema_1 = __importDefault(require("./configSchema"));
31
+ exports.default = (pluginManager) => {
32
+ pluginManager.addAdapterType(() => new AdapterType_1.default({
33
+ name: 'PairwiseIndexedPAFAdapter',
34
+ displayName: 'Pairwise indexed PAF adapter',
35
+ configSchema: configSchema_1.default,
36
+ adapterMetadata: {
37
+ hiddenFromGUI: true,
38
+ },
39
+ getAdapterClass: () => Promise.resolve().then(() => __importStar(require('./PairwiseIndexedPAFAdapter'))).then(r => r.default),
40
+ }));
41
+ };
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const Plugin_1 = __importDefault(require("@jbrowse/core/Plugin"));
7
7
  const PAFAdapter_1 = __importDefault(require("./PAFAdapter"));
8
+ const PairwiseIndexedPAFAdapter_1 = __importDefault(require("./PairwiseIndexedPAFAdapter"));
8
9
  const MCScanAnchorsAdapter_1 = __importDefault(require("./MCScanAnchorsAdapter"));
9
10
  const MCScanSimpleAnchorsAdapter_1 = __importDefault(require("./MCScanSimpleAnchorsAdapter"));
10
11
  const MashMapAdapter_1 = __importDefault(require("./MashMapAdapter"));
@@ -18,6 +19,7 @@ class ComparativeAdaptersPlugin extends Plugin_1.default {
18
19
  }
19
20
  install(pluginManager) {
20
21
  (0, PAFAdapter_1.default)(pluginManager);
22
+ (0, PairwiseIndexedPAFAdapter_1.default)(pluginManager);
21
23
  (0, DeltaAdapter_1.default)(pluginManager);
22
24
  (0, ChainAdapter_1.default)(pluginManager);
23
25
  (0, MCScanAnchorsAdapter_1.default)(pluginManager);
@@ -38,12 +40,9 @@ class ComparativeAdaptersPlugin extends Plugin_1.default {
38
40
  };
39
41
  });
40
42
  pluginManager.addToExtensionPoint('Core-guessTrackTypeForLocation', (trackTypeGuesser) => {
41
- return (adapterName) => {
42
- if (adapterName === 'PAFAdapter') {
43
- return 'SyntenyTrack';
44
- }
45
- return trackTypeGuesser(adapterName);
46
- };
43
+ return (adapterName) => adapterName === 'PAFAdapter'
44
+ ? 'SyntenyTrack'
45
+ : trackTypeGuesser(adapterName);
47
46
  });
48
47
  }
49
48
  }
package/dist/util.d.ts CHANGED
@@ -14,3 +14,6 @@ export declare function parseBed(text: string): Map<string, {
14
14
  export declare function readFile(file: GenericFilehandle, opts?: BaseOptions): Promise<string>;
15
15
  export declare function zip(a: number[], b: number[]): [number, number][];
16
16
  export declare function parseLineByLine(buffer: Buffer, cb: (line: string) => PAFRecord): PAFRecord[];
17
+ export declare function parsePAFLine(line: string): PAFRecord;
18
+ export declare function flipCigar(cigar: string[]): string[];
19
+ export declare function swapIndelCigar(cigar: string): string;
package/dist/util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseLineByLine = exports.zip = exports.readFile = exports.parseBed = exports.isGzip = void 0;
3
+ exports.swapIndelCigar = exports.flipCigar = exports.parsePAFLine = exports.parseLineByLine = exports.zip = exports.readFile = exports.parseBed = exports.isGzip = void 0;
4
4
  const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
5
5
  function isGzip(buf) {
6
6
  return buf[0] === 31 && buf[1] === 139 && buf[2] === 8;
@@ -54,3 +54,50 @@ function parseLineByLine(buffer, cb) {
54
54
  return entries;
55
55
  }
56
56
  exports.parseLineByLine = parseLineByLine;
57
+ function parsePAFLine(line) {
58
+ const [qname, , qstart, qend, strand, tname, , tstart, tend, numMatches, blockLen, mappingQual, ...fields] = line.split('\t');
59
+ const rest = Object.fromEntries(fields.map(field => {
60
+ const r = field.indexOf(':');
61
+ const fieldName = field.slice(0, r);
62
+ const fieldValue = field.slice(r + 3);
63
+ return [fieldName, fieldValue];
64
+ }));
65
+ return {
66
+ tname,
67
+ tstart: +tstart,
68
+ tend: +tend,
69
+ qname,
70
+ qstart: +qstart,
71
+ qend: +qend,
72
+ strand: strand === '-' ? -1 : 1,
73
+ extra: {
74
+ numMatches: +numMatches,
75
+ blockLen: +blockLen,
76
+ mappingQual: +mappingQual,
77
+ ...rest,
78
+ },
79
+ };
80
+ }
81
+ exports.parsePAFLine = parsePAFLine;
82
+ function flipCigar(cigar) {
83
+ const arr = [];
84
+ for (let i = cigar.length - 2; i >= 0; i -= 2) {
85
+ arr.push(cigar[i]);
86
+ const op = cigar[i + 1];
87
+ if (op === 'D') {
88
+ arr.push('I');
89
+ }
90
+ else if (op === 'I') {
91
+ arr.push('D');
92
+ }
93
+ else {
94
+ arr.push(op);
95
+ }
96
+ }
97
+ return arr;
98
+ }
99
+ exports.flipCigar = flipCigar;
100
+ function swapIndelCigar(cigar) {
101
+ return cigar.replaceAll('D', 'K').replaceAll('I', 'D').replaceAll('K', 'I');
102
+ }
103
+ exports.swapIndelCigar = swapIndelCigar;
@@ -6,9 +6,9 @@ import { readConfObject, } from '@jbrowse/core/configuration';
6
6
  import { unzip } from '@gmod/bgzf-filehandle';
7
7
  import { MismatchParser } from '@jbrowse/plugin-alignments';
8
8
  // locals
9
- import SyntenyFeature from './SyntenyFeature';
10
- import { isGzip, parseLineByLine } from '../util';
11
- import { getWeightedMeans, flipCigar, swapIndelCigar, parsePAFLine, } from './util';
9
+ import SyntenyFeature from '../SyntenyFeature';
10
+ import { flipCigar, swapIndelCigar, parsePAFLine, isGzip, parseLineByLine, } from '../util';
11
+ import { getWeightedMeans } from './util';
12
12
  const { parseCigar } = MismatchParser;
13
13
  class PAFAdapter extends BaseFeatureDataAdapter {
14
14
  async setup(opts) {
@@ -70,8 +70,11 @@ class PAFAdapter extends BaseFeatureDataAdapter {
70
70
  const assemblyNames = this.getAssemblyNames();
71
71
  // The index of the assembly name in the query list corresponds to the
72
72
  // adapter in the subadapters list
73
- const index = assemblyNames.indexOf(query.assemblyName);
74
73
  const { start: qstart, end: qend, refName: qref, assemblyName } = query;
74
+ const index = assemblyNames.indexOf(assemblyName);
75
+ // if the getFeatures::query is on the query assembly, flip orientation
76
+ // of data
77
+ const flip = index === 0;
75
78
  if (index === -1) {
76
79
  console.warn(`${assemblyName} not found in this adapter`);
77
80
  observer.complete();
@@ -84,9 +87,7 @@ class PAFAdapter extends BaseFeatureDataAdapter {
84
87
  let mateName = '';
85
88
  let mateStart = 0;
86
89
  let mateEnd = 0;
87
- const flip = index === 0;
88
- const assemblyName = assemblyNames[+!flip];
89
- if (index === 0) {
90
+ if (flip) {
90
91
  start = r.qstart;
91
92
  end = r.qend;
92
93
  refName = r.qname;
@@ -15,6 +15,3 @@ export interface PAFRecord {
15
15
  };
16
16
  }
17
17
  export declare function getWeightedMeans(ret: PAFRecord[]): PAFRecord[];
18
- export declare function parsePAFLine(line: string): PAFRecord;
19
- export declare function flipCigar(cigar: string[]): string[];
20
- export declare function swapIndelCigar(cigar: string): string;
@@ -76,47 +76,3 @@ function weightedMean(tuples) {
76
76
  ], [0, 0]);
77
77
  return valueSum / weightSum;
78
78
  }
79
- export function parsePAFLine(line) {
80
- const [qname, , qstart, qend, strand, tname, , tstart, tend, numMatches, blockLen, mappingQual, ...fields] = line.split('\t');
81
- const rest = Object.fromEntries(fields.map(field => {
82
- const r = field.indexOf(':');
83
- const fieldName = field.slice(0, r);
84
- const fieldValue = field.slice(r + 3);
85
- return [fieldName, fieldValue];
86
- }));
87
- return {
88
- tname,
89
- tstart: +tstart,
90
- tend: +tend,
91
- qname,
92
- qstart: +qstart,
93
- qend: +qend,
94
- strand: strand === '-' ? -1 : 1,
95
- extra: {
96
- numMatches: +numMatches,
97
- blockLen: +blockLen,
98
- mappingQual: +mappingQual,
99
- ...rest,
100
- },
101
- };
102
- }
103
- export function flipCigar(cigar) {
104
- const arr = [];
105
- for (let i = cigar.length - 2; i >= 0; i -= 2) {
106
- arr.push(cigar[i]);
107
- const op = cigar[i + 1];
108
- if (op === 'D') {
109
- arr.push('I');
110
- }
111
- else if (op === 'I') {
112
- arr.push('D');
113
- }
114
- else {
115
- arr.push(op);
116
- }
117
- }
118
- return arr;
119
- }
120
- export function swapIndelCigar(cigar) {
121
- return cigar.replaceAll('D', 'K').replaceAll('I', 'D').replaceAll('K', 'I');
122
- }
@@ -0,0 +1,24 @@
1
+ import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
2
+ import { Region } from '@jbrowse/core/util/types';
3
+ import { Feature } from '@jbrowse/core/util';
4
+ import { AnyConfigurationModel } from '@jbrowse/core/configuration';
5
+ import { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
6
+ import PluginManager from '@jbrowse/core/PluginManager';
7
+ import { TabixIndexedFile } from '@gmod/tabix';
8
+ interface PAFOptions extends BaseOptions {
9
+ config?: AnyConfigurationModel;
10
+ }
11
+ export default class PAFAdapter extends BaseFeatureDataAdapter {
12
+ static capabilities: string[];
13
+ protected pif: TabixIndexedFile;
14
+ constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
15
+ getHeader(): Promise<string>;
16
+ getAssemblyNames(): string[];
17
+ hasDataForRefName(): Promise<boolean>;
18
+ getRefNames(opts?: BaseOptions & {
19
+ regions?: Region[];
20
+ }): Promise<string[]>;
21
+ getFeatures(query: Region, opts?: PAFOptions): import("rxjs").Observable<Feature>;
22
+ freeResources(): void;
23
+ }
24
+ export {};
@@ -0,0 +1,102 @@
1
+ import { BaseFeatureDataAdapter, } from '@jbrowse/core/data_adapters/BaseAdapter';
2
+ import { ObservableCreate } from '@jbrowse/core/util/rxjs';
3
+ import { openLocation } from '@jbrowse/core/util/io';
4
+ import { TabixIndexedFile } from '@gmod/tabix';
5
+ // locals
6
+ import { parsePAFLine } from '../util';
7
+ import SyntenyFeature from '../SyntenyFeature';
8
+ class PAFAdapter extends BaseFeatureDataAdapter {
9
+ constructor(config, getSubAdapter, pluginManager) {
10
+ super(config, getSubAdapter, pluginManager);
11
+ const pifGzLoc = this.getConf('pifGzLocation');
12
+ const type = this.getConf(['index', 'indexType']);
13
+ const loc = this.getConf(['index', 'location']);
14
+ const pm = this.pluginManager;
15
+ this.pif = new TabixIndexedFile({
16
+ filehandle: openLocation(pifGzLoc, pm),
17
+ csiFilehandle: type === 'CSI' ? openLocation(loc, pm) : undefined,
18
+ tbiFilehandle: type !== 'CSI' ? openLocation(loc, pm) : undefined,
19
+ chunkCacheSize: 50 * 2 ** 20,
20
+ });
21
+ }
22
+ async getHeader() {
23
+ return this.pif.getHeader();
24
+ }
25
+ getAssemblyNames() {
26
+ const assemblyNames = this.getConf('assemblyNames');
27
+ if (assemblyNames.length === 0) {
28
+ return [
29
+ this.getConf('queryAssembly'),
30
+ this.getConf('targetAssembly'),
31
+ ];
32
+ }
33
+ return assemblyNames;
34
+ }
35
+ async hasDataForRefName() {
36
+ return true;
37
+ }
38
+ async getRefNames(opts = {}) {
39
+ var _a;
40
+ const r1 = (_a = opts.regions) === null || _a === void 0 ? void 0 : _a[0].assemblyName;
41
+ if (!r1) {
42
+ throw new Error('no assembly name provided');
43
+ }
44
+ const idx = this.getAssemblyNames().indexOf(r1);
45
+ const names = await this.pif.getReferenceSequenceNames(opts);
46
+ if (idx === 0) {
47
+ return names.filter(n => n.startsWith('q')).map(n => n.slice(1));
48
+ }
49
+ else if (idx === 1) {
50
+ return names.filter(n => n.startsWith('t')).map(n => n.slice(1));
51
+ }
52
+ return [];
53
+ }
54
+ getFeatures(query, opts = {}) {
55
+ return ObservableCreate(async (observer) => {
56
+ const { assemblyName } = query;
57
+ const assemblyNames = this.getAssemblyNames();
58
+ const index = assemblyNames.indexOf(assemblyName);
59
+ const flip = index === 0;
60
+ const letter = flip ? 'q' : 't';
61
+ await this.pif.getLines(letter + query.refName, query.start, query.end, {
62
+ lineCallback: (line, fileOffset) => {
63
+ const r = parsePAFLine(line);
64
+ const refName = r.qname.slice(1);
65
+ const start = r.qstart;
66
+ const end = r.qend;
67
+ const mateName = r.tname;
68
+ const mateStart = r.tstart;
69
+ const mateEnd = r.tend;
70
+ const { extra, strand } = r;
71
+ const { numMatches = 0, blockLen = 1, cg, ...rest } = extra;
72
+ observer.next(new SyntenyFeature({
73
+ uniqueId: fileOffset + assemblyName,
74
+ assemblyName,
75
+ start,
76
+ end,
77
+ type: 'match',
78
+ refName,
79
+ strand,
80
+ ...rest,
81
+ CIGAR: extra.cg,
82
+ syntenyId: fileOffset,
83
+ identity: numMatches / blockLen,
84
+ numMatches,
85
+ blockLen,
86
+ mate: {
87
+ start: mateStart,
88
+ end: mateEnd,
89
+ refName: mateName,
90
+ assemblyName: assemblyNames[+flip],
91
+ },
92
+ }));
93
+ },
94
+ signal: opts.signal,
95
+ });
96
+ observer.complete();
97
+ });
98
+ }
99
+ freeResources( /* { query } */) { }
100
+ }
101
+ PAFAdapter.capabilities = ['getFeatures', 'getRefNames'];
102
+ export default PAFAdapter;
@@ -0,0 +1,61 @@
1
+ declare const PairwiseIndexedPAFAdapter: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
+ /**
3
+ * #slot
4
+ */
5
+ assemblyNames: {
6
+ type: string;
7
+ defaultValue: never[];
8
+ description: string;
9
+ };
10
+ /**
11
+ * #slot
12
+ */
13
+ targetAssembly: {
14
+ type: string;
15
+ defaultValue: string;
16
+ description: string;
17
+ };
18
+ /**
19
+ * #slot
20
+ */
21
+ queryAssembly: {
22
+ type: string;
23
+ defaultValue: string;
24
+ description: string;
25
+ };
26
+ /**
27
+ * #slot
28
+ */
29
+ pifGzLocation: {
30
+ type: string;
31
+ description: string;
32
+ defaultValue: {
33
+ uri: string;
34
+ locationType: string;
35
+ };
36
+ };
37
+ /**
38
+ * #slot
39
+ */
40
+ index: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
41
+ /**
42
+ * #slot index.indexType
43
+ */
44
+ indexType: {
45
+ model: import("mobx-state-tree").ISimpleType<string>;
46
+ type: string;
47
+ defaultValue: string;
48
+ };
49
+ /**
50
+ * #slot index.location
51
+ */
52
+ location: {
53
+ type: string;
54
+ defaultValue: {
55
+ uri: string;
56
+ locationType: string;
57
+ };
58
+ };
59
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
60
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
61
+ export default PairwiseIndexedPAFAdapter;
@@ -0,0 +1,67 @@
1
+ import { ConfigurationSchema } from '@jbrowse/core/configuration';
2
+ import { types } from 'mobx-state-tree';
3
+ /**
4
+ * #config PairwiseIndexedPAFAdapter
5
+ */
6
+ function x() { } // eslint-disable-line @typescript-eslint/no-unused-vars
7
+ const PairwiseIndexedPAFAdapter = ConfigurationSchema('PairwiseIndexedPAFAdapter', {
8
+ /**
9
+ * #slot
10
+ */
11
+ assemblyNames: {
12
+ type: 'stringArray',
13
+ defaultValue: [],
14
+ description: 'Array of assembly names to use for this file. The target assembly name is the first value in the array, query assembly name is the second',
15
+ },
16
+ /**
17
+ * #slot
18
+ */
19
+ targetAssembly: {
20
+ type: 'string',
21
+ defaultValue: '',
22
+ description: 'Alternative to assemblyNames: the target assembly name',
23
+ },
24
+ /**
25
+ * #slot
26
+ */
27
+ queryAssembly: {
28
+ type: 'string',
29
+ defaultValue: '',
30
+ description: 'Alternative to assemblyNames: the query assembly name',
31
+ },
32
+ /**
33
+ * #slot
34
+ */
35
+ pifGzLocation: {
36
+ type: 'fileLocation',
37
+ description: 'location of pairwise tabix indexed PAF (pif)',
38
+ defaultValue: {
39
+ uri: '/path/to/data/file.pif.gz',
40
+ locationType: 'UriLocation',
41
+ },
42
+ },
43
+ /**
44
+ * #slot
45
+ */
46
+ index: ConfigurationSchema('TabixIndex', {
47
+ /**
48
+ * #slot index.indexType
49
+ */
50
+ indexType: {
51
+ model: types.enumeration('IndexType', ['TBI', 'CSI']),
52
+ type: 'stringEnum',
53
+ defaultValue: 'TBI',
54
+ },
55
+ /**
56
+ * #slot index.location
57
+ */
58
+ location: {
59
+ type: 'fileLocation',
60
+ defaultValue: {
61
+ uri: '/path/to/my.paf.gz.tbi',
62
+ locationType: 'UriLocation',
63
+ },
64
+ },
65
+ }),
66
+ }, { explicitlyTyped: true });
67
+ export default PairwiseIndexedPAFAdapter;
@@ -0,0 +1,3 @@
1
+ import PluginManager from '@jbrowse/core/PluginManager';
2
+ declare const _default: (pluginManager: PluginManager) => void;
3
+ export default _default;
@@ -0,0 +1,13 @@
1
+ import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType';
2
+ import configSchema from './configSchema';
3
+ export default (pluginManager) => {
4
+ pluginManager.addAdapterType(() => new AdapterType({
5
+ name: 'PairwiseIndexedPAFAdapter',
6
+ displayName: 'Pairwise indexed PAF adapter',
7
+ configSchema,
8
+ adapterMetadata: {
9
+ hiddenFromGUI: true,
10
+ },
11
+ getAdapterClass: () => import('./PairwiseIndexedPAFAdapter').then(r => r.default),
12
+ }));
13
+ };
package/esm/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import Plugin from '@jbrowse/core/Plugin';
2
2
  import PAFAdapterF from './PAFAdapter';
3
+ import PairwiseIndexedPAFAdapterF from './PairwiseIndexedPAFAdapter';
3
4
  import MCScanAnchorsAdapterF from './MCScanAnchorsAdapter';
4
5
  import MCScanSimpleAnchorsAdapterF from './MCScanSimpleAnchorsAdapter';
5
6
  import MashMapAdapterF from './MashMapAdapter';
@@ -13,6 +14,7 @@ export default class ComparativeAdaptersPlugin extends Plugin {
13
14
  }
14
15
  install(pluginManager) {
15
16
  PAFAdapterF(pluginManager);
17
+ PairwiseIndexedPAFAdapterF(pluginManager);
16
18
  DeltaAdapterF(pluginManager);
17
19
  ChainAdapterF(pluginManager);
18
20
  MCScanAnchorsAdapterF(pluginManager);
@@ -33,12 +35,9 @@ export default class ComparativeAdaptersPlugin extends Plugin {
33
35
  };
34
36
  });
35
37
  pluginManager.addToExtensionPoint('Core-guessTrackTypeForLocation', (trackTypeGuesser) => {
36
- return (adapterName) => {
37
- if (adapterName === 'PAFAdapter') {
38
- return 'SyntenyTrack';
39
- }
40
- return trackTypeGuesser(adapterName);
41
- };
38
+ return (adapterName) => adapterName === 'PAFAdapter'
39
+ ? 'SyntenyTrack'
40
+ : trackTypeGuesser(adapterName);
42
41
  });
43
42
  }
44
43
  }
package/esm/util.d.ts CHANGED
@@ -14,3 +14,6 @@ export declare function parseBed(text: string): Map<string, {
14
14
  export declare function readFile(file: GenericFilehandle, opts?: BaseOptions): Promise<string>;
15
15
  export declare function zip(a: number[], b: number[]): [number, number][];
16
16
  export declare function parseLineByLine(buffer: Buffer, cb: (line: string) => PAFRecord): PAFRecord[];
17
+ export declare function parsePAFLine(line: string): PAFRecord;
18
+ export declare function flipCigar(cigar: string[]): string[];
19
+ export declare function swapIndelCigar(cigar: string): string;
package/esm/util.js CHANGED
@@ -46,3 +46,47 @@ export function parseLineByLine(buffer, cb) {
46
46
  }
47
47
  return entries;
48
48
  }
49
+ export function parsePAFLine(line) {
50
+ const [qname, , qstart, qend, strand, tname, , tstart, tend, numMatches, blockLen, mappingQual, ...fields] = line.split('\t');
51
+ const rest = Object.fromEntries(fields.map(field => {
52
+ const r = field.indexOf(':');
53
+ const fieldName = field.slice(0, r);
54
+ const fieldValue = field.slice(r + 3);
55
+ return [fieldName, fieldValue];
56
+ }));
57
+ return {
58
+ tname,
59
+ tstart: +tstart,
60
+ tend: +tend,
61
+ qname,
62
+ qstart: +qstart,
63
+ qend: +qend,
64
+ strand: strand === '-' ? -1 : 1,
65
+ extra: {
66
+ numMatches: +numMatches,
67
+ blockLen: +blockLen,
68
+ mappingQual: +mappingQual,
69
+ ...rest,
70
+ },
71
+ };
72
+ }
73
+ export function flipCigar(cigar) {
74
+ const arr = [];
75
+ for (let i = cigar.length - 2; i >= 0; i -= 2) {
76
+ arr.push(cigar[i]);
77
+ const op = cigar[i + 1];
78
+ if (op === 'D') {
79
+ arr.push('I');
80
+ }
81
+ else if (op === 'I') {
82
+ arr.push('D');
83
+ }
84
+ else {
85
+ arr.push(op);
86
+ }
87
+ }
88
+ return arr;
89
+ }
90
+ export function swapIndelCigar(cigar) {
91
+ return cigar.replaceAll('D', 'K').replaceAll('I', 'D').replaceAll('K', 'I');
92
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-comparative-adapters",
3
- "version": "2.8.0",
3
+ "version": "2.10.0",
4
4
  "description": "JBrowse 2 comparative adapters",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -37,6 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@gmod/bgzf-filehandle": "^1.4.3",
40
+ "@gmod/tabix": "^1.5.6",
40
41
  "generic-filehandle": "^3.0.0"
41
42
  },
42
43
  "peerDependencies": {
@@ -58,5 +59,5 @@
58
59
  "publishConfig": {
59
60
  "access": "public"
60
61
  },
61
- "gitHead": "ee8c2bdc8bd4f1a70b1eefda984f04a2830d9ca0"
62
+ "gitHead": "223d8bfb68fd1bacaf22852639ad5920f1b7f43b"
62
63
  }