From 0c08a3e1a37eca3a7c011a56f0c353258b0e8020 Mon Sep 17 00:00:00 2001 From: James Procter Date: Mon, 1 May 2023 13:54:50 +0100 Subject: [PATCH] JAL-3858 report errors when trying to parse JSON to extract PAE and raise a warning dialog when user provided PAE file cannot be read via structure chooser --- src/jalview/ext/jmol/JmolParser.java | 26 ++++-- src/jalview/gui/StructureChooser.java | 21 ++++- .../ws/datamodel/alphafold/PAEContactMatrix.java | 83 ++++++++++++++++++-- 3 files changed, 115 insertions(+), 15 deletions(-) diff --git a/src/jalview/ext/jmol/JmolParser.java b/src/jalview/ext/jmol/JmolParser.java index f0e477c..25b52b4 100644 --- a/src/jalview/ext/jmol/JmolParser.java +++ b/src/jalview/ext/jmol/JmolParser.java @@ -47,6 +47,7 @@ import jalview.datamodel.SequenceI; import jalview.datamodel.annotations.AlphaFoldAnnotationRowBuilder; import jalview.datamodel.annotations.AnnotationRowBuilder; import jalview.io.DataSourceType; +import jalview.io.FileFormatException; import jalview.io.FileParse; import jalview.io.StructureFile; import jalview.schemes.ResidueProperties; @@ -303,18 +304,29 @@ public class JmolParser extends StructureFile implements JmolStatusListener // add a PAEMatrix if set (either by above or otherwise) if (hasPAEMatrix()) { - Alignment al = new Alignment(prot.toArray(new SequenceI[0])); - EBIAlfaFold.addAlphaFoldPAE(al, new File(this.getPAEMatrix()), 0, - null, false, false); - - if (al.getAlignmentAnnotation() != null) + try { - for (AlignmentAnnotation alann : al.getAlignmentAnnotation()) + Alignment al = new Alignment(prot.toArray(new SequenceI[0])); + EBIAlfaFold.addAlphaFoldPAE(al, new File(this.getPAEMatrix()), 0, + null, false, false); + + if (al.getAlignmentAnnotation() != null) { - annotations.add(alann); + for (AlignmentAnnotation alann : al.getAlignmentAnnotation()) + { + annotations.add(alann); + } } + } catch (Throwable ff) + { + Console.error("Couldn't import PAE Matrix from " + getPAEMatrix(), + ff); + warningMessage += "Couldn't import PAE Matrix" + + getNewlineString() + ff.getLocalizedMessage() + + getNewlineString(); } } + } catch (OutOfMemoryError er) { System.out.println( diff --git a/src/jalview/gui/StructureChooser.java b/src/jalview/gui/StructureChooser.java index 3fce931..03f9269 100644 --- a/src/jalview/gui/StructureChooser.java +++ b/src/jalview/gui/StructureChooser.java @@ -64,6 +64,7 @@ import jalview.gui.structurechooser.PDBStructureChooserQuerySource; import jalview.gui.structurechooser.StructureChooserQuerySource; import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource; import jalview.io.DataSourceType; +import jalview.io.FileFormatException; import jalview.io.JalviewFileChooser; import jalview.io.JalviewFileView; import jalview.jbgui.FilterOption; @@ -76,6 +77,8 @@ import jalview.util.Platform; import jalview.util.StringUtils; import jalview.ws.DBRefFetcher; import jalview.ws.DBRefFetcher.FetchFinishedListenerI; +import jalview.ws.datamodel.alphafold.PAEContactMatrix; +import jalview.ws.dbsources.EBIAlfaFold; import jalview.ws.seqfetcher.DbSourceProxy; import jalview.ws.sifts.SiftsSettings; @@ -699,7 +702,7 @@ public class StructureChooser extends GStructureChooser } /** - * Handles action event for btn_pdbFromFile + * Handles action event for btn_paeMatrixFile */ @Override protected void paeMatrixFile_actionPerformed() @@ -728,10 +731,24 @@ public class StructureChooser extends GStructureChooser "label.load_pae_matrix_file_associate_with_structure", pdbFile.getName())); + // TODO convert to Callable/Promise int value = chooser.showOpenDialog(null); if (value == JalviewFileChooser.APPROVE_OPTION) { - localPdbPaeMatrixFileName = chooser.getSelectedFile().getPath(); + String fileName = chooser.getSelectedFile().getPath(); + try { + PAEContactMatrix.validateContactMatrixFile(fileName); + } catch (Exception thr) + { + JvOptionPane.showInternalMessageDialog(this, MessageManager + .formatMessage("label.couldnt_load_file", new Object[] + { fileName})+"
"+thr.getLocalizedMessage(), + MessageManager.getString("label.error_loading_file"), + JvOptionPane.WARNING_MESSAGE); + Console.error("Couldn't import "+fileName+" as a PAE matrix",thr); + return; + } + localPdbPaeMatrixFileName = fileName; Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName); } validateAssociationFromFile(); diff --git a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java index 41e677a..22dd7fb 100644 --- a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java +++ b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java @@ -1,6 +1,10 @@ package jalview.ws.datamodel.alphafold; import java.awt.Color; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.BitSet; import java.util.HashMap; @@ -8,6 +12,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.json.simple.JSONObject; + import jalview.analysis.AverageDistanceEngine; import jalview.bin.Console; import jalview.datamodel.BinaryNode; @@ -15,8 +21,13 @@ import jalview.datamodel.ContactListI; import jalview.datamodel.ContactListImpl; import jalview.datamodel.ContactListProviderI; import jalview.datamodel.ContactMatrixI; +import jalview.datamodel.SequenceDummy; import jalview.datamodel.SequenceI; +import jalview.io.DataSourceType; +import jalview.io.FileFormatException; +import jalview.io.FileParse; import jalview.util.MapUtils; +import jalview.ws.dbsources.EBIAlfaFold; public class PAEContactMatrix implements ContactMatrixI { @@ -47,7 +58,7 @@ public class PAEContactMatrix implements ContactMatrixI } @SuppressWarnings("unchecked") - public PAEContactMatrix(SequenceI _refSeq, Map pae_obj) + public PAEContactMatrix(SequenceI _refSeq, Map pae_obj) throws FileFormatException { setRefSeq(_refSeq); // convert the lists to primitive arrays and store @@ -101,9 +112,17 @@ public class PAEContactMatrix implements ContactMatrixI @SuppressWarnings("unchecked") private void parse_version_2_pAE(Map pae_obj) { - // this is never going to be reached by the integer rounding.. or is it ? - maxscore = ((Double) MapUtils.getFirst(pae_obj, - "max_predicted_aligned_error", "max_pae")).floatValue(); + maxscore = -1; + // look for a maxscore element - if there is one... + try + { + // this is never going to be reached by the integer rounding.. or is it ? + maxscore = ((Double) MapUtils.getFirst(pae_obj, + "max_predicted_aligned_error", "max_pae")).floatValue(); + } catch (Throwable t) + { + // ignore if a key is not found. + } List> scoreRows = ((List>) MapUtils .getFirst(pae_obj, "predicted_aligned_error", "pae")); elements = new float[scoreRows.size()][scoreRows.size()]; @@ -114,10 +133,20 @@ public class PAEContactMatrix implements ContactMatrixI while (scores.hasNext()) { Object d = scores.next(); + if (d instanceof Double) + { elements[row][col++] = ((Double) d).longValue(); + } else + { elements[row][col++] = (float) ((Long) d).longValue(); + } + + if (maxscore < elements[row][col - 1]) + { + maxscore = elements[row][col - 1]; + } } row++; col = 0; @@ -139,10 +168,26 @@ public class PAEContactMatrix implements ContactMatrixI // dataset refSeq Iterator rows = ((List) pae_obj.get("residue1")).iterator(); Iterator cols = ((List) pae_obj.get("residue2")).iterator(); + // two pass - to allocate the elements array + while (rows.hasNext()) + { + int row = rows.next().intValue(); + int col = cols.next().intValue(); + if (maxrow < row) + { + maxrow = row; + } + if (maxcol < col) + { + maxcol = col; + } + + } + rows = ((List) pae_obj.get("residue1")).iterator(); + cols = ((List) pae_obj.get("residue2")).iterator(); Iterator scores = ((List) pae_obj.get("distance")) .iterator(); - // assume square matrix - elements = new float[length][length]; + elements = new float[maxrow][maxcol]; while (scores.hasNext()) { float escore = scores.next().floatValue(); @@ -373,4 +418,30 @@ public class PAEContactMatrix implements ContactMatrixI { return treeType; } + + public static void validateContactMatrixFile(String fileName) throws FileFormatException,IOException + { + FileInputStream infile=null; + try { + infile = new FileInputStream(new File(fileName)); + } catch (Throwable t) + { + new IOException("Couldn't open "+fileName,t); + } + + + JSONObject paeDict=null; + try { + paeDict = EBIAlfaFold.parseJSONtoPAEContactMatrix(infile); + } catch (Throwable t) + { + new FileFormatException("Couldn't parse "+fileName+" as a JSON dict or array containing a dict"); + } + + PAEContactMatrix matrix = new PAEContactMatrix(new SequenceDummy("Predicted"), (Map)paeDict); + if (matrix.getWidth()<=0) + { + throw new FileFormatException("No data in PAE matrix read from '"+fileName+"'"); + } + } } -- 1.7.10.2