Skip to content

Commit

Permalink
Use BCIF files for AlphaFold models
Browse files Browse the repository at this point in the history
  • Loading branch information
midlik committed Aug 9, 2024
1 parent f0e8808 commit bd1c419
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file, following t

- Mol* core dependency updated to 4.5.0
- Solves the bug with Export Models
- Use BCIF files for AlphaFold models (unless `encoding: 'cif'`)
- PDBeMolstarPlugin.extensions.foldseek
- Added options `leftPanel`, `rightPanel`, `logPanel`, `tabs`
- Option `hideCanvasControls` accepts "trajectory" value (for multi-model structures)
Expand Down
5 changes: 5 additions & 0 deletions src/app/plugin-custom-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ export interface PluginCustomState {
colorCounters: number[],
alphafold: {
apiData: {
/** URL of BCIF file */
bcif: string,
/** URL of CIF file */
cif: string,
/** URL of PAE image */
pae: string,
/** Length of UniProt sequence */
length: number,
},
length: number,
Expand Down
45 changes: 23 additions & 22 deletions src/app/superposition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { PluginContext } from 'molstar/lib/mol-plugin/context';
import { MolScriptBuilder as MS } from 'molstar/lib/mol-script/language/builder';
import { Script } from 'molstar/lib/mol-script/script';
import { State, StateObjectRef, StateObjectSelector } from 'molstar/lib/mol-state';
import { Task } from 'molstar/lib/mol-task';
import { Asset } from 'molstar/lib/mol-util/assets';
import { Color, ColorListEntry } from 'molstar/lib/mol-util/color/color';
import { ColorListName, ColorLists } from 'molstar/lib/mol-util/color/lists';
Expand Down Expand Up @@ -55,6 +54,7 @@ export async function initSuperposition(plugin: PluginContext, completeSubject?:
colorCounters: [],
alphafold: {
apiData: {
bcif: '',
cif: '',
pae: '',
length: 0
Expand All @@ -79,8 +79,8 @@ export async function initSuperposition(plugin: PluginContext, completeSubject?:
if (!customState.superpositionState.segmentData) return;

if (!customState.initParams!.moleculeId) throw new Error('initParams.moleculeId is not defined');
const afStrUrls = await getAfUrl(plugin, customState.initParams!.moleculeId);
if (afStrUrls) customState.superpositionState.alphafold.apiData = afStrUrls;
const afApiData = await getAfUrls(plugin, customState.initParams!.moleculeId);
if (afApiData) customState.superpositionState.alphafold.apiData = afApiData;

segmentData.forEach(() => {
customState.superpositionState!.loadedStructs.push([]);
Expand Down Expand Up @@ -127,31 +127,32 @@ function createCarbVisLabel(carbLigNamesAndCount: any) {

return compList.join(', ');
}
async function getAfUrl(plugin: PluginContext, accession: string) {
let apiResponse: any;
let apiData: any;
await plugin.runTask(Task.create('Get AlphaFold URL', async ctx => {
try {
apiResponse = await plugin.fetch({ url: `https://alphafold.ebi.ac.uk/api/prediction/${accession}`, type: 'json' }).runInContext(ctx);
if (apiResponse && apiResponse?.[0].bcifUrl) {
apiData = {
cif: apiResponse?.[0].cifUrl,
pae: apiResponse?.[0].paeImageUrl,
length: apiResponse?.[0].uniprotEnd
};
}
} catch (e) {
// console.warn(e);
}
}));

return apiData;
type AfApiData = NonNullable<PluginCustomState['superpositionState']>['alphafold']['apiData']

async function getAfUrls(plugin: PluginContext, accession: string): Promise<AfApiData | undefined> {
const url = `https://alphafold.ebi.ac.uk/api/prediction/${accession}`;
try {
const apiResponse = await plugin.runTask(plugin.fetch({ url, type: 'json' }));
if (apiResponse?.[0].bcifUrl) {
return {
bcif: apiResponse[0].bcifUrl,
cif: apiResponse[0].cifUrl,
pae: apiResponse[0].paeImageUrl,
length: apiResponse[0].uniprotEnd
};
}
} catch { }
console.warn(`Failed to get AFDB URLs for ${accession}: ${url}`);
return undefined;
}

export async function loadAfStructure(plugin: PluginContext) {
const customState = PluginCustomState(plugin);
if (!customState.superpositionState) throw new Error('customState.superpositionState has not been initialized');
const { structure } = await loadStructure(plugin, customState.superpositionState.alphafold.apiData.cif, 'mmcif', false);
const isBinary = customState.initParams?.encoding === 'bcif';
const url = isBinary ? customState.superpositionState.alphafold.apiData.bcif : customState.superpositionState.alphafold.apiData.cif;
const { structure } = await loadStructure(plugin, url, 'mmcif', isBinary);
const strInstance = structure;
if (!strInstance) return false;

Expand Down
2 changes: 1 addition & 1 deletion src/app/ui/alphafold-superposition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export class AlphafoldSuperpositionControls extends CollapsableControls {
componentDidMount() {
this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, sel => {
const superpositionState = PluginCustomState(this.plugin).superpositionState;
if (superpositionState && superpositionState.alphafold.apiData.cif && superpositionState.alphafold.apiData.cif !== '') {
if (superpositionState?.alphafold.apiData.cif && superpositionState?.alphafold.apiData.bcif) {
this.setState({ isHidden: false });
}
});
Expand Down

0 comments on commit bd1c419

Please sign in to comment.