@jbrowse/plugin-variants 2.6.1 → 2.6.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/dist/ChordVariantDisplay/index.js +0 -1
- package/dist/ChordVariantDisplay/models/configSchema.js +0 -1
- package/dist/ChordVariantDisplay/models/stateModelFactory.js +0 -1
- package/dist/LinearVariantDisplay/configSchema.js +0 -1
- package/dist/LinearVariantDisplay/index.js +0 -1
- package/dist/LinearVariantDisplay/model.js +0 -1
- package/dist/StructuralVariantChordRenderer/Chord.js +0 -1
- package/dist/StructuralVariantChordRenderer/ReactComponent.js +0 -1
- package/dist/StructuralVariantChordRenderer/configSchema.js +0 -1
- package/dist/StructuralVariantChordRenderer/index.js +0 -1
- package/dist/VariantFeatureWidget/AnnotGrid.js +0 -1
- package/dist/VariantFeatureWidget/BreakendOptionDialog.js +0 -1
- package/dist/VariantFeatureWidget/BreakendPanel.js +0 -1
- package/dist/VariantFeatureWidget/VariantAnnotationTable.js +0 -1
- package/dist/VariantFeatureWidget/VariantFeatureWidget.js +0 -1
- package/dist/VariantFeatureWidget/VariantSampleGrid.js +0 -1
- package/dist/VariantFeatureWidget/index.js +0 -1
- package/dist/VariantTrack/configSchema.js +0 -1
- package/dist/VariantTrack/index.js +0 -1
- package/dist/VcfAdapter/VcfAdapter.js +0 -1
- package/dist/VcfAdapter/configSchema.js +0 -1
- package/dist/VcfAdapter/index.js +0 -1
- package/dist/VcfFeature/index.js +2 -2
- package/dist/VcfFeature/util.js +0 -1
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js +0 -1
- package/dist/VcfTabixAdapter/configSchema.js +0 -1
- package/dist/VcfTabixAdapter/index.js +0 -1
- package/dist/extensionPoints.js +0 -1
- package/dist/index.js +0 -1
- package/esm/ChordVariantDisplay/index.js +0 -1
- package/esm/ChordVariantDisplay/models/configSchema.js +0 -1
- package/esm/ChordVariantDisplay/models/stateModelFactory.js +0 -1
- package/esm/LinearVariantDisplay/configSchema.js +0 -1
- package/esm/LinearVariantDisplay/index.js +0 -1
- package/esm/LinearVariantDisplay/model.js +0 -1
- package/esm/StructuralVariantChordRenderer/Chord.js +0 -1
- package/esm/StructuralVariantChordRenderer/ReactComponent.js +0 -1
- package/esm/StructuralVariantChordRenderer/configSchema.js +0 -1
- package/esm/StructuralVariantChordRenderer/index.js +0 -1
- package/esm/VariantFeatureWidget/AnnotGrid.js +0 -1
- package/esm/VariantFeatureWidget/BreakendOptionDialog.js +0 -1
- package/esm/VariantFeatureWidget/BreakendPanel.js +0 -1
- package/esm/VariantFeatureWidget/VariantAnnotationTable.js +0 -1
- package/esm/VariantFeatureWidget/VariantFeatureWidget.js +0 -1
- package/esm/VariantFeatureWidget/VariantSampleGrid.js +0 -1
- package/esm/VariantFeatureWidget/index.js +0 -1
- package/esm/VariantTrack/configSchema.js +0 -1
- package/esm/VariantTrack/index.js +0 -1
- package/esm/VcfAdapter/VcfAdapter.js +0 -1
- package/esm/VcfAdapter/configSchema.js +0 -1
- package/esm/VcfAdapter/index.js +0 -1
- package/esm/VcfFeature/index.js +2 -2
- package/esm/VcfFeature/util.js +0 -1
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js +0 -1
- package/esm/VcfTabixAdapter/configSchema.js +0 -1
- package/esm/VcfTabixAdapter/index.js +0 -1
- package/esm/extensionPoints.js +0 -1
- package/esm/index.js +0 -1
- package/package.json +3 -4
- package/dist/ChordVariantDisplay/index.js.map +0 -1
- package/dist/ChordVariantDisplay/models/configSchema.js.map +0 -1
- package/dist/ChordVariantDisplay/models/stateModelFactory.js.map +0 -1
- package/dist/LinearVariantDisplay/configSchema.js.map +0 -1
- package/dist/LinearVariantDisplay/index.js.map +0 -1
- package/dist/LinearVariantDisplay/model.js.map +0 -1
- package/dist/StructuralVariantChordRenderer/Chord.js.map +0 -1
- package/dist/StructuralVariantChordRenderer/ReactComponent.js.map +0 -1
- package/dist/StructuralVariantChordRenderer/configSchema.js.map +0 -1
- package/dist/StructuralVariantChordRenderer/index.js.map +0 -1
- package/dist/VariantFeatureWidget/AnnotGrid.js.map +0 -1
- package/dist/VariantFeatureWidget/BreakendOptionDialog.js.map +0 -1
- package/dist/VariantFeatureWidget/BreakendPanel.js.map +0 -1
- package/dist/VariantFeatureWidget/VariantAnnotationTable.js.map +0 -1
- package/dist/VariantFeatureWidget/VariantFeatureWidget.js.map +0 -1
- package/dist/VariantFeatureWidget/VariantSampleGrid.js.map +0 -1
- package/dist/VariantFeatureWidget/index.js.map +0 -1
- package/dist/VariantTrack/configSchema.js.map +0 -1
- package/dist/VariantTrack/index.js.map +0 -1
- package/dist/VcfAdapter/VcfAdapter.js.map +0 -1
- package/dist/VcfAdapter/configSchema.js.map +0 -1
- package/dist/VcfAdapter/index.js.map +0 -1
- package/dist/VcfFeature/index.js.map +0 -1
- package/dist/VcfFeature/util.js.map +0 -1
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js.map +0 -1
- package/dist/VcfTabixAdapter/configSchema.js.map +0 -1
- package/dist/VcfTabixAdapter/index.js.map +0 -1
- package/dist/extensionPoints.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/esm/ChordVariantDisplay/index.js.map +0 -1
- package/esm/ChordVariantDisplay/models/configSchema.js.map +0 -1
- package/esm/ChordVariantDisplay/models/stateModelFactory.js.map +0 -1
- package/esm/LinearVariantDisplay/configSchema.js.map +0 -1
- package/esm/LinearVariantDisplay/index.js.map +0 -1
- package/esm/LinearVariantDisplay/model.js.map +0 -1
- package/esm/StructuralVariantChordRenderer/Chord.js.map +0 -1
- package/esm/StructuralVariantChordRenderer/ReactComponent.js.map +0 -1
- package/esm/StructuralVariantChordRenderer/configSchema.js.map +0 -1
- package/esm/StructuralVariantChordRenderer/index.js.map +0 -1
- package/esm/VariantFeatureWidget/AnnotGrid.js.map +0 -1
- package/esm/VariantFeatureWidget/BreakendOptionDialog.js.map +0 -1
- package/esm/VariantFeatureWidget/BreakendPanel.js.map +0 -1
- package/esm/VariantFeatureWidget/VariantAnnotationTable.js.map +0 -1
- package/esm/VariantFeatureWidget/VariantFeatureWidget.js.map +0 -1
- package/esm/VariantFeatureWidget/VariantSampleGrid.js.map +0 -1
- package/esm/VariantFeatureWidget/index.js.map +0 -1
- package/esm/VariantTrack/configSchema.js.map +0 -1
- package/esm/VariantTrack/index.js.map +0 -1
- package/esm/VcfAdapter/VcfAdapter.js.map +0 -1
- package/esm/VcfAdapter/configSchema.js.map +0 -1
- package/esm/VcfAdapter/index.js.map +0 -1
- package/esm/VcfFeature/index.js.map +0 -1
- package/esm/VcfFeature/util.js.map +0 -1
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js.map +0 -1
- package/esm/VcfTabixAdapter/configSchema.js.map +0 -1
- package/esm/VcfTabixAdapter/index.js.map +0 -1
- package/esm/extensionPoints.js.map +0 -1
- package/esm/index.js.map +0 -1
- package/src/ChordVariantDisplay/index.ts +0 -23
- package/src/ChordVariantDisplay/models/configSchema.ts +0 -33
- package/src/ChordVariantDisplay/models/stateModelFactory.ts +0 -63
- package/src/LinearVariantDisplay/configSchema.ts +0 -30
- package/src/LinearVariantDisplay/index.ts +0 -20
- package/src/LinearVariantDisplay/model.ts +0 -76
- package/src/StructuralVariantChordRenderer/Chord.tsx +0 -141
- package/src/StructuralVariantChordRenderer/ReactComponent.tsx +0 -78
- package/src/StructuralVariantChordRenderer/configSchema.ts +0 -42
- package/src/StructuralVariantChordRenderer/index.ts +0 -17
- package/src/VariantFeatureWidget/AnnotGrid.tsx +0 -51
- package/src/VariantFeatureWidget/BreakendOptionDialog.tsx +0 -117
- package/src/VariantFeatureWidget/BreakendPanel.tsx +0 -93
- package/src/VariantFeatureWidget/VariantAnnotationTable.tsx +0 -27
- package/src/VariantFeatureWidget/VariantFeatureWidget.test.tsx +0 -42
- package/src/VariantFeatureWidget/VariantFeatureWidget.tsx +0 -112
- package/src/VariantFeatureWidget/VariantSampleGrid.tsx +0 -151
- package/src/VariantFeatureWidget/__snapshots__/VariantFeatureWidget.test.tsx.snap +0 -244
- package/src/VariantFeatureWidget/index.ts +0 -32
- package/src/VariantTrack/configSchema.ts +0 -24
- package/src/VariantTrack/index.ts +0 -16
- package/src/VcfAdapter/VcfAdapter.test.ts +0 -28
- package/src/VcfAdapter/VcfAdapter.ts +0 -125
- package/src/VcfAdapter/__snapshots__/VcfAdapter.test.ts.snap +0 -325
- package/src/VcfAdapter/configSchema.ts +0 -22
- package/src/VcfAdapter/index.ts +0 -15
- package/src/VcfAdapter/test_data/volvox.filtered.vcf +0 -73
- package/src/VcfFeature/index.test.ts +0 -132
- package/src/VcfFeature/index.ts +0 -104
- package/src/VcfFeature/util.ts +0 -138
- package/src/VcfTabixAdapter/VcfTabixAdapter.test.ts +0 -69
- package/src/VcfTabixAdapter/VcfTabixAdapter.ts +0 -90
- package/src/VcfTabixAdapter/__snapshots__/VcfTabixAdapter.test.ts.snap +0 -325
- package/src/VcfTabixAdapter/configSchema.ts +0 -43
- package/src/VcfTabixAdapter/index.ts +0 -17
- package/src/VcfTabixAdapter/test_data/volvox.filtered.vcf.gz +0 -0
- package/src/VcfTabixAdapter/test_data/volvox.filtered.vcf.gz.csi +0 -0
- package/src/VcfTabixAdapter/test_data/volvox.filtered.vcf.gz.tbi +0 -0
- package/src/__snapshots__/index.test.ts.snap +0 -20
- package/src/extensionPoints.ts +0 -74
- package/src/index.test.ts +0 -32
- package/src/index.ts +0 -27
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
FormControlLabel,
|
|
5
|
-
Checkbox,
|
|
6
|
-
TextField,
|
|
7
|
-
Typography,
|
|
8
|
-
} from '@mui/material'
|
|
9
|
-
|
|
10
|
-
import { DataGrid, GridToolbar } from '@mui/x-data-grid'
|
|
11
|
-
import { BaseCard } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
12
|
-
import { measureGridWidth, SimpleFeatureSerialized } from '@jbrowse/core/util'
|
|
13
|
-
import ResizeBar, { useResizeBar } from '@jbrowse/core/ui/ResizeBar'
|
|
14
|
-
|
|
15
|
-
interface Entry {
|
|
16
|
-
sample: string
|
|
17
|
-
id: string
|
|
18
|
-
[key: string]: string
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type InfoFields = Record<string, unknown>
|
|
22
|
-
type Filters = Record<string, string>
|
|
23
|
-
|
|
24
|
-
function SampleFilters({
|
|
25
|
-
columns,
|
|
26
|
-
filter,
|
|
27
|
-
setFilter,
|
|
28
|
-
}: {
|
|
29
|
-
columns: { field: string }[]
|
|
30
|
-
filter: Filters
|
|
31
|
-
setFilter: (arg: Filters) => void
|
|
32
|
-
}) {
|
|
33
|
-
return (
|
|
34
|
-
<>
|
|
35
|
-
<Typography>
|
|
36
|
-
These filters can use a plain text search or regex style query, e.g. in
|
|
37
|
-
the genotype field, entering 1 will query for all genotypes that include
|
|
38
|
-
the first alternate allele e.g. 0|1 or 1|1, entering [1-9]\d* will find
|
|
39
|
-
any non-zero allele e.g. 0|2 or 2/33
|
|
40
|
-
</Typography>
|
|
41
|
-
{columns.map(({ field }) => (
|
|
42
|
-
<TextField
|
|
43
|
-
key={`filter-${field}`}
|
|
44
|
-
placeholder={`Filter ${field}`}
|
|
45
|
-
value={filter[field] || ''}
|
|
46
|
-
onChange={event =>
|
|
47
|
-
setFilter({ ...filter, [field]: event.target.value })
|
|
48
|
-
}
|
|
49
|
-
/>
|
|
50
|
-
))}
|
|
51
|
-
</>
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export default function VariantSamples(props: {
|
|
56
|
-
feature: SimpleFeatureSerialized
|
|
57
|
-
descriptions: { FORMAT?: { [key: string]: { Description?: string } } }
|
|
58
|
-
}) {
|
|
59
|
-
const { feature, descriptions = {} } = props
|
|
60
|
-
const { ref, scrollLeft } = useResizeBar()
|
|
61
|
-
const [filter, setFilter] = useState<Filters>({})
|
|
62
|
-
const samples = (feature.samples || {}) as Record<string, InfoFields>
|
|
63
|
-
const preFilteredRows = Object.entries(samples)
|
|
64
|
-
|
|
65
|
-
let error
|
|
66
|
-
let rows = [] as Entry[]
|
|
67
|
-
const filters = Object.keys(filter)
|
|
68
|
-
|
|
69
|
-
// catch some error thrown from regex
|
|
70
|
-
// note: maps all values into a string, if this is not done rows are not
|
|
71
|
-
// sortable by the data-grid
|
|
72
|
-
try {
|
|
73
|
-
rows = preFilteredRows
|
|
74
|
-
.map(row => {
|
|
75
|
-
return {
|
|
76
|
-
...Object.fromEntries(
|
|
77
|
-
Object.entries(row[1]).map(e => [e[0], `${e[1]}`]),
|
|
78
|
-
),
|
|
79
|
-
sample: row[0],
|
|
80
|
-
id: row[0],
|
|
81
|
-
} as Entry
|
|
82
|
-
})
|
|
83
|
-
.filter(row =>
|
|
84
|
-
filters.length
|
|
85
|
-
? filters.every(key => {
|
|
86
|
-
const currFilter = filter[key]
|
|
87
|
-
return currFilter
|
|
88
|
-
? row[key].match(new RegExp(currFilter, 'i'))
|
|
89
|
-
: true
|
|
90
|
-
})
|
|
91
|
-
: true,
|
|
92
|
-
)
|
|
93
|
-
} catch (e) {
|
|
94
|
-
error = e
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const keys = ['sample', ...Object.keys(preFilteredRows[0]?.[1] || {})]
|
|
98
|
-
const [checked, setChecked] = useState(false)
|
|
99
|
-
const [widths, setWidths] = useState(
|
|
100
|
-
keys.map(e => measureGridWidth(rows.map(r => r[e]))),
|
|
101
|
-
)
|
|
102
|
-
const columns = keys.map((field, index) => ({
|
|
103
|
-
field,
|
|
104
|
-
description: descriptions.FORMAT?.[field]?.Description,
|
|
105
|
-
width: widths[index],
|
|
106
|
-
}))
|
|
107
|
-
|
|
108
|
-
// disableRowSelectionOnClick helps avoid
|
|
109
|
-
// https://github.com/mui-org/material-ui-x/issues/1197
|
|
110
|
-
return !preFilteredRows.length ? null : (
|
|
111
|
-
<BaseCard {...props} title="Samples">
|
|
112
|
-
{error ? <Typography color="error">{`${error}`}</Typography> : null}
|
|
113
|
-
<FormControlLabel
|
|
114
|
-
control={
|
|
115
|
-
<Checkbox
|
|
116
|
-
checked={checked}
|
|
117
|
-
onChange={event => setChecked(event.target.checked)}
|
|
118
|
-
/>
|
|
119
|
-
}
|
|
120
|
-
label={<Typography variant="body2">Show options</Typography>}
|
|
121
|
-
/>
|
|
122
|
-
{checked ? (
|
|
123
|
-
<SampleFilters
|
|
124
|
-
setFilter={setFilter}
|
|
125
|
-
columns={columns}
|
|
126
|
-
filter={filter}
|
|
127
|
-
/>
|
|
128
|
-
) : null}
|
|
129
|
-
<div ref={ref}>
|
|
130
|
-
<ResizeBar
|
|
131
|
-
widths={widths}
|
|
132
|
-
setWidths={setWidths}
|
|
133
|
-
scrollLeft={scrollLeft}
|
|
134
|
-
/>
|
|
135
|
-
<DataGrid
|
|
136
|
-
rows={rows}
|
|
137
|
-
hideFooter={rows.length < 100}
|
|
138
|
-
columns={columns}
|
|
139
|
-
disableRowSelectionOnClick
|
|
140
|
-
rowHeight={25}
|
|
141
|
-
columnHeaderHeight={35}
|
|
142
|
-
disableColumnMenu
|
|
143
|
-
slots={{ toolbar: checked ? GridToolbar : null }}
|
|
144
|
-
slotProps={{
|
|
145
|
-
toolbar: { printOptions: { disableToolbarButton: true } },
|
|
146
|
-
}}
|
|
147
|
-
/>
|
|
148
|
-
</div>
|
|
149
|
-
</BaseCard>
|
|
150
|
-
)
|
|
151
|
-
}
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`renders with just the required model elements 1`] = `
|
|
4
|
-
<div
|
|
5
|
-
class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-1ps6pg7-MuiPaper-root"
|
|
6
|
-
data-testid="variant-side-drawer"
|
|
7
|
-
>
|
|
8
|
-
<div
|
|
9
|
-
class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 MuiAccordion-root MuiAccordion-rounded Mui-expanded MuiAccordion-gutters css-1elwnq4-MuiPaper-root-MuiAccordion-root"
|
|
10
|
-
>
|
|
11
|
-
<div
|
|
12
|
-
aria-expanded="true"
|
|
13
|
-
class="MuiButtonBase-root MuiAccordionSummary-root Mui-expanded MuiAccordionSummary-gutters css-sh22l5-MuiButtonBase-root-MuiAccordionSummary-root"
|
|
14
|
-
role="button"
|
|
15
|
-
tabindex="0"
|
|
16
|
-
>
|
|
17
|
-
<div
|
|
18
|
-
class="MuiAccordionSummary-content Mui-expanded MuiAccordionSummary-contentGutters css-o4b71y-MuiAccordionSummary-content"
|
|
19
|
-
>
|
|
20
|
-
<span
|
|
21
|
-
class="MuiTypography-root MuiTypography-button css-1f0on15-MuiTypography-root"
|
|
22
|
-
>
|
|
23
|
-
|
|
24
|
-
rs123
|
|
25
|
-
</span>
|
|
26
|
-
</div>
|
|
27
|
-
<div
|
|
28
|
-
class="MuiAccordionSummary-expandIconWrapper Mui-expanded css-yw020d-MuiAccordionSummary-expandIconWrapper"
|
|
29
|
-
>
|
|
30
|
-
<svg
|
|
31
|
-
aria-hidden="true"
|
|
32
|
-
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-ymsoo8-MuiSvgIcon-root-expandIcon"
|
|
33
|
-
data-testid="ExpandMoreIcon"
|
|
34
|
-
focusable="false"
|
|
35
|
-
viewBox="0 0 24 24"
|
|
36
|
-
>
|
|
37
|
-
<path
|
|
38
|
-
d="M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z"
|
|
39
|
-
/>
|
|
40
|
-
</svg>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
<div
|
|
44
|
-
class="MuiCollapse-root MuiCollapse-vertical MuiCollapse-entered css-pwcg7p-MuiCollapse-root"
|
|
45
|
-
style="min-height: 0px;"
|
|
46
|
-
>
|
|
47
|
-
<div
|
|
48
|
-
class="MuiCollapse-wrapper MuiCollapse-vertical css-smkl36-MuiCollapse-wrapper"
|
|
49
|
-
>
|
|
50
|
-
<div
|
|
51
|
-
class="MuiCollapse-wrapperInner MuiCollapse-vertical css-9l5vo-MuiCollapse-wrapperInner"
|
|
52
|
-
>
|
|
53
|
-
<div
|
|
54
|
-
class="MuiAccordion-region"
|
|
55
|
-
role="region"
|
|
56
|
-
>
|
|
57
|
-
<div
|
|
58
|
-
class="MuiAccordionDetails-root css-rqrb7m-MuiAccordionDetails-root-expansionPanelDetails"
|
|
59
|
-
>
|
|
60
|
-
<p
|
|
61
|
-
class="MuiTypography-root MuiTypography-body1 css-ahj2mt-MuiTypography-root"
|
|
62
|
-
>
|
|
63
|
-
Core details
|
|
64
|
-
</p>
|
|
65
|
-
<div
|
|
66
|
-
class="css-1m8nxnb-field"
|
|
67
|
-
>
|
|
68
|
-
<div
|
|
69
|
-
class="css-1q83rf3-fieldName"
|
|
70
|
-
>
|
|
71
|
-
Position
|
|
72
|
-
</div>
|
|
73
|
-
<div
|
|
74
|
-
class="css-1omt041-fieldValue"
|
|
75
|
-
>
|
|
76
|
-
ctgA:177
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
<div
|
|
80
|
-
class="css-1m8nxnb-field"
|
|
81
|
-
>
|
|
82
|
-
<div
|
|
83
|
-
class="css-1q83rf3-fieldName"
|
|
84
|
-
>
|
|
85
|
-
Name
|
|
86
|
-
</div>
|
|
87
|
-
<div
|
|
88
|
-
class="css-1omt041-fieldValue"
|
|
89
|
-
>
|
|
90
|
-
<span>
|
|
91
|
-
rs123
|
|
92
|
-
</span>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
<div
|
|
96
|
-
class="css-1m8nxnb-field"
|
|
97
|
-
>
|
|
98
|
-
<div
|
|
99
|
-
class="css-1q83rf3-fieldName"
|
|
100
|
-
>
|
|
101
|
-
Length
|
|
102
|
-
</div>
|
|
103
|
-
<div
|
|
104
|
-
class="css-1omt041-fieldValue"
|
|
105
|
-
>
|
|
106
|
-
<span>
|
|
107
|
-
1
|
|
108
|
-
</span>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
<hr
|
|
112
|
-
class="MuiDivider-root MuiDivider-fullWidth css-9mgopn-MuiDivider-root"
|
|
113
|
-
/>
|
|
114
|
-
<p
|
|
115
|
-
class="MuiTypography-root MuiTypography-body1 css-ahj2mt-MuiTypography-root"
|
|
116
|
-
>
|
|
117
|
-
Attributes
|
|
118
|
-
</p>
|
|
119
|
-
<div
|
|
120
|
-
class="css-1m8nxnb-field"
|
|
121
|
-
>
|
|
122
|
-
<div
|
|
123
|
-
aria-label="reference base(s): Each base must be one of A,C,G,T,N (case insensitive)."
|
|
124
|
-
class="css-18vnxxj-fieldDescription-fieldName"
|
|
125
|
-
data-mui-internal-clone-element="true"
|
|
126
|
-
>
|
|
127
|
-
REF
|
|
128
|
-
</div>
|
|
129
|
-
<div
|
|
130
|
-
class="css-1omt041-fieldValue"
|
|
131
|
-
>
|
|
132
|
-
<span>
|
|
133
|
-
A
|
|
134
|
-
</span>
|
|
135
|
-
</div>
|
|
136
|
-
</div>
|
|
137
|
-
<div
|
|
138
|
-
class="css-1m8nxnb-field"
|
|
139
|
-
>
|
|
140
|
-
<div
|
|
141
|
-
aria-label="alternate base(s): Comma-separated list of alternate non-reference alleles"
|
|
142
|
-
class="css-18vnxxj-fieldDescription-fieldName"
|
|
143
|
-
data-mui-internal-clone-element="true"
|
|
144
|
-
>
|
|
145
|
-
ALT
|
|
146
|
-
</div>
|
|
147
|
-
<div
|
|
148
|
-
class="css-1omt041-fieldValue"
|
|
149
|
-
>
|
|
150
|
-
<span>
|
|
151
|
-
<TRA>
|
|
152
|
-
</span>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
<div
|
|
156
|
-
class="css-1m8nxnb-field"
|
|
157
|
-
>
|
|
158
|
-
<div
|
|
159
|
-
aria-label="quality: Phred-scaled quality score for the assertion made in ALT"
|
|
160
|
-
class="css-18vnxxj-fieldDescription-fieldName"
|
|
161
|
-
data-mui-internal-clone-element="true"
|
|
162
|
-
>
|
|
163
|
-
QUAL
|
|
164
|
-
</div>
|
|
165
|
-
<div
|
|
166
|
-
class="css-1omt041-fieldValue"
|
|
167
|
-
>
|
|
168
|
-
<span>
|
|
169
|
-
10.4
|
|
170
|
-
</span>
|
|
171
|
-
</div>
|
|
172
|
-
</div>
|
|
173
|
-
<div
|
|
174
|
-
class="css-1m8nxnb-field"
|
|
175
|
-
>
|
|
176
|
-
<div
|
|
177
|
-
class="css-1q83rf3-fieldName"
|
|
178
|
-
style="width: 62px;"
|
|
179
|
-
>
|
|
180
|
-
INFO.MQ
|
|
181
|
-
</div>
|
|
182
|
-
<div
|
|
183
|
-
class="css-1omt041-fieldValue"
|
|
184
|
-
>
|
|
185
|
-
<span>
|
|
186
|
-
5
|
|
187
|
-
</span>
|
|
188
|
-
</div>
|
|
189
|
-
</div>
|
|
190
|
-
<div
|
|
191
|
-
class="css-1lttu3w-container"
|
|
192
|
-
>
|
|
193
|
-
<button
|
|
194
|
-
class="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium css-sghohy-MuiButtonBase-root-MuiButton-root"
|
|
195
|
-
tabindex="0"
|
|
196
|
-
type="button"
|
|
197
|
-
>
|
|
198
|
-
Show feature sequence
|
|
199
|
-
<span
|
|
200
|
-
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
|
|
201
|
-
/>
|
|
202
|
-
</button>
|
|
203
|
-
<div
|
|
204
|
-
class="MuiFormControl-root css-147opmv-MuiFormControl-root-formControl"
|
|
205
|
-
>
|
|
206
|
-
<button
|
|
207
|
-
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium css-78trlr-MuiButtonBase-root-MuiIconButton-root"
|
|
208
|
-
tabindex="0"
|
|
209
|
-
type="button"
|
|
210
|
-
>
|
|
211
|
-
<svg
|
|
212
|
-
aria-hidden="true"
|
|
213
|
-
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
|
|
214
|
-
data-testid="HelpIcon"
|
|
215
|
-
focusable="false"
|
|
216
|
-
viewBox="0 0 24 24"
|
|
217
|
-
>
|
|
218
|
-
<path
|
|
219
|
-
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"
|
|
220
|
-
/>
|
|
221
|
-
</svg>
|
|
222
|
-
<span
|
|
223
|
-
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
|
|
224
|
-
/>
|
|
225
|
-
</button>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
</div>
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
</div>
|
|
234
|
-
<hr
|
|
235
|
-
class="MuiDivider-root MuiDivider-fullWidth css-9mgopn-MuiDivider-root"
|
|
236
|
-
/>
|
|
237
|
-
<hr
|
|
238
|
-
class="MuiDivider-root MuiDivider-fullWidth css-9mgopn-MuiDivider-root"
|
|
239
|
-
/>
|
|
240
|
-
<hr
|
|
241
|
-
class="MuiDivider-root MuiDivider-fullWidth css-9mgopn-MuiDivider-root"
|
|
242
|
-
/>
|
|
243
|
-
</div>
|
|
244
|
-
`;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { lazy } from 'react'
|
|
2
|
-
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
3
|
-
import WidgetType from '@jbrowse/core/pluggableElementTypes/WidgetType'
|
|
4
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
5
|
-
import { types } from 'mobx-state-tree'
|
|
6
|
-
import { stateModelFactory as baseModelFactory } from '@jbrowse/core/BaseFeatureWidget'
|
|
7
|
-
|
|
8
|
-
export const configSchema = ConfigurationSchema('VariantFeatureWidget', {})
|
|
9
|
-
|
|
10
|
-
export function stateModelFactory(pluginManager: PluginManager) {
|
|
11
|
-
const baseModel = baseModelFactory(pluginManager)
|
|
12
|
-
return types.compose(
|
|
13
|
-
baseModel,
|
|
14
|
-
types.model('VariantFeatureWidget', {
|
|
15
|
-
type: types.literal('VariantFeatureWidget'),
|
|
16
|
-
descriptions: types.frozen(),
|
|
17
|
-
}),
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default (pluginManager: PluginManager) => {
|
|
22
|
-
pluginManager.addWidgetType(
|
|
23
|
-
() =>
|
|
24
|
-
new WidgetType({
|
|
25
|
-
name: 'VariantFeatureWidget',
|
|
26
|
-
heading: 'Feature details',
|
|
27
|
-
configSchema,
|
|
28
|
-
stateModel: stateModelFactory(pluginManager),
|
|
29
|
-
ReactComponent: lazy(() => import('./VariantFeatureWidget')),
|
|
30
|
-
}),
|
|
31
|
-
)
|
|
32
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
2
|
-
import { createBaseTrackConfig } from '@jbrowse/core/pluggableElementTypes'
|
|
3
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* #config VariantTrack
|
|
7
|
-
* Mostly similar to feature track, but has `ChordDisplayType` registered to it,
|
|
8
|
-
* and custom feature details in `LinearVariantDisplay`
|
|
9
|
-
*/
|
|
10
|
-
function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
11
|
-
|
|
12
|
-
const configSchema = (pluginManager: PluginManager) =>
|
|
13
|
-
ConfigurationSchema(
|
|
14
|
-
'VariantTrack',
|
|
15
|
-
{},
|
|
16
|
-
{
|
|
17
|
-
/**
|
|
18
|
-
* #baseConfiguration
|
|
19
|
-
*/
|
|
20
|
-
baseConfiguration: createBaseTrackConfig(pluginManager),
|
|
21
|
-
},
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
export default configSchema
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
-
import TrackType from '@jbrowse/core/pluggableElementTypes/TrackType'
|
|
3
|
-
import { createBaseTrackModel } from '@jbrowse/core/pluggableElementTypes/models'
|
|
4
|
-
import configSchemaF from './configSchema'
|
|
5
|
-
|
|
6
|
-
export default (pm: PluginManager) => {
|
|
7
|
-
pm.addTrackType(() => {
|
|
8
|
-
const configSchema = configSchemaF(pm)
|
|
9
|
-
return new TrackType({
|
|
10
|
-
name: 'VariantTrack',
|
|
11
|
-
displayName: 'Variant track',
|
|
12
|
-
configSchema,
|
|
13
|
-
stateModel: createBaseTrackModel(pm, 'VariantTrack', configSchema),
|
|
14
|
-
})
|
|
15
|
-
})
|
|
16
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { toArray } from 'rxjs/operators'
|
|
2
|
-
import { firstValueFrom } from 'rxjs'
|
|
3
|
-
import Adapter from './VcfAdapter'
|
|
4
|
-
import configSchema from './configSchema'
|
|
5
|
-
|
|
6
|
-
test('adapter can fetch variants from volvox.vcf', async () => {
|
|
7
|
-
const adapter = new Adapter(
|
|
8
|
-
configSchema.create({
|
|
9
|
-
vcfLocation: {
|
|
10
|
-
localPath: require.resolve('./test_data/volvox.filtered.vcf'),
|
|
11
|
-
locationType: 'LocalPathLocation',
|
|
12
|
-
},
|
|
13
|
-
}),
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
const feat = adapter.getFeatures({
|
|
17
|
-
assemblyName: 'volvox',
|
|
18
|
-
refName: 'ctgA',
|
|
19
|
-
start: 0,
|
|
20
|
-
end: 20000,
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
const names = await adapter.getRefNames()
|
|
24
|
-
expect(names).toMatchSnapshot()
|
|
25
|
-
|
|
26
|
-
const featArray = await firstValueFrom(feat.pipe(toArray()))
|
|
27
|
-
expect(featArray.slice(0, 5)).toMatchSnapshot()
|
|
28
|
-
})
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BaseFeatureDataAdapter,
|
|
3
|
-
BaseOptions,
|
|
4
|
-
} from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
5
|
-
import { Region, Feature } from '@jbrowse/core/util'
|
|
6
|
-
import { openLocation } from '@jbrowse/core/util/io'
|
|
7
|
-
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
|
|
8
|
-
import IntervalTree from '@flatten-js/interval-tree'
|
|
9
|
-
import { unzip } from '@gmod/bgzf-filehandle'
|
|
10
|
-
import VCF from '@gmod/vcf'
|
|
11
|
-
|
|
12
|
-
// local
|
|
13
|
-
import VcfFeature from '../VcfFeature'
|
|
14
|
-
|
|
15
|
-
const readVcf = (f: string) => {
|
|
16
|
-
const header: string[] = []
|
|
17
|
-
const rest: string[] = []
|
|
18
|
-
f.split(/\n|\r\n|\r/)
|
|
19
|
-
.map(f => f.trim())
|
|
20
|
-
.filter(f => !!f)
|
|
21
|
-
.forEach(line => {
|
|
22
|
-
if (line.startsWith('#')) {
|
|
23
|
-
header.push(line)
|
|
24
|
-
} else if (line) {
|
|
25
|
-
rest.push(line)
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
return { header: header.join('\n'), lines: rest }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function isGzip(buf: Buffer) {
|
|
32
|
-
return buf[0] === 31 && buf[1] === 139 && buf[2] === 8
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export default class VcfAdapter extends BaseFeatureDataAdapter {
|
|
36
|
-
public static capabilities = ['getFeatures', 'getRefNames']
|
|
37
|
-
|
|
38
|
-
protected vcfFeatures?: Promise<{
|
|
39
|
-
header: string
|
|
40
|
-
intervalTree: Record<string, IntervalTree>
|
|
41
|
-
}>
|
|
42
|
-
|
|
43
|
-
public async getHeader() {
|
|
44
|
-
const { header } = await this.setup()
|
|
45
|
-
return header
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async getMetadata() {
|
|
49
|
-
const { header } = await this.setup()
|
|
50
|
-
const parser = new VCF({ header: header })
|
|
51
|
-
return parser.getMetadata()
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// converts lines into an interval tree
|
|
55
|
-
public async setupP() {
|
|
56
|
-
const pm = this.pluginManager
|
|
57
|
-
const buf = await openLocation(this.getConf('vcfLocation'), pm).readFile()
|
|
58
|
-
|
|
59
|
-
const buffer = isGzip(buf) ? await unzip(buf) : buf
|
|
60
|
-
|
|
61
|
-
// 512MB max chrome string length is 512MB
|
|
62
|
-
if (buffer.length > 536_870_888) {
|
|
63
|
-
throw new Error('Data exceeds maximum string length (512MB)')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const str = new TextDecoder().decode(buffer)
|
|
67
|
-
const { header, lines } = readVcf(str)
|
|
68
|
-
const intervalTree = {} as { [key: string]: IntervalTree }
|
|
69
|
-
|
|
70
|
-
for (const obj of lines.map((line, id) => {
|
|
71
|
-
const [refName, startP, , ref, , , , info] = line.split('\t')
|
|
72
|
-
const start = +startP - 1
|
|
73
|
-
const def = start + ref.length
|
|
74
|
-
const end = +(info.match(/END=(\d+)/)?.[1].trim() || def)
|
|
75
|
-
return { line, refName, start, end, id }
|
|
76
|
-
})) {
|
|
77
|
-
const key = obj.refName
|
|
78
|
-
if (!intervalTree[key]) {
|
|
79
|
-
intervalTree[key] = new IntervalTree()
|
|
80
|
-
}
|
|
81
|
-
intervalTree[key].insert([obj.start, obj.end], obj)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return { header, intervalTree }
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public async setup() {
|
|
88
|
-
if (!this.vcfFeatures) {
|
|
89
|
-
this.vcfFeatures = this.setupP().catch(e => {
|
|
90
|
-
this.vcfFeatures = undefined
|
|
91
|
-
throw e
|
|
92
|
-
})
|
|
93
|
-
}
|
|
94
|
-
return this.vcfFeatures
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public async getRefNames(_: BaseOptions = {}) {
|
|
98
|
-
const { intervalTree } = await this.setup()
|
|
99
|
-
return Object.keys(intervalTree)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public getFeatures(region: Region, opts: BaseOptions = {}) {
|
|
103
|
-
return ObservableCreate<Feature>(async observer => {
|
|
104
|
-
try {
|
|
105
|
-
const { start, end, refName } = region
|
|
106
|
-
const { header, intervalTree } = await this.setup()
|
|
107
|
-
const parser = new VCF({ header })
|
|
108
|
-
intervalTree[refName]?.search([start, end]).forEach(f =>
|
|
109
|
-
observer.next(
|
|
110
|
-
new VcfFeature({
|
|
111
|
-
variant: parser.parseLine(f.line),
|
|
112
|
-
parser,
|
|
113
|
-
id: `${this.id}-${f.id}`,
|
|
114
|
-
}),
|
|
115
|
-
),
|
|
116
|
-
)
|
|
117
|
-
observer.complete()
|
|
118
|
-
} catch (e) {
|
|
119
|
-
observer.error(e)
|
|
120
|
-
}
|
|
121
|
-
}, opts.signal)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
public freeResources(): void {}
|
|
125
|
-
}
|