@jbrowse/img 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -4
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +2 -2
- package/dist/bin.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +207 -202
- package/dist/index.js.map +1 -0
- package/dist/parseArgv.d.ts +8 -0
- package/dist/parseArgv.js +42 -33
- package/dist/parseArgv.js.map +1 -0
- package/dist/renderRegion.d.ts +35 -0
- package/dist/renderRegion.js +345 -425
- package/dist/renderRegion.js.map +1 -0
- package/dist/util.d.ts +5 -0
- package/dist/util.js +31 -9
- package/dist/util.js.map +1 -0
- package/esm/bin.d.ts +2 -0
- package/esm/bin.js +4 -0
- package/esm/bin.js.map +1 -0
- package/esm/index.d.ts +1 -0
- package/esm/index.js +186 -0
- package/esm/index.js.map +1 -0
- package/esm/parseArgv.d.ts +8 -0
- package/esm/parseArgv.js +42 -0
- package/esm/parseArgv.js.map +1 -0
- package/esm/renderRegion.d.ts +35 -0
- package/esm/renderRegion.js +366 -0
- package/esm/renderRegion.js.map +1 -0
- package/esm/util.d.ts +5 -0
- package/esm/util.js +25 -0
- package/esm/util.js.map +1 -0
- package/package.json +15 -10
- package/src/bin.js +2 -0
- package/src/index.test.js +179 -0
- package/src/index.ts +210 -0
- package/src/parseArgv.test.js +29 -0
- package/src/parseArgv.ts +48 -0
- package/src/renderRegion.tsx +456 -0
- package/src/util.ts +32 -0
- package/dist/index.testmod.js +0 -210
- package/dist/parseArgv.testmod.js +0 -7
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { createViewState } from '@jbrowse/react-linear-genome-view'
|
|
3
|
+
import {
|
|
4
|
+
LinearGenomeViewModel,
|
|
5
|
+
renderToSvg,
|
|
6
|
+
} from '@jbrowse/plugin-linear-genome-view'
|
|
7
|
+
import createCache from '@emotion/cache'
|
|
8
|
+
import { CacheProvider } from '@emotion/react'
|
|
9
|
+
import path from 'path'
|
|
10
|
+
import fs from 'fs'
|
|
11
|
+
|
|
12
|
+
// local
|
|
13
|
+
import { Entry } from './parseArgv'
|
|
14
|
+
import { booleanize } from './util'
|
|
15
|
+
|
|
16
|
+
export interface Opts {
|
|
17
|
+
noRasterize?: boolean
|
|
18
|
+
loc?: string
|
|
19
|
+
width?: number
|
|
20
|
+
session?: string
|
|
21
|
+
assembly?: string
|
|
22
|
+
config?: string
|
|
23
|
+
fasta?: string
|
|
24
|
+
aliases?: string
|
|
25
|
+
cytobands?: string
|
|
26
|
+
defaultSession?: string
|
|
27
|
+
trackList: Entry[]
|
|
28
|
+
tracks?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function read(file: string) {
|
|
32
|
+
let res
|
|
33
|
+
try {
|
|
34
|
+
res = JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
35
|
+
} catch (e) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Failed to parse ${file} as JSON, use --fasta if you mean to pass a FASTA file`,
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
return res
|
|
41
|
+
}
|
|
42
|
+
function makeLocation(file: string) {
|
|
43
|
+
return file.startsWith('http') ? { uri: file } : { localPath: file }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function addRelativePaths(config: Record<string, unknown>, configPath: string) {
|
|
47
|
+
if (typeof config === 'object') {
|
|
48
|
+
for (const key of Object.keys(config)) {
|
|
49
|
+
if (typeof config[key] === 'object') {
|
|
50
|
+
addRelativePaths(config[key] as Record<string, unknown>, configPath)
|
|
51
|
+
} else if (key === 'localPath') {
|
|
52
|
+
config.localPath = path.resolve(configPath, config.localPath as string)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface Assembly {
|
|
59
|
+
name: string
|
|
60
|
+
sequence: Record<string, unknown>
|
|
61
|
+
refNameAliases?: Record<string, unknown>
|
|
62
|
+
cytobands?: Record<string, unknown>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface Track {
|
|
66
|
+
trackId: string
|
|
67
|
+
[key: string]: unknown
|
|
68
|
+
}
|
|
69
|
+
interface Config {
|
|
70
|
+
assemblies: Assembly[]
|
|
71
|
+
assembly: Assembly
|
|
72
|
+
tracks: Track[]
|
|
73
|
+
[key: string]: unknown
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function readData({
|
|
77
|
+
assembly: asm,
|
|
78
|
+
config,
|
|
79
|
+
session,
|
|
80
|
+
fasta,
|
|
81
|
+
aliases,
|
|
82
|
+
cytobands,
|
|
83
|
+
defaultSession,
|
|
84
|
+
tracks,
|
|
85
|
+
trackList = [],
|
|
86
|
+
}: Opts) {
|
|
87
|
+
const assemblyData = asm && fs.existsSync(asm) ? read(asm) : undefined
|
|
88
|
+
const tracksData = tracks ? read(tracks) : undefined
|
|
89
|
+
const configData = (config ? read(config) : {}) as Config
|
|
90
|
+
let sessionData = session ? read(session) : undefined
|
|
91
|
+
|
|
92
|
+
if (config) {
|
|
93
|
+
addRelativePaths(configData, path.dirname(path.resolve(config)))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// the session.json can be a raw session or a json file with a "session"
|
|
97
|
+
// attribute, which is what is exported via the "File->Export session" in
|
|
98
|
+
// jbrowse-web
|
|
99
|
+
if (sessionData?.session) {
|
|
100
|
+
sessionData = sessionData.session
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// only export first view
|
|
104
|
+
if (sessionData?.views) {
|
|
105
|
+
sessionData.view = sessionData.views[0]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// use assembly from file if a file existed
|
|
109
|
+
if (assemblyData) {
|
|
110
|
+
configData.assembly = assemblyData
|
|
111
|
+
}
|
|
112
|
+
// else check if it was an assembly name in a config file
|
|
113
|
+
else if (configData.assemblies?.length) {
|
|
114
|
+
configData.assemblies.find(entry => entry.name === asm)
|
|
115
|
+
if (asm) {
|
|
116
|
+
const assembly = configData.assemblies.find(entry => entry.name === asm)
|
|
117
|
+
if (!assembly) {
|
|
118
|
+
throw new Error(`assembly ${asm} not found in config`)
|
|
119
|
+
}
|
|
120
|
+
configData.assembly = assembly
|
|
121
|
+
} else {
|
|
122
|
+
configData.assembly = configData.assemblies[0]
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// else load fasta from command line
|
|
126
|
+
else if (fasta) {
|
|
127
|
+
const bgzip = fasta.endsWith('gz')
|
|
128
|
+
|
|
129
|
+
configData.assembly = {
|
|
130
|
+
name: path.basename(fasta),
|
|
131
|
+
sequence: {
|
|
132
|
+
type: 'ReferenceSequenceTrack',
|
|
133
|
+
trackId: 'refseq',
|
|
134
|
+
adapter: {
|
|
135
|
+
type: bgzip ? 'BgzipFastaAdapter' : 'IndexedFastaAdapter',
|
|
136
|
+
fastaLocation: makeLocation(fasta),
|
|
137
|
+
faiLocation: makeLocation(fasta + '.fai'),
|
|
138
|
+
gziLocation: bgzip ? makeLocation(fasta + '.gzi') : undefined,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
if (aliases) {
|
|
143
|
+
configData.assembly.refNameAliases = {
|
|
144
|
+
adapter: {
|
|
145
|
+
type: 'RefNameAliasAdapter',
|
|
146
|
+
location: makeLocation(aliases),
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (cytobands) {
|
|
151
|
+
configData.assembly.cytobands = {
|
|
152
|
+
adapter: {
|
|
153
|
+
type: 'CytobandAdapter',
|
|
154
|
+
location: makeLocation(cytobands),
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// throw if still no assembly
|
|
161
|
+
if (!configData.assembly) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
'no assembly specified, use --fasta to supply an indexed FASTA file (generated with samtools faidx yourfile.fa). see README for alternatives with --assembly and --config',
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (tracksData) {
|
|
168
|
+
configData.tracks = tracksData
|
|
169
|
+
} else if (!configData.tracks) {
|
|
170
|
+
configData.tracks = []
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
trackList.forEach(track => {
|
|
174
|
+
const [type, [file]] = track
|
|
175
|
+
|
|
176
|
+
if (type === 'bam') {
|
|
177
|
+
configData.tracks = [
|
|
178
|
+
...configData.tracks,
|
|
179
|
+
{
|
|
180
|
+
type: 'AlignmentsTrack',
|
|
181
|
+
trackId: path.basename(file),
|
|
182
|
+
name: path.basename(file),
|
|
183
|
+
assemblyNames: [configData.assembly.name],
|
|
184
|
+
adapter: {
|
|
185
|
+
type: 'BamAdapter',
|
|
186
|
+
bamLocation: makeLocation(file),
|
|
187
|
+
index: { location: makeLocation(file + '.bai') },
|
|
188
|
+
sequenceAdapter: configData.assembly.sequence.adapter,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
if (type === 'cram') {
|
|
194
|
+
configData.tracks = [
|
|
195
|
+
...configData.tracks,
|
|
196
|
+
{
|
|
197
|
+
type: 'AlignmentsTrack',
|
|
198
|
+
trackId: path.basename(file),
|
|
199
|
+
name: path.basename(file),
|
|
200
|
+
assemblyNames: [configData.assembly.name],
|
|
201
|
+
adapter: {
|
|
202
|
+
type: 'CramAdapter',
|
|
203
|
+
cramLocation: makeLocation(file),
|
|
204
|
+
craiLocation: makeLocation(file + '.crai'),
|
|
205
|
+
sequenceAdapter: configData.assembly.sequence.adapter,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
if (type === 'bigwig') {
|
|
211
|
+
configData.tracks = [
|
|
212
|
+
...configData.tracks,
|
|
213
|
+
{
|
|
214
|
+
type: 'QuantitativeTrack',
|
|
215
|
+
trackId: path.basename(file),
|
|
216
|
+
name: path.basename(file),
|
|
217
|
+
assemblyNames: [configData.assembly.name],
|
|
218
|
+
adapter: {
|
|
219
|
+
type: 'BigWigAdapter',
|
|
220
|
+
bigWigLocation: makeLocation(file),
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (type === 'vcfgz') {
|
|
227
|
+
configData.tracks = [
|
|
228
|
+
...configData.tracks,
|
|
229
|
+
{
|
|
230
|
+
type: 'VariantTrack',
|
|
231
|
+
trackId: path.basename(file),
|
|
232
|
+
name: path.basename(file),
|
|
233
|
+
assemblyNames: [configData.assembly.name],
|
|
234
|
+
adapter: {
|
|
235
|
+
type: 'VcfTabixAdapter',
|
|
236
|
+
vcfGzLocation: makeLocation(file),
|
|
237
|
+
index: {
|
|
238
|
+
location: makeLocation(file + '.tbi'),
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (type === 'gffgz') {
|
|
246
|
+
configData.tracks = [
|
|
247
|
+
...configData.tracks,
|
|
248
|
+
{
|
|
249
|
+
type: 'FeatureTrack',
|
|
250
|
+
trackId: path.basename(file),
|
|
251
|
+
name: path.basename(file),
|
|
252
|
+
assemblyNames: [configData.assembly.name],
|
|
253
|
+
adapter: {
|
|
254
|
+
type: 'Gff3TabixAdapter',
|
|
255
|
+
gffGzLocation: makeLocation(file),
|
|
256
|
+
index: {
|
|
257
|
+
location: makeLocation(file + '.tbi'),
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (type === 'hic') {
|
|
265
|
+
configData.tracks = [
|
|
266
|
+
...configData.tracks,
|
|
267
|
+
{
|
|
268
|
+
type: 'HicTrack',
|
|
269
|
+
trackId: path.basename(file),
|
|
270
|
+
name: path.basename(file),
|
|
271
|
+
assemblyNames: [configData.assembly.name],
|
|
272
|
+
adapter: {
|
|
273
|
+
type: 'HicAdapter',
|
|
274
|
+
hicLocation: makeLocation(file),
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
if (type === 'bigbed') {
|
|
280
|
+
configData.tracks = [
|
|
281
|
+
...configData.tracks,
|
|
282
|
+
{
|
|
283
|
+
type: 'FeatureTrack',
|
|
284
|
+
trackId: path.basename(file),
|
|
285
|
+
name: path.basename(file),
|
|
286
|
+
assemblyNames: [configData.assembly.name],
|
|
287
|
+
adapter: {
|
|
288
|
+
type: 'BigBedAdapter',
|
|
289
|
+
bigBedLocation: makeLocation(file),
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
if (type === 'bedgz') {
|
|
295
|
+
configData.tracks = [
|
|
296
|
+
...configData.tracks,
|
|
297
|
+
{
|
|
298
|
+
type: 'FeatureTrack',
|
|
299
|
+
trackId: path.basename(file),
|
|
300
|
+
name: path.basename(file),
|
|
301
|
+
assemblyNames: [configData.assembly.name],
|
|
302
|
+
adapter: {
|
|
303
|
+
type: 'BedTabixAdapter',
|
|
304
|
+
bedGzLocation: makeLocation(file),
|
|
305
|
+
index: {
|
|
306
|
+
location: makeLocation(file + '.tbi'),
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
if (!defaultSession) {
|
|
315
|
+
// don't use defaultSession from config.json file, can result in assembly
|
|
316
|
+
// name confusion
|
|
317
|
+
delete configData.defaultSession
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// only allow an external manually specified session
|
|
321
|
+
if (sessionData) {
|
|
322
|
+
configData.defaultSession = sessionData
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return configData
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// without this, the styles can become messed up especially in lgv header
|
|
329
|
+
// xref https://github.com/garronej/tss-react/issues/25
|
|
330
|
+
export const muiCache = createCache({
|
|
331
|
+
key: 'mui',
|
|
332
|
+
prepend: true,
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
function process(
|
|
336
|
+
trackEntry: Entry,
|
|
337
|
+
view: LinearGenomeViewModel,
|
|
338
|
+
extra: (arg: string) => string = c => c,
|
|
339
|
+
) {
|
|
340
|
+
const [, [track, ...opts]] = trackEntry
|
|
341
|
+
const currentTrack = view.showTrack(extra(track))
|
|
342
|
+
const display = currentTrack.displays[0]
|
|
343
|
+
opts.forEach(opt => {
|
|
344
|
+
// apply height to any track
|
|
345
|
+
if (opt.startsWith('height:')) {
|
|
346
|
+
const [, height] = opt.split(':')
|
|
347
|
+
display.setHeight(+height)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// apply sort to pileup
|
|
351
|
+
else if (opt.startsWith('sort:')) {
|
|
352
|
+
const [, type, tag] = opt.split(':')
|
|
353
|
+
display.PileupDisplay.setSortedBy(type, tag)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// apply color scheme to pileup
|
|
357
|
+
else if (opt.startsWith('color:')) {
|
|
358
|
+
const [, type, tag] = opt.split(':')
|
|
359
|
+
if (display.PileupDisplay) {
|
|
360
|
+
display.PileupDisplay.setColorScheme({ type, tag })
|
|
361
|
+
} else {
|
|
362
|
+
display.setColor(type)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// force track to render even if maxbpperpx limit hit...
|
|
367
|
+
else if (opt.startsWith('force:')) {
|
|
368
|
+
const [, force] = opt.split(':')
|
|
369
|
+
if (force) {
|
|
370
|
+
display.updateStatsLimit({ bytes: Number.MAX_VALUE })
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// apply wiggle autoscale
|
|
375
|
+
else if (opt.startsWith('autoscale:')) {
|
|
376
|
+
const [, autoscale] = opt.split(':')
|
|
377
|
+
display.setAutoscale(autoscale)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// apply min and max score to wiggle
|
|
381
|
+
else if (opt.startsWith('minmax:')) {
|
|
382
|
+
const [, min, max] = opt.split(':')
|
|
383
|
+
display.setMinScore(+min)
|
|
384
|
+
display.setMaxScore(+max)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// apply linear or log scale to wiggle
|
|
388
|
+
else if (opt.startsWith('scaletype:')) {
|
|
389
|
+
const [, scaletype] = opt.split(':')
|
|
390
|
+
display.setScaleType(scaletype)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// draw crosshatches on wiggle
|
|
394
|
+
else if (opt.startsWith('crosshatch:')) {
|
|
395
|
+
const [, val] = opt.split(':')
|
|
396
|
+
display.setCrossHatches(booleanize(val))
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// turn off fill on bigwig with fill:false
|
|
400
|
+
else if (opt.startsWith('fill:')) {
|
|
401
|
+
const [, val] = opt.split(':')
|
|
402
|
+
display.setFill(booleanize(val))
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// set resolution:superfine to use finer bigwig bin size
|
|
406
|
+
else if (opt.startsWith('resolution:')) {
|
|
407
|
+
let [, val] = opt.split(':')
|
|
408
|
+
if (val === 'fine') {
|
|
409
|
+
val = '10'
|
|
410
|
+
} else if (val === 'superfine') {
|
|
411
|
+
val = '100'
|
|
412
|
+
}
|
|
413
|
+
display.setResolution(+val)
|
|
414
|
+
}
|
|
415
|
+
})
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export async function renderRegion(opts: Opts) {
|
|
419
|
+
const model = createViewState(readData(opts))
|
|
420
|
+
const {
|
|
421
|
+
loc,
|
|
422
|
+
width = 1500,
|
|
423
|
+
trackList = [],
|
|
424
|
+
session: sessionParam,
|
|
425
|
+
defaultSession,
|
|
426
|
+
} = opts
|
|
427
|
+
|
|
428
|
+
const { session } = model
|
|
429
|
+
const { view } = session
|
|
430
|
+
const { assemblyManager } = model
|
|
431
|
+
|
|
432
|
+
view.setWidth(width)
|
|
433
|
+
|
|
434
|
+
if (loc) {
|
|
435
|
+
const [assembly] = assemblyManager.assemblies
|
|
436
|
+
if (loc === 'all') {
|
|
437
|
+
view.showAllRegionsInAssembly(assembly.name)
|
|
438
|
+
} else {
|
|
439
|
+
await view.navToLocString(loc, assembly.name)
|
|
440
|
+
}
|
|
441
|
+
} else if (!sessionParam && !defaultSession) {
|
|
442
|
+
console.warn('No loc specified')
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
trackList.forEach(track => {
|
|
446
|
+
process(track, view, extra => path.basename(extra))
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
return renderToSvg(view, {
|
|
450
|
+
rasterizeLayers: !opts.noRasterize,
|
|
451
|
+
...opts,
|
|
452
|
+
Wrapper: ({ children }) => (
|
|
453
|
+
<CacheProvider value={muiCache}>{children}</CacheProvider>
|
|
454
|
+
),
|
|
455
|
+
})
|
|
456
|
+
}
|
package/src/util.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import tmp from 'tmp'
|
|
3
|
+
import { spawnSync } from 'child_process'
|
|
4
|
+
|
|
5
|
+
// nice helper function from https://stackoverflow.com/questions/263965/
|
|
6
|
+
export function booleanize(str: string) {
|
|
7
|
+
return str === 'false' ? false : !!str
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function createTmp() {
|
|
11
|
+
return tmp.fileSync({
|
|
12
|
+
mode: 0o644,
|
|
13
|
+
prefix: 'prefix-',
|
|
14
|
+
postfix: '.svg',
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function convert(
|
|
19
|
+
result: string,
|
|
20
|
+
args: { out: string; pngwidth?: string },
|
|
21
|
+
spawnArgs: string[] = [],
|
|
22
|
+
) {
|
|
23
|
+
const { name } = createTmp()
|
|
24
|
+
const { pngwidth = '2048', out } = args
|
|
25
|
+
fs.writeFileSync(name, result)
|
|
26
|
+
const a = ['-w', pngwidth, name, '-o', out, ...spawnArgs] as string[]
|
|
27
|
+
const ls = spawnSync('rsvg-convert', a)
|
|
28
|
+
|
|
29
|
+
console.error(`rsvg-convert stderr: ${ls.stderr.toString()}`)
|
|
30
|
+
console.log(`rsvg-convert stdout: ${ls.stdout.toString()}`) // eslint-disable-line no-console
|
|
31
|
+
fs.unlinkSync(name)
|
|
32
|
+
}
|
package/dist/index.testmod.js
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
5
|
-
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
6
|
-
var _renderRegion = require("./renderRegion");
|
|
7
|
-
var _fs = _interopRequireDefault(require("fs"));
|
|
8
|
-
var _jsdom = require("jsdom");
|
|
9
|
-
require("abortcontroller-polyfill/dist/abortcontroller-polyfill-only");
|
|
10
|
-
var _canvas = require("canvas");
|
|
11
|
-
var document = new _jsdom.JSDOM("...").window.document;
|
|
12
|
-
global.document = document;
|
|
13
|
-
global.nodeImage = _canvas.Image;
|
|
14
|
-
global.nodeCreateCanvas = _canvas.createCanvas;
|
|
15
|
-
function hashCode(str) {
|
|
16
|
-
var hash = 0;
|
|
17
|
-
var chr;
|
|
18
|
-
if (str.length === 0) {
|
|
19
|
-
return hash;
|
|
20
|
-
}
|
|
21
|
-
for (var i = 0; i < str.length; i++) {
|
|
22
|
-
chr = str.charCodeAt(i);
|
|
23
|
-
hash = (hash << 5) - hash + chr;
|
|
24
|
-
hash |= 0; // Convert to 32bit integer
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return hash;
|
|
28
|
-
}
|
|
29
|
-
var timeout = 20000;
|
|
30
|
-
|
|
31
|
-
// commented out for using remote files currently
|
|
32
|
-
xtest('renders a region with --session and --config args', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
33
|
-
var result;
|
|
34
|
-
return _regenerator.default.wrap(function _callee$(_context) {
|
|
35
|
-
while (1) {
|
|
36
|
-
switch (_context.prev = _context.next) {
|
|
37
|
-
case 0:
|
|
38
|
-
_context.next = 2;
|
|
39
|
-
return (0, _renderRegion.renderRegion)({
|
|
40
|
-
session: require.resolve('../test/clingen_session.json'),
|
|
41
|
-
config: require.resolve('../data/config.json')
|
|
42
|
-
});
|
|
43
|
-
case 2:
|
|
44
|
-
result = _context.sent;
|
|
45
|
-
_fs.default.writeFileSync('svg_from_config_and_session_param.svg', result);
|
|
46
|
-
expect(hashCode(result)).toMatchSnapshot();
|
|
47
|
-
case 5:
|
|
48
|
-
case "end":
|
|
49
|
-
return _context.stop();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}, _callee);
|
|
53
|
-
})), timeout);
|
|
54
|
-
|
|
55
|
-
// commented out for using remote files currently
|
|
56
|
-
xtest('renders a region with --session, --tracks, and --assembly args', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
|
|
57
|
-
var result;
|
|
58
|
-
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
59
|
-
while (1) {
|
|
60
|
-
switch (_context2.prev = _context2.next) {
|
|
61
|
-
case 0:
|
|
62
|
-
_context2.next = 2;
|
|
63
|
-
return (0, _renderRegion.renderRegion)({
|
|
64
|
-
session: require.resolve('../test/clingen_session.json'),
|
|
65
|
-
tracks: require.resolve('../data/tracks.json'),
|
|
66
|
-
assembly: require.resolve('../data/assembly.json')
|
|
67
|
-
});
|
|
68
|
-
case 2:
|
|
69
|
-
result = _context2.sent;
|
|
70
|
-
_fs.default.writeFileSync('svg_from_separate_session_and_tracks.svg', result);
|
|
71
|
-
expect(hashCode(result)).toMatchSnapshot();
|
|
72
|
-
case 5:
|
|
73
|
-
case "end":
|
|
74
|
-
return _context2.stop();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}, _callee2);
|
|
78
|
-
})), timeout);
|
|
79
|
-
test('renders volvox with variety of args', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
|
|
80
|
-
var fp, result;
|
|
81
|
-
return _regenerator.default.wrap(function _callee3$(_context3) {
|
|
82
|
-
while (1) {
|
|
83
|
-
switch (_context3.prev = _context3.next) {
|
|
84
|
-
case 0:
|
|
85
|
-
fp = function fp(f) {
|
|
86
|
-
return require.resolve('../data/volvox/' + f);
|
|
87
|
-
};
|
|
88
|
-
console.error = jest.fn();
|
|
89
|
-
_context3.next = 4;
|
|
90
|
-
return (0, _renderRegion.renderRegion)({
|
|
91
|
-
fasta: fp('volvox.fa'),
|
|
92
|
-
trackList: [['bam', [fp('volvox-sorted.bam')]], ['cram', [fp('volvox-sorted.cram')]], ['bigwig', [fp('volvox-sorted.bam.coverage.bw')]], ['vcfgz', [fp('volvox.filtered.vcf.gz')]], ['gffgz', [fp('volvox.sort.gff3.gz')]], ['bigbed', [fp('volvox.bb')]], ['bedgz', [fp('volvox-bed12.bed.gz')]]],
|
|
93
|
-
loc: 'ctgA:1000-2000'
|
|
94
|
-
});
|
|
95
|
-
case 4:
|
|
96
|
-
result = _context3.sent;
|
|
97
|
-
// can't do a snapshot test here, slightly inconsistent results(?)
|
|
98
|
-
_fs.default.writeFileSync(require.resolve('../test/svg_from_volvox_fasta_and_bam.svg'), result);
|
|
99
|
-
expect(result).toBeTruthy();
|
|
100
|
-
case 7:
|
|
101
|
-
case "end":
|
|
102
|
-
return _context3.stop();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}, _callee3);
|
|
106
|
-
})), timeout);
|
|
107
|
-
test('renders volvox with variety of args (noRasterize)', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
|
|
108
|
-
var fp, result;
|
|
109
|
-
return _regenerator.default.wrap(function _callee4$(_context4) {
|
|
110
|
-
while (1) {
|
|
111
|
-
switch (_context4.prev = _context4.next) {
|
|
112
|
-
case 0:
|
|
113
|
-
fp = function fp(f) {
|
|
114
|
-
return require.resolve('../data/volvox/' + f);
|
|
115
|
-
};
|
|
116
|
-
console.error = jest.fn();
|
|
117
|
-
_context4.next = 4;
|
|
118
|
-
return (0, _renderRegion.renderRegion)({
|
|
119
|
-
fasta: fp('volvox.fa'),
|
|
120
|
-
trackList: [['bam', [fp('volvox-sorted.bam')]], ['cram', [fp('volvox-sorted.cram')]], ['bigwig', [fp('volvox-sorted.bam.coverage.bw')]], ['vcfgz', [fp('volvox.filtered.vcf.gz')]], ['gffgz', [fp('volvox.sort.gff3.gz')]], ['bigbed', [fp('volvox.bb')]], ['bedgz', [fp('volvox-bed12.bed.gz')]]],
|
|
121
|
-
loc: 'ctgA:1000-2000',
|
|
122
|
-
noRasterize: true
|
|
123
|
-
});
|
|
124
|
-
case 4:
|
|
125
|
-
result = _context4.sent;
|
|
126
|
-
// can't do a snapshot test here, slightly inconsistent results(?)
|
|
127
|
-
_fs.default.writeFileSync(require.resolve('../test/svg_from_volvox_fasta_and_bam_norasterize.svg'), result);
|
|
128
|
-
expect(result).toBeTruthy();
|
|
129
|
-
case 7:
|
|
130
|
-
case "end":
|
|
131
|
-
return _context4.stop();
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}, _callee4);
|
|
135
|
-
})), timeout);
|
|
136
|
-
|
|
137
|
-
// commented out for using remote files currently
|
|
138
|
-
xtest('configtracks arg with urls', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5() {
|
|
139
|
-
var result;
|
|
140
|
-
return _regenerator.default.wrap(function _callee5$(_context5) {
|
|
141
|
-
while (1) {
|
|
142
|
-
switch (_context5.prev = _context5.next) {
|
|
143
|
-
case 0:
|
|
144
|
-
_context5.next = 2;
|
|
145
|
-
return (0, _renderRegion.renderRegion)({
|
|
146
|
-
config: 'data/config.json',
|
|
147
|
-
trackList: [['configtracks', ['ncbi_refseq_109_hg38']]],
|
|
148
|
-
assembly: 'GRCh38',
|
|
149
|
-
loc: 'chr1:50,000-60,000'
|
|
150
|
-
});
|
|
151
|
-
case 2:
|
|
152
|
-
result = _context5.sent;
|
|
153
|
-
// can't do a snapshot test here, slightly inconsistent results(?)
|
|
154
|
-
_fs.default.writeFileSync('svg_configtracks_simple.svg', result);
|
|
155
|
-
expect(result).toBeTruthy();
|
|
156
|
-
case 5:
|
|
157
|
-
case "end":
|
|
158
|
-
return _context5.stop();
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}, _callee5);
|
|
162
|
-
})), timeout * 3);
|
|
163
|
-
test('configtracks arg with local files', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6() {
|
|
164
|
-
var result;
|
|
165
|
-
return _regenerator.default.wrap(function _callee6$(_context6) {
|
|
166
|
-
while (1) {
|
|
167
|
-
switch (_context6.prev = _context6.next) {
|
|
168
|
-
case 0:
|
|
169
|
-
_context6.next = 2;
|
|
170
|
-
return (0, _renderRegion.renderRegion)({
|
|
171
|
-
config: require.resolve('../data/volvox/config.json'),
|
|
172
|
-
trackList: [['configtracks', ['volvox_sv']]],
|
|
173
|
-
assembly: 'volvox',
|
|
174
|
-
loc: 'ctgA:1-50,000'
|
|
175
|
-
});
|
|
176
|
-
case 2:
|
|
177
|
-
result = _context6.sent;
|
|
178
|
-
// can't do a snapshot test here, slightly inconsistent results(?)
|
|
179
|
-
_fs.default.writeFileSync(require.resolve('../test/svg_configtracks_local.svg'), result);
|
|
180
|
-
expect(result).toBeTruthy();
|
|
181
|
-
case 5:
|
|
182
|
-
case "end":
|
|
183
|
-
return _context6.stop();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}, _callee6);
|
|
187
|
-
})), timeout * 3);
|
|
188
|
-
xtest('renders --hic', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7() {
|
|
189
|
-
var result;
|
|
190
|
-
return _regenerator.default.wrap(function _callee7$(_context7) {
|
|
191
|
-
while (1) {
|
|
192
|
-
switch (_context7.prev = _context7.next) {
|
|
193
|
-
case 0:
|
|
194
|
-
_context7.next = 2;
|
|
195
|
-
return (0, _renderRegion.renderRegion)({
|
|
196
|
-
fasta: 'https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz',
|
|
197
|
-
trackList: [['hic', ['https://s3.amazonaws.com/igv.broadinstitute.org/data/hic/intra_nofrag_30.hic']]],
|
|
198
|
-
loc: '1:2,000,000-10,000,000'
|
|
199
|
-
});
|
|
200
|
-
case 2:
|
|
201
|
-
result = _context7.sent;
|
|
202
|
-
_fs.default.writeFileSync(require.resolve('../test/svg_from_human_hic.svg'), result);
|
|
203
|
-
expect(result).toBeTruthy();
|
|
204
|
-
case 5:
|
|
205
|
-
case "end":
|
|
206
|
-
return _context7.stop();
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}, _callee7);
|
|
210
|
-
})), 20000);
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _parseArgv = require("./parseArgv");
|
|
4
|
-
test('parse', function () {
|
|
5
|
-
var args = '--bam dad.bam color:red --vcf variants.vcf --bam mom.bam --defaultSession --out out.svg --noRasterize';
|
|
6
|
-
expect((0, _parseArgv.parseArgv)(args.split(' '))).toEqual([['bam', ['dad.bam', 'color:red']], ['vcf', ['variants.vcf']], ['bam', ['mom.bam']], ['defaultSession', []], ['out', ['out.svg']], ['noRasterize', []]]);
|
|
7
|
-
});
|