Skip to content

Commit 12f8d0d

Browse files
authored
Misc refactors for save track data (#5397)
1 parent 2ec5080 commit 12f8d0d

File tree

10 files changed

+124
-46
lines changed

10 files changed

+124
-46
lines changed

packages/core/src/pluggableElementTypes/models/BaseConnectionModelFactory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ function stateModelFactory(pluginManager: PluginManager) {
5151
* #action
5252
*/
5353
addTrackConfs(trackConfs: TrackConf[]) {
54-
self.tracks.push(...trackConfs)
54+
for (const trackConf of trackConfs) {
55+
self.tracks.push(trackConf)
56+
}
5557
},
5658
/**
5759
* #action

packages/core/src/pluggableElementTypes/models/components/SaveTrackData.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ const SaveTrackDataDialog = observer(function SaveTrackDataDialog({
9292
const { visibleRegions, coarseVisibleLocStrings: regionStr } = view
9393

9494
useEffect(() => {
95+
let cancelled = false
9596
// eslint-disable-next-line @typescript-eslint/no-floating-promises
9697
;(async () => {
9798
try {
@@ -125,27 +126,49 @@ const SaveTrackDataDialog = observer(function SaveTrackDataDialog({
125126
},
126127
)) as string | undefined
127128

129+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
130+
if (cancelled) {
131+
return
132+
}
128133
setUsedAdapterExport(true)
129134
setStr(exportResult ?? '')
130135
} else {
131136
const features = await fetchFeatures(model, regions)
137+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
138+
if (cancelled) {
139+
return
140+
}
132141
const result = await options[type]!.callback({
133142
features,
134143
session,
135144
assemblyName: regions[0]!.assemblyName,
136145
})
137146

147+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
148+
if (cancelled) {
149+
return
150+
}
138151
setUsedAdapterExport(false)
139152
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
140153
setStr(result ?? '')
141154
}
142155
} catch (e) {
143-
setError(e)
144-
console.error(e)
156+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
157+
if (!cancelled) {
158+
setError(e)
159+
console.error(e)
160+
}
145161
} finally {
146-
setLoading(false)
162+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
163+
if (!cancelled) {
164+
setLoading(false)
165+
}
147166
}
148167
})()
168+
169+
return () => {
170+
cancelled = true
171+
}
149172
}, [type, visibleRegions, options, model])
150173

151174
return (

packages/core/src/pluggableElementTypes/models/saveTrackFileTypes/bed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export function stringifyBED({ features }: { features: Feature[] }) {
55
return features
66
.map(feature =>
77
fields
8-
.map(field => feature.get(field))
8+
.map(field => feature.get(field) ?? '.')
99
.join('\t')
1010
.trim(),
1111
)

plugins/alignments/src/saveTrackFormats/sam.ts

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* optional tags. The output may not fully conform to the SAM specification and should be
77
* validated before use in production workflows.
88
*/
9-
import type { Feature } from '@jbrowse/core/util'
9+
import type { AbstractSessionModel, Feature } from '@jbrowse/core/util'
1010

1111
function qualToPhred(qual: string): string {
1212
if (!qual) {
@@ -19,38 +19,67 @@ function qualToPhred(qual: string): string {
1919
.join('')
2020
}
2121

22-
export function stringifySAM({ features }: { features: Feature[] }) {
23-
return features
24-
.map(feature => {
25-
const start = feature.get('start')
26-
// The 11 mandatory SAM fields (optional tags are not currently output)
27-
const fields = [
28-
// QNAME (query name)
29-
feature.get('name') || feature.get('id') || '*',
30-
// FLAG (bitwise flags) - 0 for unmapped/unknown
31-
feature.get('flag') ?? '0',
32-
// RNAME (reference sequence name)
33-
feature.get('refName') || '*',
34-
// POS (1-based leftmost mapping position)
35-
String(start + 1),
36-
// MAPQ (mapping quality)
37-
feature.get('mapq') ?? '255',
38-
// CIGAR (CIGAR string)
39-
feature.get('CIGAR') || '*',
40-
// RNEXT (reference sequence name of next read)
41-
feature.get('next_ref') || '*',
42-
// PNEXT (position of next read)
43-
feature.get('next_pos') ?? '0',
44-
// TLEN (template length)
45-
feature.get('template_len') ?? '0',
46-
// SEQ (sequence)
47-
feature.get('seq') || '*',
48-
// QUAL (quality in PHRED ASCII format)
49-
qualToPhred(feature.get('qual')),
50-
]
51-
// TODO: Add support for optional tags
52-
53-
return fields.join('\t')
54-
})
55-
.join('\n')
22+
export function stringifySAM({
23+
features,
24+
session,
25+
assemblyName,
26+
}: {
27+
features: Feature[]
28+
session: AbstractSessionModel
29+
assemblyName: string
30+
}) {
31+
const lines: string[] = ['@HD\tVN:1.6\tSO:unsorted']
32+
33+
// @HD header - SAM version
34+
35+
// @SQ headers - reference sequences
36+
const { assemblyManager } = session
37+
const assembly = assemblyManager.get(assemblyName)
38+
if (assembly) {
39+
const regions = assembly.regions
40+
if (regions) {
41+
for (const region of regions) {
42+
const length = region.end - region.start
43+
lines.push(`@SQ\tSN:${region.refName}\tLN:${length}`)
44+
}
45+
}
46+
}
47+
48+
// @PG header - program info
49+
lines.push('@PG\tID:jbrowse\tPN:JBrowse\tVN:2')
50+
51+
// Alignment records
52+
for (const feature of features) {
53+
const start = feature.get('start')
54+
// The 11 mandatory SAM fields (optional tags are not currently output)
55+
const fields = [
56+
// QNAME (query name)
57+
feature.get('name') || feature.get('id') || '*',
58+
// FLAG (bitwise flags) - 0 for unmapped/unknown
59+
feature.get('flag') ?? '0',
60+
// RNAME (reference sequence name)
61+
feature.get('refName') || '*',
62+
// POS (1-based leftmost mapping position)
63+
String(start + 1),
64+
// MAPQ (mapping quality)
65+
feature.get('mapq') ?? '255',
66+
// CIGAR (CIGAR string)
67+
feature.get('CIGAR') || '*',
68+
// RNEXT (reference sequence name of next read)
69+
feature.get('next_ref') || '*',
70+
// PNEXT (position of next read)
71+
feature.get('next_pos') ?? '0',
72+
// TLEN (template length)
73+
feature.get('template_len') ?? '0',
74+
// SEQ (sequence)
75+
feature.get('seq') || '*',
76+
// QUAL (quality in PHRED ASCII format)
77+
qualToPhred(feature.get('qual')),
78+
]
79+
// TODO: Add support for optional tags
80+
81+
lines.push(fields.join('\t'))
82+
}
83+
84+
return lines.join('\n')
5685
}

plugins/legacy-jbrowse/src/JBrowse1Connection/jb1ConfigParse.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,14 @@ export function regularizeConf(conf: Config, url: string): Config {
241241
// conf, if needed
242242
const addBase: (Track | Store | Names)[] = []
243243
if (conf.tracks) {
244-
addBase.push(...conf.tracks)
244+
for (const track of conf.tracks) {
245+
addBase.push(track)
246+
}
245247
}
246248
if (conf.stores) {
247-
addBase.push(...Object.values(conf.stores))
249+
for (const store of Object.values(conf.stores)) {
250+
addBase.push(store)
251+
}
248252
}
249253
if (conf.names) {
250254
addBase.push(conf.names)

plugins/rdf/src/SPARQLAdapter/SPARQLAdapter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,9 @@ export default class SPARQLAdapter extends BaseFeatureDataAdapter {
212212
break
213213
}
214214
if (subfeature.subfeatures) {
215-
subfeatures.push(...subfeature.subfeatures)
215+
for (const sf of subfeature.subfeatures) {
216+
subfeatures.push(sf)
217+
}
216218
}
217219
}
218220
if (!found) {

plugins/variants/src/VcfTabixAdapter/VcfTabixAdapter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ export default class VcfTabixAdapter extends BaseFeatureDataAdapter {
107107
}),
108108
)
109109

110-
exportLines.push(...regionLines)
110+
for (const line of regionLines) {
111+
exportLines.push(line)
112+
}
111113
}
112114

113115
return exportLines.join('\n')

products/jbrowse-web/src/tests/__file_snapshots__/save_track_data.cram.sam

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
@HD VN:1.6 SO:unsorted
2+
@SQ SN:ctgA LN:50001
3+
@SQ SN:ctgB LN:6079
4+
@PG ID:jbrowse PN:JBrowse VN:2
15
ctgA_4231_4700_3:0:0_0:0:0_119d 0 ctgA 4231 255 100M * 0 0 CTGGTTGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGAGGTTGGAAGCGAGTACCGGTTAAGGGAAGTCACGTTAACCCAACATAGTGAGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
26
ctgA_4236_4755_0:0:0_0:0:0_1567 0 ctgA 4236 255 100M * 0 0 TGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
37
ctgA_4239_4750_1:0:0_3:0:0_d21 0 ctgA 4239 255 100M * 0 0 CACTTTGCATAACCCACCACGAAAACCCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGCTTA 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

products/jbrowse-web/src/tests/__file_snapshots__/save_track_data.sam

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
@HD VN:1.6 SO:unsorted
2+
@SQ SN:ctgA LN:50001
3+
@SQ SN:ctgB LN:6079
4+
@PG ID:jbrowse PN:JBrowse VN:2
15
ctgA_4231_4700_3:0:0_0:0:0_119d 0 ctgA 4231 255 100M * -1 0 CTGGTTGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGAGGTTGGAAGCGAGTACCGGTTAAGGGAAGTCACGTTAACCCAACATAGTGAGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
26
ctgA_4236_4755_0:0:0_0:0:0_1567 0 ctgA 4236 255 100M * -1 0 TGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
37
ctgA_4239_4750_1:0:0_3:0:0_d21 0 ctgA 4239 255 100M * -1 0 CACTTTGCATAACCCACCACGAAAACCCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGCTTA 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

products/jbrowse-web/src/tests/__snapshots__/SaveTrackData.test.tsx.snap

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
22

33
exports[`save track data for BAM track 1`] = `
4-
"ctgA_4231_4700_3:0:0_0:0:0_119d 0 ctgA 4231 255 100M * -1 0 CTGGTTGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGAGGTTGGAAGCGAGTACCGGTTAAGGGAAGTCACGTTAACCCAACATAGTGAGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
4+
"@HD VN:1.6 SO:unsorted
5+
@SQ SN:ctgA LN:50001
6+
@SQ SN:ctgB LN:6079
7+
@PG ID:jbrowse PN:JBrowse VN:2
8+
ctgA_4231_4700_3:0:0_0:0:0_119d 0 ctgA 4231 255 100M * -1 0 CTGGTTGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGAGGTTGGAAGCGAGTACCGGTTAAGGGAAGTCACGTTAACCCAACATAGTGAGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
59
ctgA_4236_4755_0:0:0_0:0:0_1567 0 ctgA 4236 255 100M * -1 0 TGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
610
ctgA_4239_4750_1:0:0_3:0:0_d21 0 ctgA 4239 255 100M * -1 0 CACTTTGCATAACCCACCACGAAAACCCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGCTTA 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
711
ctgA_3775_4342_0:0:1_4:0:0_25cd 0 ctgA 4243 255 100M * -1 0 TTGCATAACCCACCACGAAAACGCGGTTTGCACGTGGTTGCAAGCGAGTACCGATTAAGGGACGTTACGTAAACCCAACATTGTGAGCGATGCTTAAAAC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
@@ -78,7 +82,11 @@ ctgA 4400 4500 299"
7882
`;
7983

8084
exports[`save track data for CRAM track 1`] = `
81-
"ctgA_4231_4700_3:0:0_0:0:0_119d 0 ctgA 4231 255 100M * 0 0 CTGGTTGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGAGGTTGGAAGCGAGTACCGGTTAAGGGAAGTCACGTTAACCCAACATAGTGAGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
85+
"@HD VN:1.6 SO:unsorted
86+
@SQ SN:ctgA LN:50001
87+
@SQ SN:ctgB LN:6079
88+
@PG ID:jbrowse PN:JBrowse VN:2
89+
ctgA_4231_4700_3:0:0_0:0:0_119d 0 ctgA 4231 255 100M * 0 0 CTGGTTGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGAGGTTGGAAGCGAGTACCGGTTAAGGGAAGTCACGTTAACCCAACATAGTGAGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
8290
ctgA_4236_4755_0:0:0_0:0:0_1567 0 ctgA 4236 255 100M * 0 0 TGACACTTTGCATAACCCACCACGAAAACGCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
8391
ctgA_4239_4750_1:0:0_3:0:0_d21 0 ctgA 4239 255 100M * 0 0 CACTTTGCATAACCCACCACGAAAACCCGGTTTGCACGTGGTTGGAAGCGAGTACCGGTTAAGGGAAGTTACGTAAACCCAACATAGTGAGCGATGCTTA 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
8492
ctgA_3775_4342_0:0:1_4:0:0_25cd 0 ctgA 4243 255 100M * 0 0 TTGCATAACCCACCACGAAAACGCGGTTTGCACGTGGTTGCAAGCGAGTACCGATTAAGGGACGTTACGTAAACCCAACATTGTGAGCGATGCTTAAAAC 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

0 commit comments

Comments
 (0)