JAL-2422 JAL-3551 viewer text/variables generalised, Pymol paths added
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 11 May 2020 13:12:03 +0000 (14:12 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 11 May 2020 13:12:03 +0000 (14:12 +0100)
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/ext/pymol/PymolManager.java
src/jalview/gui/AppJmol.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/Preferences.java
src/jalview/gui/StructureViewerBase.java
src/jalview/jbgui/GPreferences.java
test/jalview/ext/pymol/PymolManagerTest.java

index 51500c6..f973ec4 100644 (file)
@@ -268,10 +268,10 @@ label.autoadd_secstr = Add secondary structure annotation to alignment
 label.autoadd_temp = Add Temperature Factor annotation to alignment
 label.structure_viewer = Default structure viewer
 label.double_click_to_browse = Double-click to browse for file
-label.chimera_path = Path to {0} program
-label.chimera_path_tip = Jalview will first try any path entered here, else standard installation locations.<br>Double-click to browse for file.
-label.invalid_chimera_path = Chimera path not found or not executable
-label.chimera_missing = Chimera structure viewer not found.<br/>Please enter the path to Chimera (if installed),<br/>or download and install UCSF Chimera.
+label.viewer_path = Path to {0} program
+label.viewer_path_tip = Jalview will first try any path entered here, else standard installation locations.<br>Double-click to browse for file.
+label.invalid_viewer_path = Path not found or not executable
+label.viewer_missing = Structure viewer not found.<br/>Please enter the path to the executable (if installed),<br/>or download and install the program.
 label.chimera_failed = Error opening Chimera - is it installed?\nCheck path in Preferences, Structure
 label.min_colour = Minimum Colour
 label.max_colour = Maximum Colour
@@ -623,7 +623,6 @@ label.editing = Editing
 label.web_services = Web Services
 label.right_click_to_edit_currently_selected_parameter = Right click to edit currently selected parameter.
 label.let_jmol_manage_structure_colours = Let Jmol manage structure colours
-label.let_chimera_manage_structure_colours = Let Chimera manage structure colours
 label.fetch_chimera_attributes = Fetch Chimera attributes
 label.fetch_chimera_attributes_tip = Copy Chimera attribute to Jalview feature
 label.marks_leaves_tree_not_associated_with_sequence = Marks leaves of tree not associated with a sequence
@@ -710,7 +709,8 @@ label.associate_nodes_with = Associate Nodes With
 label.link_name = Link Name
 label.pdb_file = PDB file
 label.colour_with_jmol = Colour with Jmol
-label.colour_with_chimera = Colour with Chimera
+label.let_viewer_manage_structure_colours = Let viewer manage structure colours
+label.colour_with_viewer = Colour in structure viewer
 label.superpose_structures = Superpose Structures
 error.superposition_failed = Superposition failed: {0}
 label.insufficient_residues = Not enough aligned residues ({0}) to perform superposition
index 199a65d..2208756 100644 (file)
@@ -1158,7 +1158,6 @@ action.export_features=Exportar Caracter
 error.invalid_regex=Expresión regular inválida
 label.autoadd_temp=Añadir anotación factor de temperatura al alineamiento
 label.double_click_to_browse = Haga doble clic para buscar fichero 
-label.chimera_path_tip=Jalview intentará primero las rutas introducidas aquí, Y si no las rutas usuales de instalación
 label.structure_chooser=Selector de Estructuras
 label.structure_chooser_manual_association=Selector de Estructuras - asociación manual
 label.threshold_filter=Filtro de Umbral
@@ -1166,11 +1165,11 @@ label.add_reference_annotations=A
 label.hide_insertions=Ocultar Inserciones
 info.change_threshold_mode_to_enable=Cambiar Modo de Umbral para Habilitar
 label.separate_multiple_query_values=Introducir uno o mas {0}s separados por punto y coma ";"
-label.let_chimera_manage_structure_colours=Deja que Chimera maneje colores de estructuras
 label.fetch_chimera_attributes = Buscar atributos desde Chimera
 label.fetch_chimera_attributes_tip = Copiar atributo de Chimera a característica de Jalview
 label.view_rna_structure=Estructura 2D VARNA
-label.colour_with_chimera=Colorear con Chimera
+label.colour_with_viewer = Colorear con visualizador de estructuras
+label.let_viewer_manage_structure_colours = Deja que el visualizador maneje los colores de estructuras
 label.superpose_structures = Superponer estructuras
 error.superposition_failed = Superposición fallido: {0}
 label.insufficient_residues = Residuos alineados ({0}) insuficentes para superponer
@@ -1181,7 +1180,6 @@ tooltip.aacon_settings=Cambiar ajustes para c
 label.mark_as_representative=Marcar como representativa
 label.include_description=Incluir Descripción
 label.for=para
-label.invalid_chimera_path=Ruta de Chimera no encontrada o no ejecutable
 info.search_in_annotation_label=Buscar en etiqueta de {0}
 info.search_in_annotation_description=Buscar en descripción de {0}
 label.select_many_views=Seleccionar múltiples vistas
@@ -1203,7 +1201,10 @@ label.configure_displayed_columns=Configurar Columnas Mostradas
 label.aacon_calculations=cálculos AACon
 label.pdb_web-service_error=Error de servicio web PDB
 exception.unable_to_detect_internet_connection=Jalview no puede detectar una conexión a Internet
-label.chimera_path=Ruta de acceso a {0}
+label.viewer_path=Ruta de acceso a {0}
+label.viewer_path_tip=Jalview intentará primero las rutas introducidas aquí, Y si no las rutas usuales de instalación
+label.invalid_viewer_path=Ruta no encontrada o no ejecutable
+label.viewer_missing=Visualizador de estructura no encontrado.<br/>Por favor, introduzca la ruta de la ejecutable,<br/>o descargar e instalar el programa.
 warn.delete_all=<html>Borrar todas las secuencias cerrará la ventana del alineamiento.<br>Confirmar o Cancelar.
 label.select_all=Seleccionar Todos
 label.alpha_helix=Hélice Alfa
@@ -1219,7 +1220,6 @@ label.aacon_settings=Cambiar Ajustes AACon...
 tooltip.aacon_calculations=Actualizar cálculos AACon automáticamente.
 info.select_filter_option=Escoger Opción de Filtro / Entrada Manual
 info.invalid_msa_input_mininfo=Necesita por lo menos dos secuencias con al menos 3 residuos cada una, sin regiones ocultas entre ellas.
-label.chimera_missing=Visualizador de estructura Chimera no encontrado.<br/>Por favor, introduzca la ruta de Chimera,<br/>o descargar e instalar la UCSF Chimera.
 exception.fts_server_unreachable=Jalview no puede conectar con el servidor {0}. \nPor favor asegúrese de que está conectado a Internet y vuelva a intentarlo.
 exception.outofmemory_loading_mmcif_file=Sin memoria al cargar el fichero mmCIF
 label.hide_columns_not_containing=Ocultar las columnas que no contengan
index f410b54..e3b913b 100644 (file)
@@ -43,20 +43,34 @@ public class PymolManager
    */
   public static List<String> getPymolPaths()
   {
+    return getPymolPaths(System.getProperty("os.name"));
+  }
+
+  /**
+   * Returns a list of paths to try for the PyMOL executable. Any user
+   * preference is placed first, otherwise 'standard' paths depending on the
+   * operating system.
+   * 
+   * @param os
+   *          operating system as reported by environment variable
+   *          {@code os.name}
+   * @return
+   */
+  protected static List<String> getPymolPaths(String os)
+  {
     List<String> pathList = new ArrayList<>();
   
     String userPath = Cache
             .getDefault(Preferences.PYMOL_PATH, null);
     if (userPath != null)
     {
-      pathList.add(0, userPath);
+      pathList.add(userPath);
     }
   
     /*
      * add default installation paths
      */
     String pymol = "PyMOL";
-    String os = System.getProperty("os.name");
     if (os.startsWith("Linux"))
     {
       pathList.add("/usr/local/pymol/bin/" + pymol);
index 581dc3d..0dde255 100644 (file)
@@ -183,7 +183,10 @@ public class AppJmol extends StructureViewerBase
     useAlignmentPanelForColourbyseq(ap);
 
     alignAddedStructures = alignAdded;
-    useAlignmentPanelForSuperposition(ap);
+    if (pdbentrys.length > 1)
+    {
+      useAlignmentPanelForSuperposition(ap);
+    }
 
     jmb.setColourBySequence(true);
     setSize(400, 400); // probably should be a configurable/dynamic default here
index 0d6a216..24ac87a 100644 (file)
  */
 package jalview.gui;
 
-import jalview.api.AlignmentViewPanel;
-import jalview.api.FeatureRenderer;
-import jalview.bin.Cache;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceI;
-import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
-import jalview.gui.StructureViewer.ViewerType;
-import jalview.io.DataSourceType;
-import jalview.io.StructureFile;
-import jalview.structures.models.AAStructureBindingModel;
-import jalview.util.BrowserLauncher;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -52,6 +36,20 @@ import javax.swing.JMenuItem;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
 
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.bin.Cache;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
+import jalview.io.StructureFile;
+import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.BrowserLauncher;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+
 /**
  * GUI elements for handling an external chimera display
  * 
@@ -83,11 +81,6 @@ public class ChimeraViewFrame extends StructureViewerBase
 
     viewerActionMenu.setText(MessageManager.getString("label.chimera"));
 
-    viewerColour
-            .setText(MessageManager.getString("label.colour_with_chimera"));
-    viewerColour.setToolTipText(MessageManager
-            .getString("label.let_chimera_manage_structure_colours"));
-
     helpItem.setText(MessageManager.getString("label.chimera_help"));
     savemenu.setVisible(false); // not yet implemented
     viewMenu.add(fitToWindow);
index d0f6cdb..6fa63fe 100755 (executable)
  */
 package jalview.gui;
 
-import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
-import jalview.bin.Cache;
-import jalview.gui.Help.HelpId;
-import jalview.gui.StructureViewer.ViewerType;
-import jalview.io.BackupFiles;
-import jalview.io.BackupFilesPresetEntry;
-import jalview.io.FileFormatI;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
-import jalview.jbgui.GPreferences;
-import jalview.jbgui.GSequenceLink;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.ColourSchemes;
-import jalview.schemes.ResidueColourScheme;
-import jalview.urls.UrlLinkTableModel;
-import jalview.urls.api.UrlProviderFactoryI;
-import jalview.urls.api.UrlProviderI;
-import jalview.urls.desktop.DesktopUrlProviderFactory;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-import jalview.util.UrlConstants;
-import jalview.ws.sifts.SiftsSettings;
-
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
@@ -74,6 +51,29 @@ import javax.swing.table.TableModel;
 import javax.swing.table.TableRowSorter;
 
 import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.bin.Cache;
+import jalview.ext.pymol.PymolManager;
+import jalview.gui.Help.HelpId;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.BackupFiles;
+import jalview.io.BackupFilesPresetEntry;
+import jalview.io.FileFormatI;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
+import jalview.jbgui.GPreferences;
+import jalview.jbgui.GSequenceLink;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
+import jalview.schemes.ResidueColourScheme;
+import jalview.urls.UrlLinkTableModel;
+import jalview.urls.api.UrlProviderFactoryI;
+import jalview.urls.api.UrlProviderI;
+import jalview.urls.desktop.DesktopUrlProviderFactory;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.util.UrlConstants;
+import jalview.ws.sifts.SiftsSettings;
 
 /**
  * DOCUMENT ME!
@@ -334,7 +334,7 @@ public class Preferences extends GPreferences
             .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, false));
 
     /*
-     * Set Structure tab defaults.
+     * Set Structure tab defaults
      */
     final boolean structSelected = Cache.getDefault(STRUCT_FROM_PDB, false);
     structFromPdb.setSelected(structSelected);
@@ -344,24 +344,46 @@ public class Preferences extends GPreferences
     addSecondaryStructure.setEnabled(structSelected);
     addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, false));
     addTempFactor.setEnabled(structSelected);
+
+    /*
+     * set choice of structure viewer, and path if saved as a preference;
+     * default to Jmol (first choice) if an unexpected value is found
+     */
     String viewerType = Cache.getDefault(STRUCTURE_DISPLAY, ViewerType.JMOL.name());
     structViewer.setSelectedItem(viewerType);
-    boolean isChimeraX = viewerType.equals(ViewerType.CHIMERAX.name());
-    if (viewerType.equals(ViewerType.JMOL.name()))
+    String viewerPath = "";
+    ViewerType type = null;
+    try
     {
-      structureViewerPath.setText("");
-    }
-    else
+      type = ViewerType.valueOf(viewerType);
+      switch (type)
+      {
+      case JMOL:
+        break;
+      case CHIMERA:
+        viewerPath = Cache.getDefault(CHIMERA_PATH, "");
+        break;
+      case CHIMERAX:
+        viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
+        break;
+      case PYMOL:
+        viewerPath = Cache.getDefault(PYMOL_PATH, "");
+        break;
+      }
+    } catch (IllegalArgumentException e)
     {
-      structureViewerPath.setText(Cache
-              .getDefault(isChimeraX ? CHIMERAX_PATH : CHIMERA_PATH, ""));
+      Cache.log.error("Unknown structure viewer type: " + viewerType
+              + ", defaulting to Jmol");
+      type = ViewerType.JMOL;
     }
+    structureViewerPath.setText(viewerPath);
+
     structureViewerPath.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        if (validateChimeraPath())
+        if (validateViewerPath())
         {
           Cache.setProperty(structViewer.getSelectedItem()
                   .equals(ViewerType.CHIMERAX.name())
@@ -887,7 +909,7 @@ public class Preferences extends GPreferences
   @Override
   protected boolean validateStructure()
   {
-    return validateChimeraPath();
+    return validateViewerPath();
 
   }
 
@@ -1219,10 +1241,11 @@ public class Preferences extends GPreferences
   }
 
   /**
-   * Returns true if chimera path is to a valid executable, else show an error
-   * dialog.
+   * Returns true if structure viewer path is to a valid executable, else shows
+   * an error dialog. Does nothing if the path is empty, as is the case for Jmol
+   * (built in to Jalview) or when Jalview is left to try default paths.
    */
-  private boolean validateChimeraPath()
+  private boolean validateViewerPath()
   {
     if (structureViewerPath.getText().trim().length() > 0)
     {
@@ -1230,8 +1253,8 @@ public class Preferences extends GPreferences
       if (!f.canExecute())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                MessageManager.getString("label.invalid_chimera_path"),
-                MessageManager.getString("label.invalid_name"),
+                MessageManager.getString("label.invalid_viewer_path"),
+                MessageManager.getString("label.invalid_viewer_path"),
                 JvOptionPane.ERROR_MESSAGE);
         return false;
       }
@@ -1256,16 +1279,40 @@ public class Preferences extends GPreferences
     structureViewerPath.setEnabled(true);
     structureViewerPathLabel.setEnabled(true);
     structureViewerPathLabel.setText(MessageManager
-            .formatMessage("label.chimera_path", selectedItem));
+            .formatMessage("label.viewer_path", selectedItem));
 
     /*
-     * Try user-specified and standard paths for Chimera executable
+     * Try user-specified and standard paths for structure viewer executable
      */
-    boolean isChimeraX = selectedItem.equals(ViewerType.CHIMERAX.name());
-    structureViewerPath.setText(Cache
-            .getDefault(isChimeraX ? CHIMERAX_PATH : CHIMERA_PATH, ""));
+    String viewerPath = "";
+    List<String> paths = null;
+    try
+    {
+      ViewerType viewerType = ViewerType.valueOf(selectedItem);
+      switch (viewerType)
+      {
+      case JMOL:
+        // dealt with above
+        break;
+      case CHIMERA:
+        viewerPath = Cache.getDefault(CHIMERA_PATH, "");
+        paths = StructureManager.getChimeraPaths(false);
+        break;
+      case CHIMERAX:
+        viewerPath = Cache.getDefault(CHIMERAX_PATH, "");
+        paths = StructureManager.getChimeraPaths(true);
+        break;
+      case PYMOL:
+        viewerPath = Cache.getDefault(PYMOL_PATH, "");
+        paths = PymolManager.getPymolPaths();
+        break;
+      }
+    } catch (IllegalArgumentException e)
+    {
+      // only valid entries should be in the drop-down
+    }
+    structureViewerPath.setText(viewerPath);
 
-    List<String> paths = StructureManager.getChimeraPaths(isChimeraX);
     paths.add(0, structureViewerPath.getText());
     for (String path : paths)
     {
@@ -1275,12 +1322,13 @@ public class Preferences extends GPreferences
         break;
       }
     }
+
     if (!found)
     {
       String[] options = { "OK", "Help" };
       int showHelp = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
               JvSwingUtils.wrapTooltip(true,
-                      MessageManager.getString("label.chimera_missing")),
+                      MessageManager.getString("label.viewer_missing")),
               "", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE,
               null, options, options[0]);
       if (showHelp == JvOptionPane.NO_OPTION)
index 0c5c5f0..1bbc397 100644 (file)
@@ -677,7 +677,10 @@ public abstract class StructureViewerBase extends GStructureViewer
     });
 
     viewerColour = new JRadioButtonMenuItem();
-    // text is set in overrides of this method
+    viewerColour
+            .setText(MessageManager.getString("label.colour_with_viewer"));
+    viewerColour.setToolTipText(MessageManager
+            .getString("label.let_viewer_manage_structure_colours"));
     viewerColour.setName(ViewerColour.ByViewer.name());
     viewerColour.setSelected(!binding.isColourBySequence());
 
@@ -715,10 +718,18 @@ public abstract class StructureViewerBase extends GStructureViewer
       @Override
       public void itemStateChanged(ItemEvent e)
       {
-        alignStructs.setEnabled(!_alignwith.isEmpty());
-        alignStructs.setToolTipText(MessageManager.formatMessage(
-                "label.align_structures_using_linked_alignment_views",
-                _alignwith.size()));
+        if (_alignwith.isEmpty())
+        {
+          alignStructs.setEnabled(false);
+          alignStructs.setToolTipText(null);
+        }
+        else
+        {
+          alignStructs.setEnabled(true);
+          alignStructs.setToolTipText(MessageManager.formatMessage(
+                  "label.align_structures_using_linked_alignment_views",
+                  _alignwith.size()));
+        }
       }
     };
     viewSelectionMenu = new ViewSelectionMenu(
index f2761dd..8963be4 100755 (executable)
  */
 package jalview.jbgui;
 
-import jalview.bin.Cache;
-import jalview.fts.core.FTSDataColumnPreferences;
-import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
-import jalview.fts.service.pdb.PDBFTSRestClient;
-import jalview.gui.Desktop;
-import jalview.gui.JalviewBooleanRadioButtons;
-import jalview.gui.JvOptionPane;
-import jalview.gui.JvSwingUtils;
-import jalview.gui.StructureViewer.ViewerType;
-import jalview.io.BackupFilenameParts;
-import jalview.io.BackupFiles;
-import jalview.io.BackupFilesPresetEntry;
-import jalview.io.IntKeyStringValueEntry;
-import jalview.util.MessageManager;
-
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
@@ -86,6 +71,21 @@ import javax.swing.event.ChangeListener;
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 
+import jalview.bin.Cache;
+import jalview.fts.core.FTSDataColumnPreferences;
+import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
+import jalview.fts.service.pdb.PDBFTSRestClient;
+import jalview.gui.Desktop;
+import jalview.gui.JalviewBooleanRadioButtons;
+import jalview.gui.JvOptionPane;
+import jalview.gui.JvSwingUtils;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.BackupFilenameParts;
+import jalview.io.BackupFiles;
+import jalview.io.BackupFilesPresetEntry;
+import jalview.io.IntKeyStringValueEntry;
+import jalview.util.MessageManager;
+
 /**
  * Base class for the Preferences panel.
  * 
@@ -1248,6 +1248,10 @@ public class GPreferences extends JPanel
     viewerLabel.setBounds(new Rectangle(10, ypos, 220, height));
     structureTab.add(viewerLabel);
 
+    /*
+     * add all external viewers as options here - check 
+     * when selected whether the program is installed
+     */
     structViewer.setFont(LABEL_FONT);
     structViewer.setBounds(new Rectangle(190, ypos, 120, height));
     structViewer.addItem(ViewerType.JMOL.name());
@@ -1270,7 +1274,7 @@ public class GPreferences extends JPanel
     structureViewerPathLabel.setFont(LABEL_FONT);// new Font("SansSerif", 0, 11));
     structureViewerPathLabel.setHorizontalAlignment(SwingConstants.LEFT);
     structureViewerPathLabel.setText(MessageManager
-            .formatMessage("label.chimera_path", "Chimera(X)"));
+            .formatMessage("label.viewer_path", "Chimera(X)"));
     structureViewerPathLabel.setBounds(new Rectangle(10, ypos, 170, height));
     structureViewerPathLabel.setEnabled(false);
     structureTab.add(structureViewerPathLabel);
@@ -1279,7 +1283,7 @@ public class GPreferences extends JPanel
     structureViewerPath.setText("");
     structureViewerPath.setEnabled(false);
     final String tooltip = JvSwingUtils.wrapTooltip(true,
-            MessageManager.getString("label.chimera_path_tip"));
+            MessageManager.getString("label.viewer_path_tip"));
     structureViewerPath.setToolTipText(tooltip);
     structureViewerPath.setBounds(new Rectangle(190, ypos, 290, height));
     structureViewerPath.addMouseListener(new MouseAdapter()
index 19b779d..c415ace 100644 (file)
@@ -1,11 +1,14 @@
 package jalview.ext.pymol;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
-import jalview.structure.StructureCommand;
+import java.util.List;
 
 import org.testng.annotations.Test;
 
+import jalview.structure.StructureCommand;
+
 public class PymolManagerTest
 {
   @Test(groups = "Functional")
@@ -23,4 +26,39 @@ public class PymolManagerTest
             + "<parameter><value>all</value></parameter>"
             + "</params></methodCall>");
   }
+
+  @Test(groups = "Functional")
+  public void testGetPymolPaths()
+  {
+    /*
+     * OSX
+     */
+    List<String> paths = PymolManager.getPymolPaths("Mac OS X");
+    assertEquals(paths.size(), 1);
+    assertTrue(
+            paths.contains("/Applications/PyMOL.app/Contents/MacOS/PyMOL"));
+
+    /*
+     * Linux
+     */
+    paths = PymolManager.getPymolPaths("Linux i386 1.5.0");
+    assertTrue(paths.contains("/usr/local/pymol/bin/PyMOL"));
+    assertTrue(paths.contains("/usr/local/bin/PyMOL"));
+    assertTrue(paths.contains("/usr/bin/PyMOL"));
+    assertTrue(paths.contains("/usr/local/pymol/bin/PyMOL"));
+    assertTrue(paths
+            .contains(System.getProperty("user.home") + "/opt/bin/PyMOL"));
+
+    /*
+     * Windows
+     */
+    paths = PymolManager.getPymolPaths("Windows 10");
+    assertTrue(paths.isEmpty()); // TODO - Windows paths
+
+    /*
+     * Other
+     */
+    paths = PymolManager.getPymolPaths("VAX/VMS");
+    assertTrue(paths.isEmpty());
+  }
 }