JAL-4366 JAL-728 simple hack to use 3di matrix when gecos-3di is enabled
[jalview.git] / src / jalview / gui / StructureChooser.java
index 5cd339b..666ff74 100644 (file)
@@ -28,10 +28,11 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.concurrent.Callable;
+import java.util.Map;
 import java.util.concurrent.Executors;
 
 import javax.swing.JCheckBox;
 import java.util.concurrent.Executors;
 
 import javax.swing.JCheckBox;
@@ -45,11 +46,16 @@ import javax.swing.table.AbstractTableModel;
 
 import com.stevesoft.pat.Regex;
 
 
 import com.stevesoft.pat.Regex;
 
+import jalview.analysis.AlignmentUtils;
+import jalview.api.AlignmentViewPanel;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.bin.Console;
 import jalview.bin.Jalview;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.bin.Console;
 import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JmolParser;
 import jalview.fts.api.FTSData;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JmolParser;
 import jalview.fts.api.FTSData;
@@ -60,11 +66,11 @@ import jalview.fts.core.FTSRestRequest;
 import jalview.fts.core.FTSRestResponse;
 import jalview.fts.service.pdb.PDBFTSRestClient;
 import jalview.fts.service.threedbeacons.TDB_FTSData;
 import jalview.fts.core.FTSRestResponse;
 import jalview.fts.service.pdb.PDBFTSRestClient;
 import jalview.fts.service.threedbeacons.TDB_FTSData;
+import jalview.gui.StructureViewer.ViewerType;
 import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
 import jalview.gui.structurechooser.StructureChooserQuerySource;
 import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
 import jalview.io.DataSourceType;
 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;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.jbgui.FilterOption;
@@ -78,7 +84,6 @@ import jalview.util.StringUtils;
 import jalview.ws.DBRefFetcher;
 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
 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;
 
 import jalview.ws.seqfetcher.DbSourceProxy;
 import jalview.ws.sifts.SiftsSettings;
 
@@ -135,6 +140,12 @@ public class StructureChooser extends GStructureChooser
 
   private boolean showChooserGUI = true;
 
 
   private boolean showChooserGUI = true;
 
+  /**
+   * when true, queries to external services are supressed (no SIFTs, no PDBe,
+   * no 3D-Beacons, etc)
+   */
+  private boolean dontQueryServices = false;
+
   private static StructureViewer lastTargetedView = null;
 
   public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
   private static StructureViewer lastTargetedView = null;
 
   public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
@@ -146,6 +157,13 @@ public class StructureChooser extends GStructureChooser
   public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
           AlignmentPanel ap, boolean showGUI)
   {
   public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
           AlignmentPanel ap, boolean showGUI)
   {
+    this(selectedSeqs, selectedSeq, ap, showGUI, false);
+  }
+
+  public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
+          AlignmentPanel ap, boolean showGUI, boolean dontQueryServices)
+  {
+
     // which FTS engine to use
     data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
     initDialog();
     // which FTS engine to use
     data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
     initDialog();
@@ -155,6 +173,7 @@ public class StructureChooser extends GStructureChooser
     this.selectedSequences = selectedSeqs;
     this.progressIndicator = (ap == null) ? null : ap.alignFrame;
     this.showChooserGUI = showGUI;
     this.selectedSequences = selectedSeqs;
     this.progressIndicator = (ap == null) ? null : ap.alignFrame;
     this.showChooserGUI = showGUI;
+    this.dontQueryServices = dontQueryServices;
     init();
 
   }
     init();
 
   }
@@ -226,17 +245,24 @@ public class StructureChooser extends GStructureChooser
       }
     });
 
       }
     });
 
-    Executors.defaultThreadFactory().newThread(new Runnable()
+    if (!dontQueryServices)
     {
     {
-      @Override
-      public void run()
+      Executors.defaultThreadFactory().newThread(new Runnable()
       {
       {
-        populateSeqsWithoutSourceDBRef();
-        initialStructureDiscovery();
-      }
-
-    }).start();
+        @Override
+        public void run()
+        {
+          populateSeqsWithoutSourceDBRef();
+          initialStructureDiscovery();
+        }
 
 
+      }).start();
+    }
+    else
+    {
+      Console.debug(
+              "Structure chooser not querying services to discover metadata.");
+    }
   }
 
   // called by init
   }
 
   // called by init
@@ -342,7 +368,7 @@ public class StructureChooser extends GStructureChooser
     };
 
     // fetch db refs if OK pressed
     };
 
     // fetch db refs if OK pressed
-    final Callable discoverCanonicalDBrefs = () -> {
+    final Runnable discoverCanonicalDBrefs = () -> {
       btn_queryTDB.setEnabled(false);
       populateSeqsWithoutSourceDBRef();
 
       btn_queryTDB.setEnabled(false);
       populateSeqsWithoutSourceDBRef();
 
@@ -364,14 +390,12 @@ public class StructureChooser extends GStructureChooser
         // call finished action directly
         afterDbRefFetch.finished();
       }
         // call finished action directly
         afterDbRefFetch.finished();
       }
-      return null;
     };
     };
-    final Callable revertview = () -> {
+    final Runnable revertview = () -> {
       if (lastSelected != null)
       {
         cmb_filterOption.setSelectedItem(lastSelected);
       }
       if (lastSelected != null)
       {
         cmb_filterOption.setSelectedItem(lastSelected);
       }
-      return null;
     };
     int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
             THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
     };
     int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
             THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
@@ -503,7 +527,7 @@ public class StructureChooser extends GStructureChooser
         }
       } catch (Exception e)
       {
         }
       } catch (Exception e)
       {
-        e.printStackTrace();
+        Console.printStackTrace(e);
         errors.add(e.getMessage());
         continue;
       }
         errors.add(e.getMessage());
         continue;
       }
@@ -540,9 +564,18 @@ public class StructureChooser extends GStructureChooser
         {
           errorMsg.append(error).append("\n");
         }
         {
           errorMsg.append(error).append("\n");
         }
-        JvOptionPane.showMessageDialog(this, errorMsg.toString(),
-                MessageManager.getString("label.pdb_web-service_error"),
-                JvOptionPane.ERROR_MESSAGE);
+        if (!Jalview.isHeadlessMode())
+        {
+          JvOptionPane.showMessageDialog(this, errorMsg.toString(),
+                  MessageManager.getString("label.pdb_web-service_error"),
+                  JvOptionPane.ERROR_MESSAGE);
+        }
+        else
+        {
+          Console.error(
+                  MessageManager.getString("label.pdb_web-service_error"));
+          Console.debug(errorMsg.toString());
+        }
       }
     }
   }
       }
     }
   }
@@ -603,7 +636,7 @@ public class StructureChooser extends GStructureChooser
 
           } catch (Exception e)
           {
 
           } catch (Exception e)
           {
-            e.printStackTrace();
+            Console.debugPrintStackTrace(e);
             errors.add(e.getMessage());
             continue;
           }
             errors.add(e.getMessage());
             continue;
           }
@@ -736,16 +769,18 @@ public class StructureChooser extends GStructureChooser
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
       String fileName = chooser.getSelectedFile().getPath();
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
       String fileName = chooser.getSelectedFile().getPath();
-      try {
+      try
+      {
         PAEContactMatrix.validateContactMatrixFile(fileName);
       } catch (Exception thr)
       {
         JvOptionPane.showInternalMessageDialog(this, MessageManager
                 .formatMessage("label.couldnt_load_file", new Object[]
         PAEContactMatrix.validateContactMatrixFile(fileName);
       } catch (Exception thr)
       {
         JvOptionPane.showInternalMessageDialog(this, MessageManager
                 .formatMessage("label.couldnt_load_file", new Object[]
-                { fileName})+"<br>"+thr.getLocalizedMessage(),
+                { fileName }) + "<br>" + thr.getLocalizedMessage(),
                 MessageManager.getString("label.error_loading_file"),
                 JvOptionPane.WARNING_MESSAGE);
                 MessageManager.getString("label.error_loading_file"),
                 JvOptionPane.WARNING_MESSAGE);
-        Console.error("Couldn't import "+fileName+" as a PAE matrix",thr);
+        Console.error("Couldn't import " + fileName + " as a PAE matrix",
+                thr);
         return;
       }
       localPdbPaeMatrixFileName = fileName;
         return;
       }
       localPdbPaeMatrixFileName = fileName;
@@ -978,8 +1013,14 @@ public class StructureChooser extends GStructureChooser
               .getFTSDataFor(getResultTable(), selectedRow,
                       discoveredStructuresSet);
       String pageUrl = row.getModelViewUrl();
               .getFTSDataFor(getResultTable(), selectedRow,
                       discoveredStructuresSet);
       String pageUrl = row.getModelViewUrl();
+
       JPopupMenu popup = new JPopupMenu("3D Beacons");
       JMenuItem viewUrl = new JMenuItem("View model web page");
       JPopupMenu popup = new JPopupMenu("3D Beacons");
       JMenuItem viewUrl = new JMenuItem("View model web page");
+      if (pageUrl == null || "".equals(pageUrl.trim()))
+      {
+        viewUrl.setEnabled(false);
+        viewUrl.setText("No model page available.");
+      }
       viewUrl.addActionListener(new ActionListener()
       {
         @Override
       viewUrl.addActionListener(new ActionListener()
       {
         @Override
@@ -1205,8 +1246,9 @@ public class StructureChooser extends GStructureChooser
     btn_newView.setEnabled(false);
     btn_cancel.setEnabled(false);
     actionsPanel.setEnabled(false);
     btn_newView.setEnabled(false);
     btn_cancel.setEnabled(false);
     actionsPanel.setEnabled(false);
-    
-    final String progress=MessageManager.getString("label.working_ellipsis");
+
+    final String progress = MessageManager
+            .getString("label.working_ellipsis");
     setProgressBar(progress, progress.hashCode());
     Runnable viewStruc = new Runnable()
     {
     setProgressBar(progress, progress.hashCode());
     Runnable viewStruc = new Runnable()
     {
@@ -1304,7 +1346,8 @@ public class StructureChooser extends GStructureChooser
           String pdbFilename = selectedPdbFileName;
 
           StructureChooser.openStructureFileForSequence(ssm, sc, ap,
           String pdbFilename = selectedPdbFileName;
 
           StructureChooser.openStructureFileForSequence(ssm, sc, ap,
-                  selectedSequence, true, pdbFilename, tft, paeFilename);
+                  selectedSequence, true, pdbFilename, tft, paeFilename,
+                  true);
         }
         SwingUtilities.invokeLater(new Runnable()
         {
         }
         SwingUtilities.invokeLater(new Runnable()
         {
@@ -1364,6 +1407,15 @@ public class StructureChooser extends GStructureChooser
           StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
           final AlignmentPanel alignPanel, SequenceI[] sequences)
   {
           StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
           final AlignmentPanel alignPanel, SequenceI[] sequences)
   {
+    return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
+            sequences, null);
+  }
+
+  private StructureViewer launchStructureViewer(
+          StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
+          final AlignmentPanel alignPanel, SequenceI[] sequences,
+          ViewerType viewerType)
+  {
     long progressId = sequences.hashCode();
     setProgressBar(MessageManager
             .getString("status.launching_3d_structure_viewer"), progressId);
     long progressId = sequences.hashCode();
     setProgressBar(MessageManager
             .getString("status.launching_3d_structure_viewer"), progressId);
@@ -1371,6 +1423,12 @@ public class StructureChooser extends GStructureChooser
     boolean superimpose = chk_superpose.isSelected();
     theViewer.setSuperpose(superimpose);
 
     boolean superimpose = chk_superpose.isSelected();
     theViewer.setSuperpose(superimpose);
 
+    // if we're running in --headless mode make this viewer synchronous
+    if (Jalview.isHeadlessMode())
+    {
+      theViewer.setAsync(false);
+    }
+
     /*
      * remember user's choice of superimpose or not
      */
     /*
      * remember user's choice of superimpose or not
      */
@@ -1428,7 +1486,8 @@ public class StructureChooser extends GStructureChooser
               MessageManager.getString(
                       "status.fetching_3d_structures_for_selected_entries"),
               progressId);
               MessageManager.getString(
                       "status.fetching_3d_structures_for_selected_entries"),
               progressId);
-      theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel);
+      theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
+              viewerType);
     }
     else
     {
     }
     else
     {
@@ -1436,7 +1495,8 @@ public class StructureChooser extends GStructureChooser
               "status.fetching_3d_structures_for",
               pdbEntriesToView[0].getId()), progressId);
       // Can we pass a pre-computeMappinged pdbFile?
               "status.fetching_3d_structures_for",
               pdbEntriesToView[0].getId()), progressId);
       // Can we pass a pre-computeMappinged pdbFile?
-      theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
+      theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
+              viewerType);
     }
     setProgressBar(null, progressId);
     // remember the last viewer we used...
     }
     setProgressBar(null, progressId);
     // remember the last viewer we used...
@@ -1505,7 +1565,8 @@ public class StructureChooser extends GStructureChooser
             // for moment, it will work fine as is because it is self-contained
             String searchTerm = text.toLowerCase(Locale.ROOT);
             searchTerm = searchTerm.split(":")[0];
             // for moment, it will work fine as is because it is self-contained
             String searchTerm = text.toLowerCase(Locale.ROOT);
             searchTerm = searchTerm.split(":")[0];
-            // System.out.println(">>>>> search term : " + searchTerm);
+            // jalview.bin.Console.outPrintln(">>>>> search term : " +
+            // searchTerm);
             List<FTSDataColumnI> wantedFields = new ArrayList<>();
             FTSRestRequest pdbRequest = new FTSRestRequest();
             pdbRequest.setAllowEmptySeq(false);
             List<FTSDataColumnI> wantedFields = new ArrayList<>();
             FTSRestRequest pdbRequest = new FTSRestRequest();
             pdbRequest.setAllowEmptySeq(false);
@@ -1677,20 +1738,21 @@ public class StructureChooser extends GStructureChooser
   @Override
   public void setProgressBar(String message, long id)
   {
   @Override
   public void setProgressBar(String message, long id)
   {
-    if (!Platform.isHeadless())
+    if (!Platform.isHeadless() && progressBar != null)
       progressBar.setProgressBar(message, id);
   }
 
   @Override
   public void registerHandler(long id, IProgressIndicatorHandler handler)
   {
       progressBar.setProgressBar(message, id);
   }
 
   @Override
   public void registerHandler(long id, IProgressIndicatorHandler handler)
   {
-    progressBar.registerHandler(id, handler);
+    if (progressBar != null)
+      progressBar.registerHandler(id, handler);
   }
 
   @Override
   public boolean operationInProgress()
   {
   }
 
   @Override
   public boolean operationInProgress()
   {
-    return progressBar.operationInProgress();
+    return progressBar == null ? false : progressBar.operationInProgress();
   }
 
   public JalviewStructureDisplayI getOpenedStructureViewer()
   }
 
   public JalviewStructureDisplayI getOpenedStructureViewer()
@@ -1737,26 +1799,77 @@ public class StructureChooser extends GStructureChooser
   public static void openStructureFileForSequence(
           StructureSelectionManager ssm, StructureChooser sc,
           AlignmentPanel ap, SequenceI seq, boolean prompt,
   public static void openStructureFileForSequence(
           StructureSelectionManager ssm, StructureChooser sc,
           AlignmentPanel ap, SequenceI seq, boolean prompt,
-          String sFilename, TFType tft, String paeFilename)
+          String sFilename, TFType tft, String paeFilename,
+          boolean doXferSettings)
   {
   {
-    boolean headless = false;
+    openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
+            paeFilename, false, true, doXferSettings, null);
+  }
+
+  public static StructureViewer openStructureFileForSequence(
+          StructureSelectionManager ssm, StructureChooser sc,
+          AlignmentPanel ap, SequenceI seq, boolean prompt,
+          String sFilename, TFType tft, String paeFilename,
+          boolean forceHeadless, boolean showRefAnnotations,
+          boolean doXferSettings, ViewerType viewerType)
+  {
+    StructureViewer sv = null;
+    boolean headless = forceHeadless;
     if (sc == null)
     {
     if (sc == null)
     {
-      headless = true;
-      sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
+      // headless = true;
+      prompt = false;
+      // suppress structure viewer's external service queries
+      sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false,
+              true);
     }
     if (ssm == null)
     }
     if (ssm == null)
+    {
       ssm = ap.getStructureSelectionManager();
       ssm = ap.getStructureSelectionManager();
+    }
 
     PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
             sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
 
     PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
             sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
-            tft, paeFilename);
+            tft, paeFilename, doXferSettings);
+
+    // if headless, "false" in the sc constructor above will avoid GUI behaviour
+    // in sc.launchStructureViewer()
+    if (!headless && !(viewerType == null))
+    {
+      sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
+              new SequenceI[]
+              { seq }, viewerType);
+    }
+
+    sc.mainFrame.dispose();
 
 
-    StructureViewer sViewer = sc.launchStructureViewer(ssm,
-            new PDBEntry[]
-            { fileEntry }, ap, new SequenceI[] { seq });
+    if (showRefAnnotations)
+    {
+      showReferenceAnnotationsForSequence(ap.alignFrame, seq);
+    }
+
+    return sv;
+  }
+
+  public static void showReferenceAnnotationsForSequence(AlignFrame af,
+          SequenceI sequence)
+  {
+    AlignViewport av = af.getCurrentView();
+    AlignmentI al = av.getAlignment();
+
+    List<SequenceI> forSequences = new ArrayList<>();
+    forSequences.add(sequence);
+    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
+    AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
+            candidates, al);
+    final SequenceGroup selectionGroup = av.getSelectionGroup();
+    AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
+    for (AlignmentViewPanel ap : af.getAlignPanels())
+    {
+      // required to readjust the height and position of the PAE
+      // annotation
+      ap.adjustAnnotationHeight();
+    }
 
 
-    if (headless)
-      sc.mainFrame.dispose();
   }
 }
   }
 }