Skip to content

Commit

Permalink
Merge pull request #68 from ebi-webcomponents/af-pred
Browse files Browse the repository at this point in the history
Af pred
  • Loading branch information
dlrice authored Dec 1, 2023
2 parents 113539a + 3b71ed4 commit 56ab12d
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 58 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"data-loader": "^2.9.1",
"file-saver": "^2.0.2",
"lit-element": "^2.2.0",
"protvista-coloured-sequence": "3.8.10",
"protvista-datatable": "3.8.10",
"protvista-feature-adapter": "3.8.12",
"protvista-filter": "3.8.4",
Expand Down
22 changes: 22 additions & 0 deletions src/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
{
"categories": [
{
"name": "ALPHAFOLD_CONFIDENCE",
"label": "AlphaFold",
"trackType": "protvista-coloured-sequence",
"scale": "H:90,M:70,L:50,D:0",
"color-range": "#ff7d45:0,#ffdb13:50,#65cbf3:70,#0053d6:90,#0053d6:100",
"tracks": [
{
"name": "alphafold_confidence",
"label": "AlphaFold Confidence",
"labelUrl": "https://alphafold.ebi.ac.uk/entry/{accession}",
"trackType": "protvista-coloured-sequence",
"data": [
{
"adapter": "protvista-alphafold-confidence-adapter",
"url": "https://alphafold.ebi.ac.uk/api/prediction/{accession}"
}
],
"tooltip": "AlphaFold prediction confidence"
}
]
},
{
"name": "DOMAINS_AND_SITES",
"label": "Domains & sites",
Expand Down
49 changes: 49 additions & 0 deletions src/protvista-alphafold-confidence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
type AlphafoldPayload = Array<{
entryId: string;
gene: string;
uniprotAccession: string;
uniprotId: string;
uniprotDescription: string;
taxId: number;
organismScientificName: string;
uniprotStart: number;
uniprotEnd: number;
uniprotSequence: string;
modelCreatedDate: string;
latestVersion: number;
allVersions: number[];
cifUrl: string;
bcifUrl: string;
pdbUrl: string;
paeImageUrl: string;
paeDocUrl: string;
}>;

type AlphafoldConfidencePayload = {
residueNumber: Array<number>;
confidenceScore: Array<number>;
confidenceCategory: Array<string>;
};

export const getConfidenceURLFromPayload = (data: AlphafoldPayload) => {
const cifURL = data?.[0]?.cifUrl;
return cifURL?.length
? cifURL.replace('-model', '-confidence').replace('.cif', '.json')
: null;
};

const loadConfidence = async (
url: string
): Promise<AlphafoldConfidencePayload> => {
try {
return (await fetch(url)).json();
} catch (e) {
console.error(`Couldn't load AlphaFold confidence`, e);
}
};

export const transformData = async (data: AlphafoldPayload) => {
const confidenceUrl = getConfidenceURLFromPayload(data);
const confidenceData = await loadConfidence(confidenceUrl);
return confidenceData.confidenceCategory.join('');
};
175 changes: 118 additions & 57 deletions src/protvista-uniprot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { frame } from 'timing-functions';
import ProtvistaNavigation from 'protvista-navigation';
import ProtvistaTooltip from 'protvista-tooltip';
import ProtvistaTrackConfig from 'protvista-track';
import ProtvistaColouredSequenceConfig from 'protvista-coloured-sequence';
import ProtvistaInterproTrack from 'protvista-interpro-track';
import ProtvistaSequence from 'protvista-sequence';
import ProtvistaVariation from 'protvista-variation';
Expand All @@ -20,6 +21,7 @@ import { transformData as _transformDataStructureAdapter } from 'protvista-struc
import { transformData as _transformDataVariationAdapter } from 'protvista-variation-adapter';
import { transformData as _transformDataInterproAdapter } from 'protvista-interpro-adapter';
import { transformData as _transformDataProteomicsPTMApdapter } from './protvista-ptm-exchange';
import { transformData as _transformDataAlphaFoldConfidenceAdapter } from './protvista-alphafold-confidence';

import defaultConfig from './config.json';
import _ProtvistaUniprotStructure from './protvista-uniprot-structure';
Expand All @@ -37,7 +39,11 @@ export const transformDataProteomicsAdapter = _transformDataProteomicsAdapter;
export const transformDataStructureAdapter = _transformDataStructureAdapter;
export const transformDataVariationAdapter = _transformDataVariationAdapter;
export const transformDataInterproAdapter = _transformDataInterproAdapter;
export const transformDataProteomicsPTMApdapter = _transformDataProteomicsPTMApdapter;
export const transformDataProteomicsPTMApdapter =
_transformDataProteomicsPTMApdapter;
export const transformDataAlphaFoldConfidenceAdapter =
_transformDataAlphaFoldConfidenceAdapter;

export const filterConfig = _filterConfig;
export const colorConfig = _colorConfig;
export const ProtvistaUniprotStructure = _ProtvistaUniprotStructure;
Expand All @@ -49,18 +55,22 @@ const adapters = {
'protvista-proteomics-adapter': transformDataProteomicsAdapter,
'protvista-structure-adapter': transformDataStructureAdapter,
'protvista-variation-adapter': transformDataVariationAdapter,
'protvista-proteomics-ptm-adapter': transformDataProteomicsPTMApdapter
'protvista-proteomics-ptm-adapter': transformDataProteomicsPTMApdapter,
'protvista-alphafold-confidence-adapter':
transformDataAlphaFoldConfidenceAdapter,
};

type TrackType =
| 'protvista-track'
| 'protvista-variation'
| 'protvista-variation-graph'
| 'protvista-interpro-track';
| 'protvista-interpro-track'
| 'protvista-coloured-sequence';

type ProtvistaTrackConfig = {
name: string;
label: string;
labelUrl?: string;
filter: string;
trackType: TrackType;
data: {
Expand All @@ -74,7 +84,9 @@ type ProtvistaTrackConfig = {
tooltip: string;
color?: string;
shape?: string; //TODO: eventually replace with list
scale?: string;
filterComponent?: 'protvista-filter';
'color-range'?: string;
};

type ProtvistaCategory = {
Expand All @@ -84,6 +96,8 @@ type ProtvistaCategory = {
tracks: ProtvistaTrackConfig[];
color?: string;
shape?: string; //TODO: eventually replace with list
scale?: string;
'color-range'?: string;
};

export type DownloadConfig = {
Expand Down Expand Up @@ -149,6 +163,10 @@ class ProtvistaUniprot extends LitElement {
loadComponent('protvista-navigation', ProtvistaNavigation);
loadComponent('protvista-tooltip', ProtvistaTooltip);
loadComponent('protvista-track', ProtvistaTrackConfig);
loadComponent(
'protvista-coloured-sequence',
ProtvistaColouredSequenceConfig
);
loadComponent('protvista-interpro-track', ProtvistaInterproTrack);
loadComponent('protvista-sequence', ProtvistaSequence);
loadComponent('protvista-variation', ProtvistaVariation);
Expand Down Expand Up @@ -189,49 +207,48 @@ class ProtvistaUniprot extends LitElement {

// Now iterate over tracks and categories, transforming the data
// and assigning it as adequate
this.config.categories.map(
({ name: categoryName, tracks, trackType }) => {
// const categoryData: any = [];
const categoryData = tracks.map(
({ data: dataConfig, name: trackName, filter }) => {
const { url, adapter } = dataConfig[0]; // TODO handle array
const trackData = this.rawData[url] || [];

if (
!trackData ||
(adapter === 'protvista-variation-adapter' &&
trackData.length === 0)
) {
return;
}
// 1. Convert data
const transformedData = adapter
? adapters[adapter](trackData)
: trackData;

// 2. Filter raw data if filter is specified
const filteredData =
Array.isArray(transformedData) && filter
? transformedData.filter(
({ type }: { type?: string }) => type === filter
)
: transformedData;
if (!filteredData) {
return;
}

// 3. Assign track data
this.data[`${categoryName}-${trackName}`] = filteredData;

return filteredData;
for (const { name: categoryName, tracks, trackType } of this.config
.categories) {
const categoryData = await Promise.all(
tracks.map(async ({ data: dataConfig, name: trackName, filter }) => {
const { url, adapter } = dataConfig[0]; // TODO handle array
const trackData = this.rawData[url] || [];

if (
!trackData ||
(adapter === 'protvista-variation-adapter' &&
trackData.length === 0)
) {
return;
}
);
this.data[categoryName] =
trackType === 'protvista-variation-graph'
? categoryData[0]
: categoryData.flat();
}
);
// 1. Convert data
const transformedData = adapter
? await adapters[adapter](trackData)
: trackData;

// 2. Filter raw data if filter is specified
const filteredData =
Array.isArray(transformedData) && filter
? transformedData.filter(
({ type }: { type?: string }) => type === filter
)
: transformedData;
if (!filteredData) {
return;
}

// 3. Assign track data
this.data[`${categoryName}-${trackName}`] = filteredData;

return filteredData;
})
);
this.data[categoryName] =
trackType === 'protvista-variation-graph' ||
trackType === 'protvista-coloured-sequence'
? categoryData[0]
: categoryData.flat();
}
}
this.loading = false;
this.requestUpdate(); // Why?
Expand All @@ -244,7 +261,9 @@ class ProtvistaUniprot extends LitElement {
`track-${id}`
);
// set data if it hasn't changed
if (element && element.data !== data) element.data = data;
if (element && element.data !== data) {
element.data = data;
}
const currentCategory = this.config?.categories.find(
({ name }) => name === id
);
Expand Down Expand Up @@ -454,10 +473,12 @@ class ProtvistaUniprot extends LitElement {
>
${category.label}
</div>
<div
data-id="category_${category.name}"
class="aggregate-track-content track-content"
class="aggregate-track-content track-content ${category.trackType ===
'protvista-coloured-sequence'
? 'track-content__coloured-sequence'
: ''}"
.style="${this.openCategories.includes(category.name)
? 'opacity:0'
: 'opacity:1'}"
Expand All @@ -468,7 +489,9 @@ class ProtvistaUniprot extends LitElement {
'non-overlapping',
category.color,
category.shape,
category.name
category.name,
category.scale,
category['color-range']
)}
</div>
</div>
Expand All @@ -484,22 +507,37 @@ class ProtvistaUniprot extends LitElement {
? html`
<div class="category__track" id="track_${track.name}">
<div class="track-label" title="${track.tooltip}">
${track.filterComponent
? this.getFilterComponent(
`${category.name}-${track.name}`
)
: track.label}
${(track.filterComponent &&
this.getFilterComponent(
`${category.name}-${track.name}`
)) ||
(track.labelUrl &&
html`<a
target="_blank"
href="${track.labelUrl.replace(
'{accession}',
this.accession
)}"
>${track.label}</a
>`) ||
track.label}
</div>
<div
class="track-content"
class="track-content ${category.trackType ===
'protvista-coloured-sequence'
? 'track-content__coloured-sequence'
: ''}"
data-id="track_${track.name}"
>
${this.getTrack(
track.trackType,
'non-overlapping',
track.color || category.color,
track.shape || category.shape,
`${category.name}-${track.name}`
`${category.name}-${track.name}`,
track.scale || category.scale,
track['color-range'] || category['color-range']
)}
</div>
</div>
Expand Down Expand Up @@ -529,7 +567,9 @@ class ProtvistaUniprot extends LitElement {
'non-overlapping',
category.color,
category.shape,
`${category.name}-${item.accession}`
`${category.name}-${item.accession}`,
category.scale,
category['color-range']
)}
</div>
</div>
Expand Down Expand Up @@ -613,7 +653,15 @@ class ProtvistaUniprot extends LitElement {
`;
}

getTrack(trackType: TrackType, layout = '', color = '', shape = '', id = '') {
getTrack(
trackType: TrackType,
layout = '',
color = '',
shape = '',
id = '',
scale = '',
colorRange = ''
) {
// lit-html doesn't allow to have dynamic tag names, hence the switch/case
// with repeated code
switch (trackType) {
Expand Down Expand Up @@ -662,6 +710,19 @@ class ProtvistaUniprot extends LitElement {
>
</protvista-variation-graph>
`;
case 'protvista-coloured-sequence':
return html`
<protvista-coloured-sequence
length="${this.sequence?.length}"
displaystart="${this.displayCoordinates?.start}"
displayend="${this.displayCoordinates?.end}"
id="track-${id}"
scale="${scale}"
color_range="${colorRange}"
height="13"
>
</protvista-coloured-sequence>
`;
default:
console.warn('No Matching ProtvistaTrack Found.');
break;
Expand Down
Loading

0 comments on commit 56ab12d

Please sign in to comment.