Skip to content

Commit

Permalink
Add some adapters for uniprot alphafold data (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin authored Aug 26, 2024
1 parent 39c30bd commit 0cd5a69
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 1 deletion.
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default tseslint.config(
markers: ['/'],
},
],

'@typescript-eslint/require-await': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
Expand Down
63 changes: 63 additions & 0 deletions src/AlphaFoldConfidenceAdapter/AlphaFoldConfidenceAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {
BaseFeatureDataAdapter,
BaseOptions,
} from '@jbrowse/core/data_adapters/BaseAdapter'
import { openLocation } from '@jbrowse/core/util/io'
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
import {
Region,
Feature,
doesIntersect2,
SimpleFeature,
} from '@jbrowse/core/util'

export default class AlphaFoldConfidenceAdapter extends BaseFeatureDataAdapter {
public static capabilities = ['getFeatures', 'getRefNames']

public feats:
| Promise<{ uniqueId: string; start: number; end: number; score: number }[]>
| undefined

private async loadDataP() {
const scores = JSON.parse(
await openLocation(this.getConf('location')).readFile('utf8'),
) as { residueNumber: number[]; confidenceScore: number[] }

return scores.residueNumber.map((value, idx) => ({
uniqueId: `feat-${idx}`,
start: value,
end: value + 1,
score: scores.confidenceScore[idx]!,
}))
}

private async loadData(_opts: BaseOptions = {}) {
if (!this.feats) {
this.feats = this.loadDataP().catch((e: unknown) => {
this.feats = undefined
throw e
})
}

return this.feats
}

public async getRefNames(_opts: BaseOptions = {}) {
return []
}

public getFeatures(query: Region, opts: BaseOptions = {}) {
return ObservableCreate<Feature>(async observer => {
const { start, end, refName } = query
const data = await this.loadData()
for (const f of data) {
if (doesIntersect2(f.start, f.end, start, end)) {
observer.next(new SimpleFeature({ ...f, refName }))
}
}
observer.complete()
}, opts.signal)
}

public freeResources(): void {}
}
21 changes: 21 additions & 0 deletions src/AlphaFoldConfidenceAdapter/configSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ConfigurationSchema } from '@jbrowse/core/configuration'

/**
* #config AlphaFoldConfidenceAdapter
*/
function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars

const AlphaFoldConfidenceAdapter = ConfigurationSchema(
'AlphaFoldConfidenceAdapter',
{
/**
* #slot
*/
location: {
type: 'fileLocation',
defaultValue: { uri: '/path/to/my.bed.gz', locationType: 'UriLocation' },
},
},
{ explicitlyTyped: true },
)
export default AlphaFoldConfidenceAdapter
19 changes: 19 additions & 0 deletions src/AlphaFoldConfidenceAdapter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import PluginManager from '@jbrowse/core/PluginManager'
import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'

import configSchema from './configSchema'

export default function AlphaFoldConfidenceAdapterF(
pluginManager: PluginManager,
) {
pluginManager.addAdapterType(
() =>
new AdapterType({
name: 'AlphaFoldConfidenceAdapter',
displayName: 'AlphaFoldConfidence adapter',
configSchema,
getAdapterClass: () =>
import('./AlphaFoldConfidenceAdapter').then(r => r.default),
}),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
BaseFeatureDataAdapter,
BaseOptions,
} from '@jbrowse/core/data_adapters/BaseAdapter'
import { openLocation } from '@jbrowse/core/util/io'
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
import {
Region,
Feature,
doesIntersect2,
SimpleFeature,
max,
min,
} from '@jbrowse/core/util'

export default class AlphaMissensePathogenicityAdapter extends BaseFeatureDataAdapter {
public static capabilities = ['getFeatures', 'getRefNames']

public feats:
| Promise<
{
uniqueId: string
start: number
end: number
score: number
ref: string
variant: string
am_class: string
}[]
>
| undefined

private async loadDataP() {
const scores = await openLocation(this.getConf('location')).readFile('utf8')
return scores
.split('\n')
.slice(1)
.map(f => f.trim())
.filter(f => !!f)
.map((row, idx) => {
const [protein_variant, score, am_class] = row.split(',')
const ref = protein_variant![0]
const variant = protein_variant!.at(-1)
const coord = protein_variant!.slice(1, -1)
return {
uniqueId: `feat-${idx}`,
ref: ref!,
variant: variant!,
start: +coord,
end: +coord + 1,
score: +score!,
am_class: am_class!,
}
})
}

private async loadData(_opts: BaseOptions = {}) {
if (!this.feats) {
this.feats = this.loadDataP().catch((e: unknown) => {
this.feats = undefined
throw e
})
}

return this.feats
}

public async getGlobalStats(_opts?: BaseOptions) {
const data = await this.loadData()
const scoreMin = min(data.map(s => s.score))
const scoreMax = max(data.map(s => s.score))
return { scoreMin, scoreMax }
}

// always render bigwig instead of calculating a feature density for it
async getMultiRegionFeatureDensityStats(_regions: Region[]) {
return { featureDensity: 0 }
}
public async getRefNames(_opts: BaseOptions = {}) {
return []
}

public getFeatures(query: Region, opts: BaseOptions = {}) {
return ObservableCreate<Feature>(async observer => {
const { start, end, refName } = query
const data = await this.loadData()
for (const f of data) {
if (doesIntersect2(f.start, f.end, start, end)) {
observer.next(new SimpleFeature({ ...f, refName, source: f.variant }))
}
}
observer.complete()
}, opts.signal)
}

public async getSources() {
const sources = new Set<string>()
const data = await this.loadData()
for (const f of data) {
sources.add(f.variant)
}
return [...sources].map(s => ({
name: s,
__name: s,
}))
}

public freeResources(): void {}
}
21 changes: 21 additions & 0 deletions src/AlphaMissensePathogenicityAdapter/configSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ConfigurationSchema } from '@jbrowse/core/configuration'

/**
* #config AlphaMissensePathogenicityAdapter
*/
function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars

const AlphaMissensePathogenicityAdapter = ConfigurationSchema(
'AlphaMissensePathogenicityAdapter',
{
/**
* #slot
*/
location: {
type: 'fileLocation',
defaultValue: { uri: '/path/to/my.bed.gz', locationType: 'UriLocation' },
},
},
{ explicitlyTyped: true },
)
export default AlphaMissensePathogenicityAdapter
19 changes: 19 additions & 0 deletions src/AlphaMissensePathogenicityAdapter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import PluginManager from '@jbrowse/core/PluginManager'
import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'

import configSchema from './configSchema'

export default function AlphaMissensePathogenicityAdapterF(
pluginManager: PluginManager,
) {
pluginManager.addAdapterType(
() =>
new AdapterType({
name: 'AlphaMissensePathogenicityAdapter',
displayName: 'AlphaMissensePathogenicity adapter',
configSchema,
getAdapterClass: () =>
import('./AlphaMissensePathogenicityAdapter').then(r => r.default),
}),
)
}
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { version } from '../package.json'
import ProteinViewF from './ProteinView'
import LaunchProteinViewF from './LaunchProteinView'
import AddHighlightModelF from './AddHighlightModel'
import AlphaFoldConfidenceAdapterF from './AlphaFoldConfidenceAdapter'
import AlphaMissensePathogenicityAdapterF from './AlphaMissensePathogenicityAdapter'

export default class ProteinViewer extends Plugin {
name = 'ProteinViewer'
Expand All @@ -15,6 +17,8 @@ export default class ProteinViewer extends Plugin {
ProteinViewF(pluginManager)
LaunchProteinViewF(pluginManager)
AddHighlightModelF(pluginManager)
AlphaFoldConfidenceAdapterF(pluginManager)
AlphaMissensePathogenicityAdapterF(pluginManager)
}

configure(_pluginManager: PluginManager) {}
Expand Down

0 comments on commit 0cd5a69

Please sign in to comment.