@@ -177,11 +177,39 @@ export const StructureViewer: React.FC<StructureViewerProps> = ({
177177 let isBinary = false ;
178178 let finalPdbId = pdbId ;
179179
180- // Handle UniProt ID by loading AlphaFold structure directly
180+ // Handle UniProt ID by loading AlphaFold structure via API
181181 if ( uniprotId && ! pdbId ) {
182- // For UniProt IDs, we'll use AlphaFold exclusively for complete structures
183- url = `https://alphafold.ebi.ac.uk/files/AF-${ uniprotId } -F1-model_v4.cif` ;
184- isBinary = true ; // AlphaFold uses mmCIF format
182+ try {
183+ // Use the new AlphaFold API to get the structure URLs
184+ const response = await fetch ( `https://alphafold.ebi.ac.uk/api/prediction/${ uniprotId } ` ) ;
185+ if ( ! response . ok ) {
186+ throw new Error ( `AlphaFold API returned ${ response . status } : ${ response . statusText } ` ) ;
187+ }
188+
189+ const predictions = await response . json ( ) ;
190+ if ( ! predictions || predictions . length === 0 ) {
191+ throw new Error ( `No AlphaFold predictions found for UniProt ID: ${ uniprotId } ` ) ;
192+ }
193+
194+ // Use the first prediction (usually the canonical sequence)
195+ const prediction = predictions [ 0 ] ;
196+
197+ // Prefer CIF format over PDB for better structure quality
198+ if ( prediction . cifUrl ) {
199+ url = prediction . cifUrl ;
200+ isBinary = true ; // CIF format
201+ } else if ( prediction . pdbUrl ) {
202+ url = prediction . pdbUrl ;
203+ isBinary = false ; // PDB format
204+ } else {
205+ throw new Error ( `No structure files available for UniProt ID: ${ uniprotId } ` ) ;
206+ }
207+
208+ console . log ( `Loading AlphaFold structure from API: ${ url } ` ) ;
209+ } catch ( apiError ) {
210+ console . error ( 'AlphaFold API error:' , apiError ) ;
211+ throw new Error ( `Failed to fetch AlphaFold structure: ${ apiError } ` ) ;
212+ }
185213 } else if ( pdbContent ) {
186214 // Load from content string
187215 const blob = new Blob ( [ pdbContent ] , { type : 'text/plain' } ) ;
@@ -197,31 +225,78 @@ export const StructureViewer: React.FC<StructureViewerProps> = ({
197225 throw new Error ( 'No PDB ID, UniProt ID, URL, or content provided' ) ;
198226 }
199227
200- // Load the structure
228+ // Load the structure with better error handling
229+ console . log ( `Loading structure from: ${ url } , format: ${ isBinary ? 'mmcif' : 'pdb' } ` ) ;
230+
201231 const data = await pluginRef . current . builders . data . download (
202232 { url : Asset . Url ( url ) } ,
203233 { state : { isGhost : false } }
204234 ) ;
205235
206- // Parse the structure format
236+ if ( ! data ) {
237+ throw new Error ( 'Failed to download structure data' ) ;
238+ }
239+
240+ // Parse the structure format with improved format detection
241+ let format = isBinary ? 'mmcif' : 'pdb' ;
242+
243+ // Better format detection based on URL
244+ if ( url . toLowerCase ( ) . includes ( '.cif' ) ) {
245+ format = 'mmcif' ;
246+ } else if ( url . toLowerCase ( ) . includes ( '.bcif' ) ) {
247+ format = 'mmcif' ; // Binary CIF is also mmcif format
248+ } else if ( url . toLowerCase ( ) . includes ( '.pdb' ) ) {
249+ format = 'pdb' ;
250+ }
251+
207252 const trajectory = await pluginRef . current . builders . structure . parseTrajectory (
208253 data ,
209- isBinary ? 'mmcif' : 'pdb'
254+ format
210255 ) ;
211256
257+ if ( ! trajectory ) {
258+ throw new Error ( 'Failed to parse structure trajectory' ) ;
259+ }
260+
212261 // Create the structure
213262 const model = await pluginRef . current . builders . structure . createModel ( trajectory ) ;
263+
264+ if ( ! model ) {
265+ throw new Error ( 'Failed to create structure model' ) ;
266+ }
267+
214268 const structure = await pluginRef . current . builders . structure . createStructure ( model ) ;
215269
270+ if ( ! structure ) {
271+ throw new Error ( 'Failed to create structure representation' ) ;
272+ }
273+
216274 // Apply default representation (cartoon + ball-and-stick for ligands)
217- await pluginRef . current . builders . structure . representation . addRepresentation (
218- structure ,
219- {
220- type : 'cartoon' ,
221- color : 'chain-id' ,
222- size : 'uniform' ,
275+ try {
276+ await pluginRef . current . builders . structure . representation . addRepresentation (
277+ structure ,
278+ {
279+ type : 'cartoon' ,
280+ color : 'chain-id' ,
281+ size : 'uniform' ,
282+ }
283+ ) ;
284+ } catch ( reprError ) {
285+ console . warn ( 'Could not add cartoon representation, trying alternative:' , reprError ) ;
286+ // Try a simpler representation if cartoon fails
287+ try {
288+ await pluginRef . current . builders . structure . representation . addRepresentation (
289+ structure ,
290+ {
291+ type : 'ball-and-stick' ,
292+ color : 'element-symbol' ,
293+ }
294+ ) ;
295+ } catch ( altReprError ) {
296+ console . warn ( 'Alternative representation also failed:' , altReprError ) ;
297+ // Structure is loaded but no representation - this is still partially successful
223298 }
224- ) ;
299+ }
225300
226301 // Focus on the structure
227302 await PluginCommands . Camera . Reset ( pluginRef . current , { } ) ;
@@ -235,10 +310,28 @@ export const StructureViewer: React.FC<StructureViewerProps> = ({
235310 onStructureLoaded ?.( ) ;
236311
237312 } catch ( err ) {
238- const errorMsg = `Failed to load structure: ${ err } ` ;
313+ let errorMsg = 'Failed to load structure' ;
314+
315+ // Provide more specific error messages based on the error type
316+ if ( err instanceof Error ) {
317+ if ( err . message . includes ( '404' ) || err . message . includes ( 'Not Found' ) ) {
318+ errorMsg = `Structure not found. The ${ uniprotId ? 'UniProt ID' : 'PDB ID' } "${ uniprotId || pdbId } " may not have an available structure in the database.` ;
319+ } else if ( err . message . includes ( 'Invalid data cell' ) ) {
320+ errorMsg = `Structure file format error. The structure data appears to be corrupted or in an unsupported format.` ;
321+ } else if ( err . message . includes ( 'AlphaFold API' ) ) {
322+ errorMsg = `AlphaFold database error: ${ err . message } ` ;
323+ } else if ( err . message . includes ( 'Network' ) ) {
324+ errorMsg = `Network error: Unable to download structure. Please check your internet connection.` ;
325+ } else {
326+ errorMsg = `Structure loading error: ${ err . message } ` ;
327+ }
328+ } else {
329+ errorMsg = `Unknown error occurred while loading structure: ${ err } ` ;
330+ }
331+
239332 setError ( errorMsg ) ;
240333 onError ?.( errorMsg ) ;
241- console . error ( errorMsg ) ;
334+ console . error ( 'Structure loading error:' , err ) ;
242335 } finally {
243336 setIsLoading ( false ) ;
244337 }
0 commit comments