jbrowse-plugin-mafviewer 1.0.6 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +71 -22
  2. package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.d.ts +20 -0
  3. package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js +197 -0
  4. package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js.map +1 -0
  5. package/dist/BgzipTaffyAdapter/configSchema.d.ts +44 -0
  6. package/dist/BgzipTaffyAdapter/configSchema.js +53 -0
  7. package/dist/BgzipTaffyAdapter/configSchema.js.map +1 -0
  8. package/dist/BgzipTaffyAdapter/index.d.ts +2 -0
  9. package/dist/BgzipTaffyAdapter/index.js +11 -0
  10. package/dist/BgzipTaffyAdapter/index.js.map +1 -0
  11. package/dist/BgzipTaffyAdapter/rowInstructions.d.ts +35 -0
  12. package/dist/BgzipTaffyAdapter/rowInstructions.js +55 -0
  13. package/dist/BgzipTaffyAdapter/rowInstructions.js.map +1 -0
  14. package/dist/BgzipTaffyAdapter/types.d.ts +13 -0
  15. package/dist/BgzipTaffyAdapter/types.js +2 -0
  16. package/dist/BgzipTaffyAdapter/types.js.map +1 -0
  17. package/dist/BgzipTaffyAdapter/virtualOffset.d.ts +8 -0
  18. package/dist/BgzipTaffyAdapter/virtualOffset.js +23 -0
  19. package/dist/BgzipTaffyAdapter/virtualOffset.js.map +1 -0
  20. package/dist/BigMafAdapter/BigMafAdapter.d.ts +17 -0
  21. package/dist/BigMafAdapter/BigMafAdapter.js +92 -0
  22. package/dist/BigMafAdapter/BigMafAdapter.js.map +1 -0
  23. package/dist/BigMafAdapter/configSchema.d.ts +32 -0
  24. package/dist/BigMafAdapter/configSchema.js +39 -0
  25. package/dist/BigMafAdapter/configSchema.js.map +1 -0
  26. package/dist/BigMafAdapter/index.d.ts +2 -0
  27. package/dist/BigMafAdapter/index.js +11 -0
  28. package/dist/BigMafAdapter/index.js.map +1 -0
  29. package/dist/LinearMafDisplay/components/ColorLegend.d.ts +8 -0
  30. package/dist/LinearMafDisplay/components/ColorLegend.js +19 -0
  31. package/dist/LinearMafDisplay/components/ColorLegend.js.map +1 -0
  32. package/dist/LinearMafDisplay/components/ReactComponent.d.ts +6 -0
  33. package/dist/LinearMafDisplay/components/ReactComponent.js +50 -0
  34. package/dist/LinearMafDisplay/components/ReactComponent.js.map +1 -0
  35. package/dist/LinearMafDisplay/components/RectBg.d.ts +9 -0
  36. package/dist/LinearMafDisplay/components/RectBg.js +7 -0
  37. package/dist/LinearMafDisplay/components/RectBg.js.map +1 -0
  38. package/dist/LinearMafDisplay/components/SetRowHeight.d.ts +11 -0
  39. package/dist/LinearMafDisplay/components/SetRowHeight.js +36 -0
  40. package/dist/LinearMafDisplay/components/SetRowHeight.js.map +1 -0
  41. package/dist/LinearMafDisplay/components/SvgWrapper.d.ts +8 -0
  42. package/dist/LinearMafDisplay/components/SvgWrapper.js +21 -0
  43. package/dist/LinearMafDisplay/components/SvgWrapper.js.map +1 -0
  44. package/dist/LinearMafDisplay/components/Tree.d.ts +5 -0
  45. package/dist/LinearMafDisplay/components/Tree.js +22 -0
  46. package/dist/LinearMafDisplay/components/Tree.js.map +1 -0
  47. package/dist/LinearMafDisplay/components/YScaleBars.d.ts +8 -0
  48. package/dist/LinearMafDisplay/components/YScaleBars.js +20 -0
  49. package/dist/LinearMafDisplay/components/YScaleBars.js.map +1 -0
  50. package/dist/LinearMafDisplay/components/util.d.ts +1 -0
  51. package/dist/LinearMafDisplay/components/util.js +8 -0
  52. package/dist/LinearMafDisplay/components/util.js.map +1 -0
  53. package/dist/LinearMafDisplay/configSchema.d.ts +34 -0
  54. package/dist/LinearMafDisplay/configSchema.js +15 -0
  55. package/dist/LinearMafDisplay/configSchema.js.map +1 -0
  56. package/dist/LinearMafDisplay/index.d.ts +2 -0
  57. package/dist/LinearMafDisplay/index.js +20 -0
  58. package/dist/LinearMafDisplay/index.js.map +1 -0
  59. package/dist/LinearMafDisplay/renderSvg.d.ts +4 -0
  60. package/dist/LinearMafDisplay/renderSvg.js +18 -0
  61. package/dist/LinearMafDisplay/renderSvg.js.map +1 -0
  62. package/dist/LinearMafDisplay/stateModel.d.ts +426 -0
  63. package/dist/LinearMafDisplay/stateModel.js +276 -0
  64. package/dist/LinearMafDisplay/stateModel.js.map +1 -0
  65. package/dist/LinearMafDisplay/types.d.ts +17 -0
  66. package/dist/LinearMafDisplay/types.js +16 -0
  67. package/dist/LinearMafDisplay/types.js.map +1 -0
  68. package/dist/LinearMafRenderer/LinearMafRenderer.d.ts +45 -0
  69. package/dist/LinearMafRenderer/LinearMafRenderer.js +183 -0
  70. package/dist/LinearMafRenderer/LinearMafRenderer.js.map +1 -0
  71. package/dist/LinearMafRenderer/components/ReactComponent.d.ts +6 -0
  72. package/dist/LinearMafRenderer/components/ReactComponent.js +8 -0
  73. package/dist/LinearMafRenderer/components/ReactComponent.js.map +1 -0
  74. package/dist/LinearMafRenderer/configSchema.d.ts +2 -0
  75. package/dist/LinearMafRenderer/configSchema.js +13 -0
  76. package/dist/LinearMafRenderer/configSchema.js.map +1 -0
  77. package/dist/LinearMafRenderer/index.d.ts +2 -0
  78. package/dist/LinearMafRenderer/index.js +12 -0
  79. package/dist/LinearMafRenderer/index.js.map +1 -0
  80. package/dist/LinearMafRenderer/util.d.ts +10 -0
  81. package/dist/LinearMafRenderer/util.js +16 -0
  82. package/dist/LinearMafRenderer/util.js.map +1 -0
  83. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.d.ts +5 -0
  84. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js +128 -0
  85. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js.map +1 -0
  86. package/dist/MafAddTrackWorkflow/index.d.ts +2 -0
  87. package/dist/MafAddTrackWorkflow/index.js +12 -0
  88. package/dist/MafAddTrackWorkflow/index.js.map +1 -0
  89. package/dist/MafRPC/index.d.ts +16 -0
  90. package/dist/MafRPC/index.js +19 -0
  91. package/dist/MafRPC/index.js.map +1 -0
  92. package/dist/MafTabixAdapter/MafTabixAdapter.d.ts +25 -0
  93. package/dist/MafTabixAdapter/MafTabixAdapter.js +95 -0
  94. package/dist/MafTabixAdapter/MafTabixAdapter.js.map +1 -0
  95. package/dist/MafTabixAdapter/configSchema.d.ts +50 -0
  96. package/dist/MafTabixAdapter/configSchema.js +56 -0
  97. package/dist/MafTabixAdapter/configSchema.js.map +1 -0
  98. package/dist/MafTabixAdapter/index.d.ts +2 -0
  99. package/dist/MafTabixAdapter/index.js +11 -0
  100. package/dist/MafTabixAdapter/index.js.map +1 -0
  101. package/dist/MafTrack/configSchema.d.ts +79 -0
  102. package/dist/MafTrack/configSchema.js +15 -0
  103. package/dist/MafTrack/configSchema.js.map +1 -0
  104. package/dist/MafTrack/index.d.ts +2 -0
  105. package/dist/MafTrack/index.js +14 -0
  106. package/dist/MafTrack/index.js.map +1 -0
  107. package/dist/index.d.ts +8 -0
  108. package/dist/index.js +26 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/jbrowse-plugin-mafviewer.umd.production.min.js +65 -1
  111. package/dist/jbrowse-plugin-mafviewer.umd.production.min.js.map +7 -1
  112. package/dist/parseNewick.d.ts +60 -0
  113. package/dist/parseNewick.js +95 -0
  114. package/dist/parseNewick.js.map +1 -0
  115. package/dist/util.d.ts +9 -0
  116. package/dist/util.js +9 -0
  117. package/dist/util.js.map +1 -0
  118. package/package.json +37 -41
  119. package/src/BgzipTaffyAdapter/BgzipTaffyAdapter.ts +227 -0
  120. package/src/BgzipTaffyAdapter/configSchema.ts +59 -0
  121. package/src/BgzipTaffyAdapter/index.ts +16 -0
  122. package/src/BgzipTaffyAdapter/rowInstructions.ts +91 -0
  123. package/src/BgzipTaffyAdapter/types.ts +16 -0
  124. package/src/BgzipTaffyAdapter/virtualOffset.ts +29 -0
  125. package/src/BigMafAdapter/BigMafAdapter.ts +12 -13
  126. package/src/BigMafAdapter/configSchema.ts +11 -0
  127. package/src/BigMafAdapter/index.ts +2 -1
  128. package/src/LinearMafDisplay/components/ColorLegend.tsx +38 -27
  129. package/src/LinearMafDisplay/components/ReactComponent.tsx +68 -3
  130. package/src/LinearMafDisplay/components/SetRowHeight.tsx +15 -8
  131. package/src/LinearMafDisplay/components/SvgWrapper.tsx +39 -0
  132. package/src/LinearMafDisplay/components/Tree.tsx +33 -0
  133. package/src/LinearMafDisplay/components/YScaleBars.tsx +11 -38
  134. package/src/LinearMafDisplay/components/util.ts +7 -0
  135. package/src/LinearMafDisplay/index.ts +2 -1
  136. package/src/LinearMafDisplay/renderSvg.tsx +2 -1
  137. package/src/LinearMafDisplay/stateModel.ts +169 -18
  138. package/src/LinearMafDisplay/types.ts +41 -0
  139. package/src/LinearMafRenderer/LinearMafRenderer.ts +51 -44
  140. package/src/LinearMafRenderer/components/ReactComponent.tsx +2 -1
  141. package/src/LinearMafRenderer/index.ts +2 -1
  142. package/src/LinearMafRenderer/util.ts +20 -0
  143. package/src/MafAddTrackWorkflow/AddTrackWorkflow.tsx +133 -51
  144. package/src/MafRPC/index.ts +39 -0
  145. package/src/MafTabixAdapter/MafTabixAdapter.ts +33 -27
  146. package/src/MafTabixAdapter/configSchema.ts +17 -1
  147. package/src/MafTabixAdapter/index.ts +2 -1
  148. package/src/MafTrack/index.ts +1 -0
  149. package/src/index.ts +6 -2
  150. package/src/parseNewick.ts +94 -0
  151. package/src/util.ts +11 -0
  152. package/LICENSE +0 -201
  153. package/dist/jbrowse-plugin-mafviewer.umd.development.js +0 -1439
  154. package/dist/jbrowse-plugin-mafviewer.umd.development.js.map +0 -1
@@ -1,4 +1,13 @@
1
1
  import React, { useState } from 'react'
2
+
3
+ import { ErrorMessage, FileSelector } from '@jbrowse/core/ui'
4
+ import {
5
+ FileLocation,
6
+ getSession,
7
+ isSessionModelWithWidgets,
8
+ isSessionWithAddTracks,
9
+ } from '@jbrowse/core/util'
10
+ import { AddTrackModel } from '@jbrowse/plugin-data-management'
2
11
  import {
3
12
  Button,
4
13
  FormControl,
@@ -9,16 +18,8 @@ import {
9
18
  RadioGroup,
10
19
  TextField,
11
20
  } from '@mui/material'
12
- import { makeStyles } from 'tss-react/mui'
13
- import {
14
- FileLocation,
15
- getSession,
16
- isSessionModelWithWidgets,
17
- isSessionWithAddTracks,
18
- } from '@jbrowse/core/util'
19
- import { AddTrackModel } from '@jbrowse/plugin-data-management'
20
- import { ErrorMessage, FileSelector } from '@jbrowse/core/ui'
21
21
  import { getRoot } from 'mobx-state-tree'
22
+ import { makeStyles } from 'tss-react/mui'
22
23
 
23
24
  const useStyles = makeStyles()(theme => ({
24
25
  textbox: {
@@ -35,15 +36,25 @@ const useStyles = makeStyles()(theme => ({
35
36
  },
36
37
  }))
37
38
 
39
+ type AdapterTypeOptions =
40
+ | 'BigMafAdapter'
41
+ | 'MafTabixAdapter'
42
+ | 'BgzipTaffyAdapter'
43
+ type IndexTypeOptions = 'TBI' | 'CSI'
44
+
38
45
  export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
39
46
  const { classes } = useStyles()
40
47
  const [samples, setSamples] = useState('')
41
48
  const [loc, setLoc] = useState<FileLocation>()
42
49
  const [indexLoc, setIndexLoc] = useState<FileLocation>()
50
+ const [nhLoc, setNhLoc] = useState<FileLocation>()
43
51
  const [error, setError] = useState<unknown>()
44
52
  const [trackName, setTrackName] = useState('MAF track')
45
- const [choice, setChoice] = useState('BigMafAdapter')
46
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ const [fileTypeChoice, setFileTypeChoice] =
54
+ useState<AdapterTypeOptions>('BigMafAdapter')
55
+ const [indexTypeChoice, setIndexTypeChoice] =
56
+ useState<IndexTypeOptions>('TBI')
57
+
47
58
  const rootModel = getRoot<any>(model)
48
59
  return (
49
60
  <Paper className={classes.paper}>
@@ -52,63 +63,121 @@ export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
52
63
  <FormControl>
53
64
  <FormLabel>File type</FormLabel>
54
65
  <RadioGroup
55
- value={choice}
56
- onChange={event => setChoice(event.target.value)}
66
+ value={fileTypeChoice}
67
+ onChange={event => {
68
+ setFileTypeChoice(event.target.value as AdapterTypeOptions)
69
+ }}
57
70
  >
58
- <FormControlLabel
59
- value="BigMafAdapter"
60
- control={<Radio />}
61
- checked={choice === 'BigMafAdapter'}
62
- label="bigMaf"
63
- />
64
- <FormControlLabel
65
- value="MafTabixAdapter"
66
- control={<Radio />}
67
- checked={choice === 'MafTabixAdapter'}
68
- label="mafTabix"
69
- />
71
+ {['BigMafAdapter', 'MafTabixAdapter', 'BgzipTaffyAdapter'].map(
72
+ r => (
73
+ <FormControlLabel
74
+ value={r}
75
+ control={<Radio />}
76
+ checked={fileTypeChoice === r}
77
+ label={r}
78
+ />
79
+ ),
80
+ )}
70
81
  </RadioGroup>
71
82
  </FormControl>
72
- {choice === 'BigMafAdapter' ? (
83
+ {fileTypeChoice === 'BigMafAdapter' ? (
73
84
  <FileSelector
74
85
  location={loc}
75
86
  name="Path to bigMaf"
76
- setLocation={arg => setLoc(arg)}
77
87
  rootModel={rootModel}
88
+ setLocation={arg => {
89
+ setLoc(arg)
90
+ }}
78
91
  />
79
- ) : (
92
+ ) : fileTypeChoice === 'MafTabixAdapter' ? (
80
93
  <>
94
+ <FormControl>
95
+ <FormLabel>Index type</FormLabel>
96
+ <RadioGroup
97
+ value={fileTypeChoice}
98
+ onChange={event => {
99
+ setIndexTypeChoice(event.target.value as IndexTypeOptions)
100
+ }}
101
+ >
102
+ {['TBI', 'CSI'].map(r => (
103
+ <FormControlLabel
104
+ value={r}
105
+ control={<Radio />}
106
+ checked={fileTypeChoice === r}
107
+ label={r}
108
+ />
109
+ ))}
110
+ </RadioGroup>
111
+ </FormControl>
81
112
  <FileSelector
82
113
  location={loc}
83
114
  name="Path to MAF tabix"
84
- setLocation={arg => setLoc(arg)}
85
115
  rootModel={rootModel}
116
+ setLocation={arg => {
117
+ setLoc(arg)
118
+ }}
86
119
  />
87
120
  <FileSelector
88
121
  location={indexLoc}
89
122
  name="Path to MAF tabix index"
90
- setLocation={arg => setIndexLoc(arg)}
91
123
  rootModel={rootModel}
124
+ setLocation={arg => {
125
+ setIndexLoc(arg)
126
+ }}
127
+ />
128
+ </>
129
+ ) : (
130
+ <>
131
+ <FileSelector
132
+ location={loc}
133
+ name="Path to TAF.gz (Bgzipped TAF)"
134
+ rootModel={rootModel}
135
+ setLocation={arg => {
136
+ setLoc(arg)
137
+ }}
138
+ />
139
+ <FileSelector
140
+ location={indexLoc}
141
+ name="Path to TAF.gz.tai (TAF index)"
142
+ rootModel={rootModel}
143
+ setLocation={arg => {
144
+ setIndexLoc(arg)
145
+ }}
92
146
  />
93
147
  </>
94
148
  )}
95
149
  </Paper>
96
- <TextField
97
- multiline
98
- rows={10}
99
- value={samples}
100
- onChange={event => setSamples(event.target.value)}
101
- placeholder={
102
- 'Enter sample names from the MAF file, one per line, or JSON formatted array of samples'
103
- }
104
- variant="outlined"
105
- fullWidth
106
- />
150
+ <div>
151
+ <FileSelector
152
+ location={nhLoc}
153
+ name="Path to newick tree (.nh)"
154
+ rootModel={rootModel}
155
+ setLocation={arg => {
156
+ setNhLoc(arg)
157
+ }}
158
+ />
159
+ <TextField
160
+ multiline
161
+ rows={10}
162
+ value={samples}
163
+ onChange={event => {
164
+ setSamples(event.target.value)
165
+ }}
166
+ helperText="Sample names (optional if .nh supplied, required if not)"
167
+ placeholder={
168
+ 'Enter sample names from the MAF file, one per line, or JSON formatted array of samples'
169
+ }
170
+ variant="outlined"
171
+ fullWidth
172
+ />
173
+ </div>
107
174
 
108
175
  <TextField
109
176
  value={trackName}
110
- onChange={event => setTrackName(event.target.value)}
111
177
  helperText="Track name"
178
+ onChange={event => {
179
+ setTrackName(event.target.value)
180
+ }}
112
181
  />
113
182
  <Button
114
183
  variant="contained"
@@ -125,7 +194,7 @@ export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
125
194
 
126
195
  const trackId = [
127
196
  `${trackName.toLowerCase().replaceAll(' ', '_')}-${Date.now()}`,
128
- `${session.adminMode ? '' : '-sessionTrack'}`,
197
+ session.adminMode ? '' : '-sessionTrack',
129
198
  ].join('')
130
199
 
131
200
  if (isSessionWithAddTracks(session)) {
@@ -135,18 +204,31 @@ export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
135
204
  name: trackName,
136
205
  assemblyNames: [model.assembly],
137
206
  adapter:
138
- choice === 'BigMafAdapter'
207
+ fileTypeChoice === 'BigMafAdapter'
139
208
  ? {
140
- type: choice,
209
+ type: fileTypeChoice,
141
210
  bigBedLocation: loc,
142
211
  samples: sampleNames,
212
+ nhLocation: nhLoc,
143
213
  }
144
- : {
145
- type: choice,
146
- bedGzLocation: loc,
147
- index: { location: indexLoc },
148
- samples: sampleNames,
149
- },
214
+ : fileTypeChoice === 'MafTabixAdapter'
215
+ ? {
216
+ type: fileTypeChoice,
217
+ bedGzLocation: loc,
218
+ nhLocation: nhLoc,
219
+ index: {
220
+ indexType: indexTypeChoice,
221
+ location: indexLoc,
222
+ },
223
+ samples: sampleNames,
224
+ }
225
+ : {
226
+ type: fileTypeChoice,
227
+ tafGzLocation: loc,
228
+ taiLocation: indexLoc,
229
+ nhLocation: nhLoc,
230
+ samples: sampleNames,
231
+ },
150
232
  })
151
233
 
152
234
  model.view?.showTrack(trackId)
@@ -0,0 +1,39 @@
1
+ import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache'
2
+ import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions'
3
+
4
+ import type PluginManager from '@jbrowse/core/PluginManager'
5
+ import type { AnyConfigurationModel } from '@jbrowse/core/configuration'
6
+ import type { Region } from '@jbrowse/core/util'
7
+
8
+ export class MafGetSamples extends RpcMethodTypeWithFiltersAndRenameRegions {
9
+ name = 'MafGetSamples'
10
+
11
+ async execute(
12
+ args: {
13
+ adapterConfig: AnyConfigurationModel
14
+ stopToken?: string
15
+ sessionId: string
16
+ headers?: Record<string, string>
17
+ regions: Region[]
18
+ bpPerPx: number
19
+ },
20
+ rpcDriverClassName: string,
21
+ ) {
22
+ const pm = this.pluginManager
23
+ const deserializedArgs = await this.deserializeArguments(
24
+ args,
25
+ rpcDriverClassName,
26
+ )
27
+ const { regions, adapterConfig, sessionId } = deserializedArgs
28
+ const { dataAdapter } = await getAdapter(pm, sessionId, adapterConfig)
29
+
30
+ // @ts-expect-error
31
+ return dataAdapter.getSamples(regions, deserializedArgs)
32
+ }
33
+ }
34
+
35
+ export default function MafRPCF(pluginManager: PluginManager) {
36
+ pluginManager.addRpcMethod(() => {
37
+ return new MafGetSamples(pluginManager)
38
+ })
39
+ }
@@ -1,9 +1,13 @@
1
1
  import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
2
- import { getSnapshot } from 'mobx-state-tree'
3
2
  import { Feature, Region, SimpleFeature } from '@jbrowse/core/util'
3
+ import { openLocation } from '@jbrowse/core/util/io'
4
4
  import { ObservableCreate } from '@jbrowse/core/util/rxjs'
5
+ import { getSnapshot } from 'mobx-state-tree'
5
6
  import { firstValueFrom, toArray } from 'rxjs'
6
7
 
8
+ import parseNewick from '../parseNewick'
9
+ import { normalize } from '../util'
10
+
7
11
  interface OrganismRecord {
8
12
  chr: string
9
13
  start: number
@@ -13,7 +17,7 @@ interface OrganismRecord {
13
17
  data: string
14
18
  }
15
19
 
16
- export default class BigMafAdapter extends BaseFeatureDataAdapter {
20
+ export default class MafTabixAdapter extends BaseFeatureDataAdapter {
17
21
  public setupP?: Promise<{ adapter: BaseFeatureDataAdapter }>
18
22
 
19
23
  async setup() {
@@ -31,7 +35,7 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
31
35
  }
32
36
  async setupPre() {
33
37
  if (!this.setupP) {
34
- this.setupP = this.setup().catch(e => {
38
+ this.setupP = this.setup().catch((e: unknown) => {
35
39
  this.setupP = undefined
36
40
  throw e
37
41
  })
@@ -55,13 +59,7 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
55
59
  const features = await firstValueFrom(
56
60
  adapter.getFeatures(query).pipe(toArray()),
57
61
  )
58
- const samples = this.getConf('samples') as string[] | { id: string }[]
59
- const sampleStrings =
60
- typeof samples[0] === 'string'
61
- ? (samples as string[])
62
- : (samples as { id: string }[]).map(s => s.id)
63
- const sampleSet = new Set(sampleStrings)
64
- let i = 0
62
+
65
63
  for (const feature of features) {
66
64
  const data = (feature.get('field5') as string).split(',')
67
65
  const alignments = {} as Record<string, OrganismRecord>
@@ -69,26 +67,18 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
69
67
 
70
68
  for (const [j, elt] of data.entries()) {
71
69
  const ad = elt.split(':')
72
- const idx = ad[0].lastIndexOf('.')
73
- const org = ad[0].slice(0, idx)
74
- const last = ad[0].slice(idx + 1)
75
- const s = sampleSet.has(org)
76
- ? org
77
- : sampleStrings.find(f => ad[0].startsWith(f))
78
- if (s) {
79
- alignments[s] = {
70
+ const idx = ad[0]!.lastIndexOf('.')
71
+ const org = ad[0]!.slice(0, idx)
72
+ const last = ad[0]!.slice(idx + 1)
73
+ if (org) {
74
+ alignments[org] = {
80
75
  chr: last,
81
- start: +ad[1],
82
- srcSize: +ad[2],
76
+ start: +ad[1]!,
77
+ srcSize: +ad[2]!,
83
78
  strand: ad[3] === '-' ? -1 : 1,
84
- unknown: +ad[4],
85
- data: alns[j],
79
+ unknown: +ad[4]!,
80
+ data: alns[j]!,
86
81
  }
87
- } else if (i < 100) {
88
- console.error(`line not processed ${ad[0]}`)
89
- i++
90
- } else if (i > 100) {
91
- console.error('too many errors, not printing any more')
92
82
  }
93
83
  }
94
84
 
@@ -110,5 +100,21 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
110
100
  observer.complete()
111
101
  })
112
102
  }
103
+
104
+ async getSamples(_query: Region) {
105
+ const nhLoc = this.getConf('nhLocation')
106
+ const nh =
107
+ nhLoc.uri === '/path/to/my.nh'
108
+ ? undefined
109
+ : await openLocation(nhLoc).readFile('utf8')
110
+
111
+ // TODO: we may need to resolve the exact set of rows in the visible region
112
+ // here
113
+ return {
114
+ samples: normalize(this.getConf('samples')),
115
+ tree: nh ? parseNewick(nh) : undefined,
116
+ }
117
+ }
118
+
113
119
  freeResources(): void {}
114
120
  }
@@ -2,7 +2,6 @@ import { ConfigurationSchema } from '@jbrowse/core/configuration'
2
2
 
3
3
  /**
4
4
  * #config MafTabixAdapter
5
- * used to configure MafTabix adapter
6
5
  */
7
6
  function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
8
7
 
@@ -28,17 +27,34 @@ const configSchema = ConfigurationSchema(
28
27
  },
29
28
  },
30
29
  index: ConfigurationSchema('Index', {
30
+ /**
31
+ * #slot index.location
32
+ */
31
33
  location: {
32
34
  type: 'fileLocation',
33
35
  defaultValue: {
34
36
  uri: '/path/to/my.bed.gz.tbi',
35
37
  },
36
38
  },
39
+ /**
40
+ * #slot index.indexType
41
+ */
37
42
  indexType: {
38
43
  type: 'string',
39
44
  defaultValue: 'TBI',
40
45
  },
41
46
  }),
47
+ /**
48
+ * #slot
49
+ */
50
+ nhLocation: {
51
+ type: 'fileLocation',
52
+ description: 'newick tree',
53
+ defaultValue: {
54
+ uri: '/path/to/my.nh',
55
+ locationType: 'UriLocation',
56
+ },
57
+ },
42
58
  },
43
59
  { explicitlyTyped: true },
44
60
  )
@@ -1,7 +1,8 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager'
2
2
  import { AdapterType } from '@jbrowse/core/pluggableElementTypes'
3
- import configSchema from './configSchema'
3
+
4
4
  import MafTabixAdapter from './MafTabixAdapter'
5
+ import configSchema from './configSchema'
5
6
 
6
7
  export default function MafTabixAdapterF(pluginManager: PluginManager) {
7
8
  return pluginManager.addAdapterType(
@@ -3,6 +3,7 @@ import {
3
3
  TrackType,
4
4
  createBaseTrackModel,
5
5
  } from '@jbrowse/core/pluggableElementTypes'
6
+
6
7
  import configSchemaF from './configSchema'
7
8
 
8
9
  export default function MafTrackF(pluginManager: PluginManager) {
package/src/index.ts CHANGED
@@ -2,12 +2,14 @@ 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'
5
6
  import BigMafAdapterF from './BigMafAdapter'
6
- import MafTrackF from './MafTrack'
7
7
  import LinearMafDisplayF from './LinearMafDisplay'
8
8
  import LinearMafRendererF from './LinearMafRenderer'
9
- import MafTabixAdapterF from './MafTabixAdapter'
10
9
  import MafAddTrackWorkflowF from './MafAddTrackWorkflow'
10
+ import MafRPCF from './MafRPC'
11
+ import MafTabixAdapterF from './MafTabixAdapter'
12
+ import MafTrackF from './MafTrack'
11
13
 
12
14
  export default class MafViewerPlugin extends Plugin {
13
15
  name = 'MafViewerPlugin'
@@ -19,7 +21,9 @@ export default class MafViewerPlugin extends Plugin {
19
21
  LinearMafDisplayF(pluginManager)
20
22
  LinearMafRendererF(pluginManager)
21
23
  MafTabixAdapterF(pluginManager)
24
+ BgzipTaffyAdapterF(pluginManager)
22
25
  MafAddTrackWorkflowF(pluginManager)
26
+ MafRPCF(pluginManager)
23
27
  }
24
28
 
25
29
  configure(_pluginManager: PluginManager) {}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Newick format parser in JavaScript.
3
+ *
4
+ * Copyright (c) Jason Davies 2010.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ *
24
+ * Example tree (from http://en.wikipedia.org/wiki/Newick_format):
25
+ *
26
+ * +--0.1--A
27
+ * F-----0.2-----B +-------0.3----C
28
+ * +------------------0.5-----E
29
+ * +---------0.4------D
30
+ *
31
+ * Newick format:
32
+ * (A:0.1,B:0.2,(C:0.3,D:0.4)E:0.5)F;
33
+ *
34
+ * Converted to JSON:
35
+ * {
36
+ * name: "F",
37
+ * children: [
38
+ * {name: "A", length: 0.1},
39
+ * {name: "B", length: 0.2},
40
+ * {
41
+ * name: "E",
42
+ * length: 0.5,
43
+ * children: [
44
+ * {name: "C", length: 0.3},
45
+ * {name: "D", length: 0.4}
46
+ * ]
47
+ * }
48
+ * ]
49
+ * }
50
+ *
51
+ * Converted to JSON, but with no names or lengths:
52
+ * {
53
+ * children: [
54
+ * {}, {}, {
55
+ * children: [{}, {}]
56
+ * }
57
+ * ]
58
+ * }
59
+ */
60
+ export default function parseNewick(s: string) {
61
+ const ancestors = []
62
+
63
+ let tree = {} as Record<string, any>
64
+ const tokens = s.split(/\s*(;|\(|\)|,|:)\s*/)
65
+ for (let i = 0; i < tokens.length; i++) {
66
+ const token = tokens[i]!
67
+ const subtree = {}
68
+ switch (token) {
69
+ case '(': // new children
70
+ tree.children = [subtree]
71
+ ancestors.push(tree)
72
+ tree = subtree
73
+ break
74
+ case ',': // another branch
75
+ ancestors.at(-1)?.children.push(subtree)
76
+ tree = subtree
77
+ break
78
+ case ')': // optional name next
79
+ tree = ancestors.pop()!
80
+ break
81
+ case ':': // optional length next
82
+ break
83
+ default: {
84
+ const x = tokens[i - 1]!
85
+ if (x === ')' || x === '(' || x === ',') {
86
+ tree.name = token
87
+ } else if (x === ':') {
88
+ tree.length = Number.parseFloat(token)
89
+ }
90
+ }
91
+ }
92
+ }
93
+ return tree
94
+ }
package/src/util.ts ADDED
@@ -0,0 +1,11 @@
1
+ function isStrs(array: unknown[]): array is string[] {
2
+ return typeof array[0] === 'string'
3
+ }
4
+
5
+ export function normalize(
6
+ r: string[] | { id: string; label: string; color?: string }[],
7
+ ) {
8
+ return isStrs(r)
9
+ ? r.map(elt => ({ id: elt, label: elt, color: undefined }))
10
+ : r
11
+ }