jbrowse-plugin-mafviewer 1.3.2 → 1.4.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.
- package/README.md +0 -47
- package/dist/LinearMafRenderer/LinearMafRenderer.d.ts +9 -3
- package/dist/LinearMafRenderer/components/LinearMafRendering.d.ts +13 -0
- package/dist/LinearMafRenderer/components/LinearMafRendering.js +46 -0
- package/dist/LinearMafRenderer/components/LinearMafRendering.js.map +1 -0
- package/dist/LinearMafRenderer/index.js +1 -1
- package/dist/LinearMafRenderer/index.js.map +1 -1
- package/dist/LinearMafRenderer/makeImageData.d.ts +3 -1
- package/dist/LinearMafRenderer/makeImageData.js +11 -4
- package/dist/LinearMafRenderer/makeImageData.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/features.d.ts +0 -17
- package/dist/LinearMafRenderer/rendering/features.js +4 -21
- package/dist/LinearMafRenderer/rendering/features.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/gaps.d.ts +1 -11
- package/dist/LinearMafRenderer/rendering/gaps.js +1 -17
- package/dist/LinearMafRenderer/rendering/gaps.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/insertions.d.ts +1 -13
- package/dist/LinearMafRenderer/rendering/insertions.js +9 -15
- package/dist/LinearMafRenderer/rendering/insertions.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/matches.d.ts +1 -12
- package/dist/LinearMafRenderer/rendering/matches.js +8 -15
- package/dist/LinearMafRenderer/rendering/matches.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/mismatches.d.ts +1 -1
- package/dist/LinearMafRenderer/rendering/mismatches.js +14 -4
- package/dist/LinearMafRenderer/rendering/mismatches.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/spatialIndex.d.ts +7 -58
- package/dist/LinearMafRenderer/rendering/spatialIndex.js +5 -85
- package/dist/LinearMafRenderer/rendering/spatialIndex.js.map +1 -1
- package/dist/LinearMafRenderer/rendering/types.d.ts +4 -16
- package/dist/LinearMafRenderer/rendering/types.js.map +1 -1
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js +37 -35
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js +5 -28
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js.map +4 -4
- package/dist/out.js +12955 -15165
- package/dist/out.js.map +4 -4
- package/package.json +3 -4
- package/src/LinearMafRenderer/components/{ReactComponent.tsx → LinearMafRendering.tsx} +16 -21
- package/src/LinearMafRenderer/index.ts +1 -1
- package/src/LinearMafRenderer/makeImageData.ts +20 -5
- package/src/LinearMafRenderer/rendering/features.ts +4 -31
- package/src/LinearMafRenderer/rendering/gaps.ts +0 -38
- package/src/LinearMafRenderer/rendering/insertions.ts +12 -28
- package/src/LinearMafRenderer/rendering/matches.ts +13 -30
- package/src/LinearMafRenderer/rendering/mismatches.ts +20 -32
- package/src/LinearMafRenderer/rendering/spatialIndex.ts +9 -105
- package/src/LinearMafRenderer/rendering/types.ts +4 -20
- package/src/MafAddTrackWorkflow/AddTrackWorkflow.tsx +5 -6
- package/src/index.ts +0 -2
- package/src/BgzipTaffyAdapter/BgzipTaffyAdapter.ts +0 -307
- package/src/BgzipTaffyAdapter/configSchema.ts +0 -59
- package/src/BgzipTaffyAdapter/index.ts +0 -16
- package/src/BgzipTaffyAdapter/rowInstructions.ts +0 -91
- package/src/BgzipTaffyAdapter/types.ts +0 -16
- package/src/BgzipTaffyAdapter/util.ts +0 -25
- package/src/BgzipTaffyAdapter/virtualOffset.ts +0 -29
|
@@ -37,10 +37,7 @@ const useStyles = makeStyles()(theme => ({
|
|
|
37
37
|
},
|
|
38
38
|
}))
|
|
39
39
|
|
|
40
|
-
type AdapterTypeOptions =
|
|
41
|
-
| 'BigMafAdapter'
|
|
42
|
-
| 'MafTabixAdapter'
|
|
43
|
-
| 'BgzipTaffyAdapter'
|
|
40
|
+
type AdapterTypeOptions = 'BigMafAdapter' | 'MafTabixAdapter'
|
|
44
41
|
type IndexTypeOptions = 'TBI' | 'CSI'
|
|
45
42
|
|
|
46
43
|
export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
|
|
@@ -89,7 +86,8 @@ export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
|
|
|
89
86
|
setLoc(arg)
|
|
90
87
|
}}
|
|
91
88
|
/>
|
|
92
|
-
) :
|
|
89
|
+
) : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
90
|
+
fileTypeChoice === 'MafTabixAdapter' ? (
|
|
93
91
|
<>
|
|
94
92
|
<FormControl>
|
|
95
93
|
<FormLabel>Index type</FormLabel>
|
|
@@ -212,7 +210,8 @@ export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
|
|
|
212
210
|
samples: sampleNames,
|
|
213
211
|
nhLocation: nhLoc,
|
|
214
212
|
}
|
|
215
|
-
:
|
|
213
|
+
: // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
214
|
+
fileTypeChoice === 'MafTabixAdapter'
|
|
216
215
|
? {
|
|
217
216
|
type: fileTypeChoice,
|
|
218
217
|
bedGzLocation: loc,
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,6 @@ import Plugin from '@jbrowse/core/Plugin'
|
|
|
2
2
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
3
|
|
|
4
4
|
import { version } from '../package.json'
|
|
5
|
-
import BgzipTaffyAdapterF from './BgzipTaffyAdapter'
|
|
6
5
|
import BigMafAdapterF from './BigMafAdapter'
|
|
7
6
|
import LinearMafDisplayF from './LinearMafDisplay'
|
|
8
7
|
import LinearMafRendererF from './LinearMafRenderer'
|
|
@@ -22,7 +21,6 @@ export default class MafViewerPlugin extends Plugin {
|
|
|
22
21
|
LinearMafDisplayF(pluginManager)
|
|
23
22
|
LinearMafRendererF(pluginManager)
|
|
24
23
|
MafTabixAdapterF(pluginManager)
|
|
25
|
-
BgzipTaffyAdapterF(pluginManager)
|
|
26
24
|
MafAddTrackWorkflowF(pluginManager)
|
|
27
25
|
MafGetSequencesF(pluginManager)
|
|
28
26
|
MafGetSamplesF(pluginManager)
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import { unzip } from '@gmod/bgzf-filehandle'
|
|
2
|
-
import {
|
|
3
|
-
BaseFeatureDataAdapter,
|
|
4
|
-
BaseOptions,
|
|
5
|
-
} from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
6
|
-
import {
|
|
7
|
-
Feature,
|
|
8
|
-
Region,
|
|
9
|
-
SimpleFeature,
|
|
10
|
-
updateStatus,
|
|
11
|
-
} from '@jbrowse/core/util'
|
|
12
|
-
import QuickLRU from '@jbrowse/core/util/QuickLRU'
|
|
13
|
-
import { openLocation } from '@jbrowse/core/util/io'
|
|
14
|
-
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
|
|
15
|
-
import AbortablePromiseCache from 'abortable-promise-cache'
|
|
16
|
-
import Long from 'long'
|
|
17
|
-
|
|
18
|
-
import VirtualOffset from './virtualOffset'
|
|
19
|
-
import parseNewick from '../parseNewick'
|
|
20
|
-
import { normalize } from '../util'
|
|
21
|
-
import { parseRowInstructions } from './rowInstructions'
|
|
22
|
-
import { parseLineByLine } from './util'
|
|
23
|
-
|
|
24
|
-
import type { IndexData, OrganismRecord } from './types'
|
|
25
|
-
|
|
26
|
-
interface Entry {
|
|
27
|
-
type: string
|
|
28
|
-
row: number
|
|
29
|
-
asm: string
|
|
30
|
-
ref: string
|
|
31
|
-
start: number
|
|
32
|
-
strand: number
|
|
33
|
-
length: number
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const toP = (s = 0) => +(+s).toFixed(1)
|
|
37
|
-
|
|
38
|
-
export default class BgzipTaffyAdapter extends BaseFeatureDataAdapter {
|
|
39
|
-
public setupP?: Promise<IndexData>
|
|
40
|
-
|
|
41
|
-
private cache = new AbortablePromiseCache({
|
|
42
|
-
cache: new QuickLRU({ maxSize: 50 }),
|
|
43
|
-
// @ts-expect-error
|
|
44
|
-
fill: async ({ nextEntry, firstEntry }, signal, statusCallback) => {
|
|
45
|
-
const file = openLocation(this.getConf('tafGzLocation'))
|
|
46
|
-
const response = await file.read(
|
|
47
|
-
nextEntry.virtualOffset.blockPosition -
|
|
48
|
-
firstEntry.virtualOffset.blockPosition,
|
|
49
|
-
firstEntry.virtualOffset.blockPosition,
|
|
50
|
-
)
|
|
51
|
-
const buffer = await unzip(response)
|
|
52
|
-
const slice = buffer.slice(firstEntry.virtualOffset.dataPosition)
|
|
53
|
-
return this.getChunk(slice, {
|
|
54
|
-
statusCallback: statusCallback as (arg: string) => void,
|
|
55
|
-
signal,
|
|
56
|
-
})
|
|
57
|
-
},
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
async getRefNames() {
|
|
61
|
-
const data = await this.setup()
|
|
62
|
-
return Object.keys(data)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async getChunk(buffer: Uint8Array, opts?: BaseOptions) {
|
|
66
|
-
const { statusCallback = () => {} } = opts || {}
|
|
67
|
-
const alignments = {} as Record<string, OrganismRecord>
|
|
68
|
-
const data = [] as Entry[]
|
|
69
|
-
let a0: any
|
|
70
|
-
let j = 0
|
|
71
|
-
let b = 0
|
|
72
|
-
parseLineByLine(buffer, line => {
|
|
73
|
-
if (j++ % 100 === 0) {
|
|
74
|
-
statusCallback(
|
|
75
|
-
`Processing ${toP(b / 1_000_000)}/${toP(buffer.length / 1_000_000)}Mb`,
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
b += line.length
|
|
79
|
-
if (line) {
|
|
80
|
-
const [lineData, rowInstructions] = line.split(' ; ')
|
|
81
|
-
if (rowInstructions) {
|
|
82
|
-
for (const ins of parseRowInstructions(rowInstructions)) {
|
|
83
|
-
if (ins.type === 'i') {
|
|
84
|
-
data.splice(ins.row, 0, ins)
|
|
85
|
-
if (!alignments[ins.asm]) {
|
|
86
|
-
alignments[ins.asm] = {
|
|
87
|
-
start: ins.start,
|
|
88
|
-
strand: ins.strand,
|
|
89
|
-
srcSize: ins.length,
|
|
90
|
-
chr: ins.ref,
|
|
91
|
-
data: '',
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const e = alignments[ins.asm]!
|
|
95
|
-
e.data += ' '.repeat(Math.max(0, j - e.data.length - 1)) // catch it up
|
|
96
|
-
} else if (ins.type === 's') {
|
|
97
|
-
if (!alignments[ins.asm]) {
|
|
98
|
-
alignments[ins.asm] = {
|
|
99
|
-
start: ins.start,
|
|
100
|
-
strand: ins.strand,
|
|
101
|
-
srcSize: ins.length,
|
|
102
|
-
chr: ins.ref,
|
|
103
|
-
data: '',
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const e = alignments[ins.asm]!
|
|
107
|
-
e.data += ' '.repeat(Math.max(0, j - e.data.length - 1)) // catch it up
|
|
108
|
-
data[ins.row] = ins
|
|
109
|
-
} else if (ins.type === 'd') {
|
|
110
|
-
data.splice(ins.row, 1)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// no gaps for now(?)
|
|
114
|
-
// else if (ins.type === 'g') {
|
|
115
|
-
// console.log('g??')
|
|
116
|
-
// } else if (ins.type === 'G') {
|
|
117
|
-
// console.log('G??')
|
|
118
|
-
// }
|
|
119
|
-
}
|
|
120
|
-
if (!a0) {
|
|
121
|
-
a0 = data[0]
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const lineLen = lineData!.length
|
|
125
|
-
|
|
126
|
-
for (let i = 0; i < lineLen; i++) {
|
|
127
|
-
const letter = lineData![i]
|
|
128
|
-
const r = data[i]
|
|
129
|
-
|
|
130
|
-
if (r) {
|
|
131
|
-
alignments[r.asm]!.data += letter
|
|
132
|
-
} else {
|
|
133
|
-
// not sure why but chr22_KI270731v1_random.taf.gz ends up here
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
if (a0) {
|
|
139
|
-
const row0 = alignments[a0.asm]!
|
|
140
|
-
|
|
141
|
-
// see
|
|
142
|
-
// https://github.com/ComparativeGenomicsToolkit/taffy/blob/f5a5354/docs/taffy_utilities.md#referenced-based-maftaf-and-indexing
|
|
143
|
-
// for the significance of row[0]:
|
|
144
|
-
//
|
|
145
|
-
// "An anchor line in TAF is a column from which all sequence
|
|
146
|
-
// coordinates can be deduced without scanning backwards to previous
|
|
147
|
-
// lines "
|
|
148
|
-
return {
|
|
149
|
-
uniqueId: `${row0.start}-${row0.data.length}`,
|
|
150
|
-
start: row0.start,
|
|
151
|
-
end: row0.start + row0.data.length,
|
|
152
|
-
strand: row0.strand,
|
|
153
|
-
alignments,
|
|
154
|
-
seq: row0.data,
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return undefined
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
setupPre() {
|
|
161
|
-
if (!this.setupP) {
|
|
162
|
-
this.setupP = this.readTaiFile().catch((e: unknown) => {
|
|
163
|
-
this.setupP = undefined
|
|
164
|
-
throw e
|
|
165
|
-
})
|
|
166
|
-
}
|
|
167
|
-
return this.setupP
|
|
168
|
-
}
|
|
169
|
-
setup(opts?: BaseOptions) {
|
|
170
|
-
const { statusCallback = () => {} } = opts || {}
|
|
171
|
-
return updateStatus('Downloading index', statusCallback, () =>
|
|
172
|
-
this.setupPre(),
|
|
173
|
-
)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async readTaiFile() {
|
|
177
|
-
const text = await openLocation(this.getConf('taiLocation')).readFile(
|
|
178
|
-
'utf8',
|
|
179
|
-
)
|
|
180
|
-
const lines = text
|
|
181
|
-
.split('\n')
|
|
182
|
-
.map(f => f.trim())
|
|
183
|
-
.filter(line => !!line)
|
|
184
|
-
const entries = {} as IndexData
|
|
185
|
-
let lastChr = ''
|
|
186
|
-
let lastChrStart = 0
|
|
187
|
-
let lastRawVirtualOffset = 0
|
|
188
|
-
for (const line of lines) {
|
|
189
|
-
const [chr, chrStart, virtualOffset] = line.split('\t')
|
|
190
|
-
const relativizedVirtualOffset = lastRawVirtualOffset + +virtualOffset!
|
|
191
|
-
const currChr = chr === '*' ? lastChr : chr!.split('.').at(-1)!
|
|
192
|
-
|
|
193
|
-
// bgzip TAF files store virtual offsets in plaintext in the TAI file
|
|
194
|
-
// these virtualoffsets are 64bit values, so the long library is needed
|
|
195
|
-
// to accurately do the bit manipulations needed
|
|
196
|
-
const x = Long.fromNumber(relativizedVirtualOffset)
|
|
197
|
-
const y = x.shiftRightUnsigned(16)
|
|
198
|
-
const z = x.and(0xffff)
|
|
199
|
-
const voff = new VirtualOffset(y.toNumber(), z.toNumber())
|
|
200
|
-
|
|
201
|
-
if (!entries[currChr]) {
|
|
202
|
-
entries[currChr] = []
|
|
203
|
-
lastChr = ''
|
|
204
|
-
lastChrStart = 0
|
|
205
|
-
lastRawVirtualOffset = 0
|
|
206
|
-
}
|
|
207
|
-
const currStart = +chrStart! + lastChrStart
|
|
208
|
-
entries[currChr].push({
|
|
209
|
-
chrStart: currStart,
|
|
210
|
-
virtualOffset: voff,
|
|
211
|
-
})
|
|
212
|
-
lastChr = currChr
|
|
213
|
-
lastChrStart = currStart
|
|
214
|
-
lastRawVirtualOffset = relativizedVirtualOffset
|
|
215
|
-
}
|
|
216
|
-
return entries
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
getFeatures(query: Region, opts?: BaseOptions) {
|
|
220
|
-
const { statusCallback = () => {} } = opts || {}
|
|
221
|
-
return ObservableCreate<Feature>(async observer => {
|
|
222
|
-
try {
|
|
223
|
-
const byteRanges = await this.setup()
|
|
224
|
-
const feat = await updateStatus(
|
|
225
|
-
'Downloading alignments',
|
|
226
|
-
statusCallback,
|
|
227
|
-
() => this.getLines(query, byteRanges),
|
|
228
|
-
)
|
|
229
|
-
if (feat) {
|
|
230
|
-
observer.next(
|
|
231
|
-
// @ts-expect-error
|
|
232
|
-
new SimpleFeature({
|
|
233
|
-
...feat,
|
|
234
|
-
refName: query.refName,
|
|
235
|
-
}),
|
|
236
|
-
)
|
|
237
|
-
} else {
|
|
238
|
-
console.error('no feature found')
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
statusCallback('')
|
|
242
|
-
observer.complete()
|
|
243
|
-
} catch (e) {
|
|
244
|
-
observer.error(e)
|
|
245
|
-
}
|
|
246
|
-
})
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
async getSamples(_query: Region) {
|
|
250
|
-
const nhLoc = this.getConf('nhLocation')
|
|
251
|
-
const nh =
|
|
252
|
-
nhLoc.uri === '/path/to/my.nh'
|
|
253
|
-
? undefined
|
|
254
|
-
: await openLocation(nhLoc).readFile('utf8')
|
|
255
|
-
|
|
256
|
-
// TODO: we may need to resolve the exact set of rows in the visible region
|
|
257
|
-
// here
|
|
258
|
-
return {
|
|
259
|
-
samples: normalize(this.getConf('samples')),
|
|
260
|
-
tree: nh ? parseNewick(nh) : undefined,
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// TODO: cache processed large chunks
|
|
265
|
-
async getLines(query: Region, byteRanges: IndexData) {
|
|
266
|
-
const records = byteRanges[query.refName]
|
|
267
|
-
if (records) {
|
|
268
|
-
let firstEntry
|
|
269
|
-
let nextEntry
|
|
270
|
-
|
|
271
|
-
// two pass:
|
|
272
|
-
// first pass: find first block greater than query start, then -1 from
|
|
273
|
-
// that
|
|
274
|
-
for (let i = 0; i < records.length; i++) {
|
|
275
|
-
if (records[i]!.chrStart >= query.start) {
|
|
276
|
-
firstEntry = records[Math.max(i - 1, 0)]
|
|
277
|
-
break
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
// second pass: find first block where query end less than record start,
|
|
281
|
-
// and +1 from that
|
|
282
|
-
for (let i = 0; i < records.length; i++) {
|
|
283
|
-
if (query.end <= records[i]!.chrStart) {
|
|
284
|
-
nextEntry = records[i + 1]
|
|
285
|
-
break
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
nextEntry = nextEntry ?? records.at(-1)
|
|
290
|
-
// we NEED at least a firstEntry (validate behavior?) because othrwise it fetches whole
|
|
291
|
-
// file whn you request e.g. out of range region (e.g. taf in chr22:1-100
|
|
292
|
-
// and you are at chr22:200-300)
|
|
293
|
-
if (firstEntry && nextEntry) {
|
|
294
|
-
return this.cache.get(
|
|
295
|
-
`${JSON.stringify(nextEntry)}_${JSON.stringify(firstEntry)}`,
|
|
296
|
-
{
|
|
297
|
-
nextEntry,
|
|
298
|
-
firstEntry,
|
|
299
|
-
},
|
|
300
|
-
)
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return undefined
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
freeResources(): void {}
|
|
307
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* #config BgzipTaffyAdapter
|
|
5
|
-
* used to configure BgzipTaffy adapter
|
|
6
|
-
*/
|
|
7
|
-
function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
8
|
-
|
|
9
|
-
const configSchema = ConfigurationSchema(
|
|
10
|
-
'BgzipTaffyAdapter',
|
|
11
|
-
{
|
|
12
|
-
/**
|
|
13
|
-
* #slot
|
|
14
|
-
*/
|
|
15
|
-
samples: {
|
|
16
|
-
type: 'frozen',
|
|
17
|
-
description: 'string[] or {id:string,label:string,color?:string}[]',
|
|
18
|
-
defaultValue: [],
|
|
19
|
-
},
|
|
20
|
-
/**
|
|
21
|
-
* #slot
|
|
22
|
-
*/
|
|
23
|
-
tafGzLocation: {
|
|
24
|
-
type: 'fileLocation',
|
|
25
|
-
description: 'bgzip taffy file',
|
|
26
|
-
defaultValue: {
|
|
27
|
-
uri: '/path/to/my.taf',
|
|
28
|
-
locationType: 'UriLocation',
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
/**
|
|
32
|
-
* #slot
|
|
33
|
-
*/
|
|
34
|
-
taiLocation: {
|
|
35
|
-
type: 'fileLocation',
|
|
36
|
-
description: 'taffy index',
|
|
37
|
-
defaultValue: {
|
|
38
|
-
uri: '/path/to/my.taf.gz.tai',
|
|
39
|
-
locationType: 'UriLocation',
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
/**
|
|
43
|
-
* #slot
|
|
44
|
-
*/
|
|
45
|
-
nhLocation: {
|
|
46
|
-
type: 'fileLocation',
|
|
47
|
-
description: 'newick tree',
|
|
48
|
-
defaultValue: {
|
|
49
|
-
uri: '/path/to/my.nh',
|
|
50
|
-
locationType: 'UriLocation',
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
explicitlyTyped: true,
|
|
56
|
-
},
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
export default configSchema
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
-
import { AdapterType } from '@jbrowse/core/pluggableElementTypes'
|
|
3
|
-
|
|
4
|
-
import BgzipTaffyAdapter from './BgzipTaffyAdapter'
|
|
5
|
-
import configSchema from './configSchema'
|
|
6
|
-
|
|
7
|
-
export default function BgzipTaffyAdapterF(pluginManager: PluginManager) {
|
|
8
|
-
return pluginManager.addAdapterType(
|
|
9
|
-
() =>
|
|
10
|
-
new AdapterType({
|
|
11
|
-
name: 'BgzipTaffyAdapter',
|
|
12
|
-
AdapterClass: BgzipTaffyAdapter,
|
|
13
|
-
configSchema,
|
|
14
|
-
}),
|
|
15
|
-
)
|
|
16
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
interface RowInsert {
|
|
2
|
-
type: 'i'
|
|
3
|
-
row: number
|
|
4
|
-
asm: string
|
|
5
|
-
ref: string
|
|
6
|
-
start: number
|
|
7
|
-
strand: number
|
|
8
|
-
length: number
|
|
9
|
-
}
|
|
10
|
-
interface RowSubstitute {
|
|
11
|
-
type: 's'
|
|
12
|
-
row: number
|
|
13
|
-
asm: string
|
|
14
|
-
ref: string
|
|
15
|
-
start: number
|
|
16
|
-
strand: number
|
|
17
|
-
length: number
|
|
18
|
-
}
|
|
19
|
-
interface RowDelete {
|
|
20
|
-
type: 'd'
|
|
21
|
-
row: number
|
|
22
|
-
}
|
|
23
|
-
interface RowGap {
|
|
24
|
-
type: 'g'
|
|
25
|
-
row: number
|
|
26
|
-
gapLen: number
|
|
27
|
-
}
|
|
28
|
-
interface RowGapSubstring {
|
|
29
|
-
type: 'G'
|
|
30
|
-
row: number
|
|
31
|
-
gapSubstring: string
|
|
32
|
-
}
|
|
33
|
-
type RowInstruction =
|
|
34
|
-
| RowInsert
|
|
35
|
-
| RowDelete
|
|
36
|
-
| RowGap
|
|
37
|
-
| RowGapSubstring
|
|
38
|
-
| RowSubstitute
|
|
39
|
-
|
|
40
|
-
export function parseRowInstructions(meta: string) {
|
|
41
|
-
const ret = meta.split(' ')
|
|
42
|
-
const rows = [] as RowInstruction[]
|
|
43
|
-
|
|
44
|
-
for (let i = 0; i < ret.length; ) {
|
|
45
|
-
const type = ret[i++]
|
|
46
|
-
if (type === 'i') {
|
|
47
|
-
const row = +ret[i++]!
|
|
48
|
-
const [asm, ref] = ret[i++]!.split('.')
|
|
49
|
-
rows.push({
|
|
50
|
-
type,
|
|
51
|
-
row,
|
|
52
|
-
asm: asm!,
|
|
53
|
-
ref: ref!,
|
|
54
|
-
start: +ret[i++]!,
|
|
55
|
-
strand: ret[i++] === '-' ? -1 : 1,
|
|
56
|
-
length: +ret[i++]!,
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
if (type === 's') {
|
|
60
|
-
const row = +ret[i++]!
|
|
61
|
-
const [asm, ref] = ret[i++]!.split('.')
|
|
62
|
-
rows.push({
|
|
63
|
-
type,
|
|
64
|
-
row,
|
|
65
|
-
asm: asm!,
|
|
66
|
-
ref: ref!,
|
|
67
|
-
start: +ret[i++]!,
|
|
68
|
-
strand: ret[i++] === '-' ? -1 : 1,
|
|
69
|
-
length: +ret[i++]!,
|
|
70
|
-
})
|
|
71
|
-
} else if (type === 'd') {
|
|
72
|
-
rows.push({
|
|
73
|
-
type,
|
|
74
|
-
row: +ret[i++]!,
|
|
75
|
-
})
|
|
76
|
-
} else if (type === 'g') {
|
|
77
|
-
rows.push({
|
|
78
|
-
type,
|
|
79
|
-
row: +ret[i++]!,
|
|
80
|
-
gapLen: +ret[i++]!,
|
|
81
|
-
})
|
|
82
|
-
} else if (type === 'G') {
|
|
83
|
-
rows.push({
|
|
84
|
-
type,
|
|
85
|
-
row: +ret[i++]!,
|
|
86
|
-
gapSubstring: ret[i++]!,
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return rows
|
|
91
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import VirtualOffset from './virtualOffset'
|
|
2
|
-
|
|
3
|
-
export interface OrganismRecord {
|
|
4
|
-
chr: string
|
|
5
|
-
start: number
|
|
6
|
-
srcSize: number
|
|
7
|
-
strand: number
|
|
8
|
-
data: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ByteRange {
|
|
12
|
-
chrStart: number
|
|
13
|
-
virtualOffset: VirtualOffset
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type IndexData = Record<string, ByteRange[]>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export function parseLineByLine<T>(
|
|
2
|
-
buffer: Uint8Array,
|
|
3
|
-
cb: (line: string) => T | undefined,
|
|
4
|
-
): T[] {
|
|
5
|
-
let blockStart = 0
|
|
6
|
-
const entries: T[] = []
|
|
7
|
-
const decoder = new TextDecoder('utf8')
|
|
8
|
-
while (blockStart < buffer.length) {
|
|
9
|
-
const n = buffer.indexOf(10, blockStart)
|
|
10
|
-
if (n === -1) {
|
|
11
|
-
break
|
|
12
|
-
}
|
|
13
|
-
const b = buffer.subarray(blockStart, n)
|
|
14
|
-
const line = decoder.decode(b).trim()
|
|
15
|
-
if (line) {
|
|
16
|
-
const entry = cb(line)
|
|
17
|
-
if (entry) {
|
|
18
|
-
entries.push(entry)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
blockStart = n + 1
|
|
23
|
-
}
|
|
24
|
-
return entries
|
|
25
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export default class VirtualOffset {
|
|
2
|
-
public blockPosition: number
|
|
3
|
-
public dataPosition: number
|
|
4
|
-
constructor(blockPosition: number, dataPosition: number) {
|
|
5
|
-
this.blockPosition = blockPosition // < offset of the compressed data block
|
|
6
|
-
this.dataPosition = dataPosition // < offset into the uncompressed data
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
toString() {
|
|
10
|
-
return `${this.blockPosition}:${this.dataPosition}`
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
compareTo(b: VirtualOffset) {
|
|
14
|
-
return (
|
|
15
|
-
this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition
|
|
16
|
-
)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
export function fromBytes(bytes: Uint8Array, offset = 0) {
|
|
20
|
-
return new VirtualOffset(
|
|
21
|
-
bytes[offset + 7]! * 0x10000000000 +
|
|
22
|
-
bytes[offset + 6]! * 0x100000000 +
|
|
23
|
-
bytes[offset + 5]! * 0x1000000 +
|
|
24
|
-
bytes[offset + 4]! * 0x10000 +
|
|
25
|
-
bytes[offset + 3]! * 0x100 +
|
|
26
|
-
bytes[offset + 2]!,
|
|
27
|
-
(bytes[offset + 1]! << 8) | bytes[offset]!,
|
|
28
|
-
)
|
|
29
|
-
}
|