Merge branch 'features/JAL-2295setChimeraAttributes' into spikes/mungo
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 17 Jan 2017 16:08:58 +0000 (16:08 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 17 Jan 2017 16:08:58 +0000 (16:08 +0000)
62 files changed:
examples/appletDeployment.html
examples/appletParameters.html
examples/applets.html
examples/groovy/fileFormat.groovy [new file with mode: 0644]
help/help.jhm
help/helpTOC.xml
help/html/calculations/referenceseq.html
help/html/menus/alignmentMenu.html
help/html/menus/wsmenu.html
help/html/webServices/jnet.html
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/CutAndPasteTransfer.java
src/jalview/appletgui/SeqPanel.java
src/jalview/bin/JalviewLite.java
src/jalview/bin/JalviewLiteURLRetrieve.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/ColumnSelection.java
src/jalview/ext/ensembl/EnsemblRestClient.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/CutAndPasteTransfer.java
src/jalview/gui/Desktop.java
src/jalview/gui/PCAPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/gui/ScalePanel.java
src/jalview/gui/SeqPanel.java
src/jalview/io/AlignFile.java
src/jalview/io/AlignmentFileReaderI.java [moved from src/jalview/io/AlignmentFileI.java with 69% similarity]
src/jalview/io/AlignmentFileWriterI.java [new file with mode: 0644]
src/jalview/io/AppletFormatAdapter.java
src/jalview/io/FileFormat.java
src/jalview/io/FileFormatI.java
src/jalview/io/FileFormats.java [new file with mode: 0644]
src/jalview/io/FileLoader.java
src/jalview/io/FormatAdapter.java
src/jalview/io/IdentifyFile.java
src/jalview/io/JalviewFileChooser.java
src/jalview/io/JalviewFileView.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/math/Matrix.java
src/jalview/util/Format.java
src/jalview/ws/jws1/Discoverer.java
src/jalview/ws/jws1/JPredClient.java
src/jalview/ws/jws1/JPredThread.java
src/jalview/ws/rest/params/Alignment.java
src/jalview/ws/sifts/SiftsClient.java
test/jalview/analysis/AlignmentGenerator.java [moved from test/jalview/analysis/DnaAlignmentGenerator.java with 82% similarity]
test/jalview/analysis/DnaTest.java
test/jalview/datamodel/AlignmentTest.java
test/jalview/datamodel/ColumnSelectionTest.java
test/jalview/io/FileFormatsTest.java [new file with mode: 0644]
test/jalview/io/FormatAdapterTest.java
test/jalview/math/MatrixTest.java [new file with mode: 0644]
test/jalview/util/FormatTest.java
test/jalview/ws/jabaws/DisorderAnnotExportImport.java
test/jalview/ws/jabaws/JpredJabaStructExportImport.java
test/jalview/ws/jabaws/RNAStructExportImport.java
test/jalview/ws/sifts/SiftsClientTest.java

index 7b4daee..e9c22e5 100644 (file)
        <tr>
                <td><strong>2.1</strong></td>
                <td><ul>
-          <li>Jalview Applet can read and display JNet secondary structure annotation 
+          <li>Jalview Applet can read and display JPred secondary structure annotation 
             directly via the <strong>jnetfile</strong> parameter. <br>
           </li>
           <li>Param &quot;UserDefinedColour&quot; - specify your own colours for each residue using a semi colon 
index cc95ecb..277fd69 100644 (file)
@@ -91,8 +91,9 @@ the applet can be interacted with <em>via</em> its
             <td>jnetfile</td>
             <td>fileName</td>
             <td>Secondary structure predictions from a <a
-            href="http://www.compbio.dundee.ac.uk/~www-jpred/">Jnet</a> Concise 
-              file will be added to the first sequence in the alignment.</td>
+            href="http://www.compbio.dundee.ac.uk/~www-jpred/">JPred</a> Concise 
+              file will be added to the first sequence in the alignment.<br/>
+              <em>jpredfile</em> can be used interchangeably with this parameter.</td>
           </tr>
           <tr> 
             <td>PDBfile(x)</td>
index d997f14..b789672 100644 (file)
@@ -136,7 +136,7 @@ Try out JalviewLite by pressing one of the buttons below.
 </applet>
                                                       </td>
       <td valign="middle">Displays a Multiple Sequence Alignment
-       Based JNet Prediction for a Sequence</td>
+       Based JPred Prediction for a Sequence</td>
     </tr>
   </table>
   <p>
diff --git a/examples/groovy/fileFormat.groovy b/examples/groovy/fileFormat.groovy
new file mode 100644 (file)
index 0000000..c314a6c
--- /dev/null
@@ -0,0 +1,108 @@
+import jalview.datamodel.AlignmentI
+import jalview.datamodel.SequenceI
+import jalview.datamodel.Sequence
+import jalview.io.FileFormatI
+import jalview.io.FileFormats
+import jalview.io.FileParse
+import jalview.io.AlignFile
+
+/*
+ * Example script that registers a new alignment file format 
+ * consisting of lines like
+ * !I=<sequence id>
+ * !S=<sequence string>
+ */
+
+/*
+ * A parser class to read or write the format
+ */
+class MyParser extends AlignFile 
+{
+  /*
+   * Constructor for reading a file; the superclass
+   * constructor will call the parse() method
+   */
+  MyParser(FileParse src) 
+  {
+    super(src)
+  }
+
+  /*
+   * Constructor for writing out an alignment
+   */
+  MyParser(AlignmentI al) 
+  {
+  }
+  
+  /*
+   * Parse a formatted data file (with no error checking!)
+   */
+  void parse() 
+  {
+    String id
+    String line
+    while ((line = nextLine()) != null) 
+    {
+      if (line.startsWith('!I='))
+      {
+        int pos = line.indexOf('/')
+        id = line.substring(3, pos == -1 ? line.length() : pos)
+      } else if (line.startsWith('!S='))
+      {
+        String seq = line.substring(3)
+        addSequence(new Sequence(id, seq))
+      }
+    }
+  }
+  
+  /*
+   * Print the formatted sequences
+   * (addSuffix always defaults to true as no user preference for it)
+   */
+  String print(SequenceI[] seqs, boolean addSuffix) 
+  {
+      StringBuilder sb = new StringBuilder()
+      for (SequenceI seq : seqs) 
+      {
+          sb.append('!I=').append(seq.getDisplayId(addSuffix)).append('\n')
+          sb.append('!S=').append(seq.getSequenceAsString()).append('\n')
+      }
+      sb.toString()
+  }
+}
+
+/*
+ * A closure that defines the 'Groovy example' file format,
+ * delegating to MyParser for reading and writing
+ */
+def myFormat = { ->
+  [
+    getName: { -> 'Groovy example' },
+    
+    toString: { -> getName() },
+    
+    getExtensions: { -> 'grv' },
+    
+    getReader: { FileParse source -> new MyParser(source) },
+    
+    getWriter: { AlignmentI al -> new MyParser(al) },
+    
+    isReadable: { -> true },
+    
+    isWritable: { -> true },
+    
+    isTextFormat: { -> true },
+    
+    isStructureFile: { -> false },
+    
+    isComplexAlignFile: { -> false },
+
+   ] as FileFormatI
+}
+
+/*
+ * Register the file format. After running this script in Jalview's
+ * Groovy console, the new format should be shown in open file,
+ * save file, and output to textbox menu options.
+ */
+FileFormats.instance.registerFileFormat(myFormat())
index e034fc2..f69ed00 100755 (executable)
@@ -33,7 +33,7 @@
    <mapID target="wsparams" url="html/webServices/webServicesParams.html"/>
    <mapID target="wsprefs" url="html/webServices/webServicesPrefs.html"/>
    <mapID target="msaservice" url="html/webServices/msaclient.html"/>
-   <mapID target="jnet" url="html/webServices/jnet.html"/>
+   <mapID target="jpred" url="html/webServices/jnet.html"/>
    <mapID target="shmrws" url="html/webServices/shmr.html"/>
    <mapID target="newsreader" url="html/webServices/newsreader.html"/>
    <mapID target="disorder" url="html/webServices/proteinDisorder.html"/>
index 3a6b0b3..54abd53 100755 (executable)
@@ -70,7 +70,7 @@
                        <tocitem text="Sequence Alignment" target="msaservice"  expand="false">
                                <tocitem text="Multiple Alignment Subjobs" target="msaservice" />
                        </tocitem>
-                       <tocitem text="Secondary Structure Prediction" target="jnet" />
+                       <tocitem text="Secondary Structure Prediction" target="jpred" />
                        <tocitem text="RNAalifold RNA Secondary Structure Prediction" target="rnaalifold" />
                        <tocitem text="Protein Disorder Prediction" target="disorder" />
                        <tocitem text="Alignment Conservation Analysis" target="aacon" />
index a79541b..7c0e3dc 100644 (file)
@@ -58,7 +58,7 @@
     <li><strong>Defining a reference when importing
         annotation</strong><br />Jalview automatically assigns a reference
       sequence when importing analysis results, such as those returned
-      from <a href="../webServices/jnet.html">JPred4</a> . A reference
+      from <a href="../webServices/jnet.html">JPred</a> . A reference
       sequence can also be assigned via the <a
       href="../features/annotationsFormat.html#refsandviews">SET_REF</a>
       command in an alignment annotation file.</li>
index 167cb25..51ad601 100755 (executable)
         <ul>
           <li><strong>JPred Secondary Structure Prediction</strong><br>
             <em>Secondary structure prediction by network
-              consensus. See the <a href="../webServices/jnet.html">Jpred3</a>
+              consensus. See the <a href="../webServices/jnet.html">Jpred</a>
               client entry for more information. The behaviour of this
               calculation depends on the current selection:
               <ul>
                 <li>If nothing is selected, and the displayed
-                  sequences appear to be aligned, then a JNet prediction
+                  sequences appear to be aligned, then a JPred prediction
                   will be run for the first sequence in the alignment,
                   using the current alignment. Otherwise the first
                   sequence will be submitted for prediction.</li>
                 <li>If just one sequence (or a region on one
                   sequence) has been selected, it will be submitted to
-                  the automatic JNet prediction server for homolog
+                  the automatic JPred prediction server for homolog
                   detection and prediction.</li>
                 <li>If a set of sequences are selected, and they
                   appear to be aligned, then the alignment will be used
-                  for a Jnet prediction on the <strong>first</strong>
+                  for a JPred prediction on the <strong>first</strong>
                   sequence in the set (that is, the one that appears
                   first in the alignment window).
                 </li>
index 33282e9..b71bc1a 100755 (executable)
       <ul>
         <li><strong>JPred Secondary Structure Prediction</strong><br>
           <em>Secondary structure prediction by network consensus.
-            See the <a href="../webServices/jnet.html">Jpred3</a> client
+            See the <a href="../webServices/jnet.html">Jpred</a> client
             entry for more information. The behaviour of this
             calculation depends on the current selection:
             <ul>
               <li>If nothing is selected, and the displayed
-                sequences appear to be aligned, then a JNet prediction
+                sequences appear to be aligned, then a JPred prediction
                 will be run for the first sequence in the alignment,
                 using the current alignment. Otherwise the first
                 sequence will be submitted for prediction.</li>
               <li>If just one sequence (or a region on one
                 sequence) has been selected, it will be submitted to the
-                automatic JNet prediction server for homolog detection
+                automatic JPred prediction server for homolog detection
                 and prediction.</li>
               <li>If a set of sequences are selected, and they
                 appear to be aligned, then the alignment will be used
-                for a Jnet prediction on the <strong>first</strong>
+                for a JPred prediction on the <strong>first</strong>
                 sequence in the set (that is, the one that appears first
                 in the alignment window).
               </li>
index 396a3a7..077ace6 100755 (executable)
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  -->
 <head>
-<title>JNet Secondary Structure Prediction</title>
+<title>JPred Secondary Structure Prediction</title>
 </head>
 <body>
-  <strong>JNet Secondary Structure Prediction</strong>
+  <strong>JPred Secondary Structure Prediction</strong>
   <p>
     Secondary structure prediction methods attempts to infer the likely
     secondary structure for a protein based on its amino acid
   </p>
   The function available from the
   <strong>Web Service&#8594;Secondary Structure
-    Prediction&#8594;JNet Secondary Structure Prediction</strong> menu does two
+    Prediction&#8594;JPred Secondary Structure Prediction</strong> menu does two
   different kinds of prediction, dependent upon the currently selected
   region:
   </p>
   <ul>
     <li>If nothing is selected, and the displayed sequences appear
-      to be aligned, then a JNet prediction will be run for the first
+      to be aligned, then a JPred prediction will be run for the first
       sequence in the alignment, using the current alignment. Otherwise
       the first sequence will be submitted for prediction.</li>
     <li>If just one sequence (or a region on one sequence) has been
-      selected, it will be submitted to the automatic JNet prediction
+      selected, it will be submitted to the automatic JPred prediction
       server for homolog detection and prediction.</li>
     <li>If a set of sequences are selected, and they appear to be
-      aligned, then the alignment will be used for a Jnet prediction on
+      aligned, then the alignment will be used for a JPred prediction on
       the <strong>first</strong> sequence selected in the set (that is,
       the one nearest the top of the alignment window).
     </li>
   </ul>
   <p>
-    <strong>Note</strong>: JNet secondary structure prediction is a
+    <strong>Note</strong>: JPred secondary structure prediction is a
     'non-column-separable' service - predictions are based on the
     sequence profile of contiguous stretches of amino-acid sequence. A
     prediction will only be made on the visible parts of a sequence (see
     <a href="../features/hiddenRegions.html">hiding columns</a>) as if
     it were a contiguous polypeptide chain. Prediction accuracy at the
     hidden column boundaries may therefore be less than indicated by
-    JNet's own reliability score (see below).
+    JPred's own reliability score (see below).
   </p>
-  <p>The result of a JNet prediction for a sequence is a new
+  <p>The result of a JPred prediction for a sequence is a new
     annotated alignment window:</p>
   <img src="jnetprediction.gif">
   <p>The sequence for which the prediction was made is the first one
         significantly different primary predictions.</em></li>
   </ul>
   </p>
-  <em>JNet annotation created in Jalview 2.8.2 and later versions
+  <em>JPred annotation created in Jalview 2.8.2 and later versions
     can be displayed on other alignments via the <a
     href="../features/annotation.html#seqannots">Add reference
       annotation</a> Sequence ID popup menu option.
   </em>
-  <em>As of Jalview 2.6, the Jnet service accessed accessed via the
+  <em>As of Jalview 2.6, the JPred service accessed accessed via the
     'Secondary structure prediction' submenu should be considered a
     legacy Jalview SOAP service, and will be replaced in the near future
     by a JPred4 Rest service.</em>
index ce39010..f1e371d 100644 (file)
@@ -837,7 +837,7 @@ label.colour_by = Colour by...
 label.muscle_multiple_protein_sequence_alignment = Muscle Multiple Protein Sequence Alignment
 label.mafft_multiple_sequence_alignment = MAFFT Multiple Sequence Alignment
 label.clustalw_multiple_sequence_alignment = ClustalW Multiple Sequence Alignment
-label.jnet_secondary_structure_prediction = JNet Secondary Structure Prediction
+label.jnet_secondary_structure_prediction = JPred Secondary Structure Prediction
 label.multiharmony = Multi-Harmony
 label.unable_start_web_service_analysis = Unable to start web service analysis
 label.job_couldnt_be_started_check_input = The Job couldn't be started. Please check your input, and the Jalview console for any warning messages.
@@ -971,7 +971,7 @@ error.cannot_have_zero_length_vector_replacement_strings = Cannot have zero leng
 error.implementation_error_multiple_single_sequence_prediction_jobs_not_supported = Implementation Error! Multiple single sequence prediction jobs are not yet supported
 error.implementation_error_invalid_msa_index_for_job =Implementation Error! Invalid msaIndex for JPredJob on parent MSA input object!
 error.implementation_error_startjob_called = Implementation error - StartJob(JpredJob) called on {0}
-error.multiple_jnet_subjob_merge_not_implemented = Multiple JNet subjob merging not yet implemented
+error.multiple_jnet_subjob_merge_not_implemented = Multiple JPred subjob merging not yet implemented
 label.job_never_ran = Job never ran - input returned to user.
 error.implementation_error_minlen_must_be_greater_zero = Implementation error: minlen must be zero or more
 error.implementation_error_msawbjob_called = Implementation error - StartJob(MsaWSJob) called on a WSJobInstance {0}
@@ -1079,7 +1079,7 @@ exception.unexpected_handling_rnaml_translation_for_pdb = Unexpected exception w
 exception.couldnt_recover_sequence_properties_for_alignment = Couldn't recover sequence properties for alignment
 exception.unknown_format_for_file = Unknown format {0} for file \: \n{1}
 label.remove_gaps = Remove Gaps
-exception.couldnt_recover_sequence_props_for_jnet_query = Couldn't recover sequence properties for JNet Query sequence!
+exception.couldnt_recover_sequence_props_for_jnet_query = Couldn't recover sequence properties for JPred Query sequence!
 exception.server_timeout_try_later = Server timed out - try again later\n
 exception.web_service_returned_null_try_later= Server at {0} returned null object, it probably cannot be contacted. Try again later.
 exception.cannot_contact_service_endpoint_at = Cannot contact service endpoint at {0}
@@ -1101,7 +1101,7 @@ info.job_couldnt_be_run_exceeded_hard_limit = Job could not be run because it ex
 info.job_couldnt_be_run_incorrect_param_setting = Job could not be run because some of the parameter settings are not supported by the server.\n{0}\nPlease check to make sure you have used the correct parameter set for this service\!\n
 info.no_jobs_ran = No jobs ran
 info.failed_to_submit_prediction = Failed to submit the prediction\:\n{0} {1}
-info.invalid_jnet_job_result_data ={0}\n{1}\nInvalid JNet job result data\!\n{2}
+info.invalid_jnet_job_result_data ={0}\n{1}\nInvalid JPred job result data\!\n{2}
 info.failed_to_submit_sequences_for_alignment = Failed to submit sequences for alignment.\nIt is most likely that there is a problem with the server.\nJust close the window\n
 info.alignment_object_method_notes = \nAlignment Object Method Notes\n
 info.server_exception = \n{0} Server exception\!\n{1}
index e5b5e27..8cdcd52 100644 (file)
@@ -768,7 +768,7 @@ label.colour_by = Colorear por...
 label.muscle_multiple_protein_sequence_alignment = Alineamiento múltiple de secuencias de proteínas con Muscle
 label.mafft_multiple_sequence_alignment = Alineamiento múltiple de secuencias con MAFFT
 label.clustalw_multiple_sequence_alignment = Alineamiento múltiple de secuencias con ClustalW
-label.jnet_secondary_structure_prediction = Predicción de la estructura secundaria con JNet
+label.jnet_secondary_structure_prediction = Predicción de la estructura secundaria con JPred
 label.multiharmony = Multi-Harmony
 label.unable_start_web_service_analysis = No es posible iniciar el servicio web de análisis
 label.job_couldnt_be_started_check_input = El trabajo no puede arrancarse. Por favor, compruebe los parámetros de entrada y los mensajes de advertencia de la consola de Jalview.
@@ -902,7 +902,7 @@ error.cannot_have_zero_length_vector_replacement_strings = No es posible tener u
 error.implementation_error_multiple_single_sequence_prediction_jobs_not_supported = ¡Error de implementación! Todavía no se soportan varios trabajos de predicción asociados a una única secuencia.
 error.implementation_error_invalid_msa_index_for_job = ¡Error de implementación! Valor msaIndex no válido para JPredJob en el objeto de entrada MSA padre!
 error.implementation_error_startjob_called = Error de implementación - StartJob(JpredJob) invocado en {0}
-error.multiple_jnet_subjob_merge_not_implemented = Todavía no se han implementado varios subtrabajos JNet conjuntos.
+error.multiple_jnet_subjob_merge_not_implemented = Todavía no se han implementado varios subtrabajos JPred conjuntos.
 label.job_never_ran = El trabajo nunca se ejecutó - entrada devuelta al usuario.
 error.implementation_error_minlen_must_be_greater_zero = Error de implementación: minlen debe ser cero o más
 error.implementation_error_msawbjob_called = Error de implementación - StartJob(MsaWSJob) invocado en un WSJobInstance {0}
@@ -1010,7 +1010,7 @@ exception.unexpected_handling_rnaml_translation_for_pdb = Excepcion inesperada c
 exception.couldnt_recover_sequence_properties_for_alignment = No es posible recuperar las propiedades de la secuencia para el alineamiento
 exception.unknown_format_for_file = Formato desconocido {0} para el fichero \: \n{1}
 label.remove_gaps = Eliminar huecos
-exception.couldnt_recover_sequence_props_for_jnet_query = No ha sido posible recuperar las propiedades de la secuencia para la secuencia JNet Query!
+exception.couldnt_recover_sequence_props_for_jnet_query = No ha sido posible recuperar las propiedades de la secuencia para la secuencia JPred Query!
 exception.server_timeout_try_later = Tiempo de conexi\u00F3n ha expirado - int\u00E9ntelo de nuevo m\u00E1s tarde\n
 exception.web_service_returned_null_try_later= El servidor {0} ha devuelto un objeto nulo, por lo que probablemente no se haya podido contactar con él. Inténtelo de nuevo más tarde.
 exception.cannot_contact_service_endpoint_at = No es posible contactar por el punto de acceso al servicio en {0}
@@ -1031,7 +1031,7 @@ info.job_couldnt_be_run_exceeded_hard_limit = No es posible ejecutar el trabajo
 info.job_couldnt_be_run_incorrect_param_setting = No es posible ejecutar el trabjao porque el servidor no soporta algunos de los par\u00E1metros.\n{0}\nPor favor, aseg\u00FArese de que ha usado los par\u00E1metros adecuados para este servicio\n
 info.no_jobs_ran = No se ha ejecutado ningún trabajo
 info.failed_to_submit_prediction = Error al enviar la predicci\u00F3n\:\n{0} {1}
-info.invalid_jnet_job_result_data ={0}\n{1}\nResultados del trabajo JNet no v\u00E1lidos\!\n{2}
+info.invalid_jnet_job_result_data ={0}\n{1}\nResultados del trabajo JPred no v\u00E1lidos\!\n{2}
 info.failed_to_submit_sequences_for_alignment = Error al enviar la secuencias para el alineamiento.\nLo m\u00E1s probable es que haya un problema en el servidor.\nSimplemente, cierre la ventana\n
 info.alignment_object_method_notes = \nNotas sobre los m\u00E9todos del objeto alineamiento\n
 info.server_exception = \n{0} Excepci\u00F3n del servidor\!\n{1}
index 015734f..8f7a15b 100644 (file)
@@ -36,7 +36,8 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
-import jalview.io.FileFormat;
+import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.SequenceAnnotationReport;
 import jalview.schemes.Blosum62ColourScheme;
 import jalview.schemes.BuriedColourScheme;
@@ -216,7 +217,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
       e.printStackTrace();
     }
 
-    for (String ff : FileFormat.getWritableFormats(true))
+    for (String ff : FileFormats.getInstance().getWritableFormats(true))
     {
       MenuItem item = new MenuItem(ff);
 
@@ -244,8 +245,12 @@ public class APopupMenu extends java.awt.PopupMenu implements
       {
         menu1.setLabel(MessageManager.getString("action.edit_group"));
         groupMenu.remove(createGroupMenuItem);
+        if (sg.cs != null)
+        {
+          abovePIDColour.setState(sg.cs.getThreshold() > 0);
+          conservationMenuItem.setState(sg.cs.conservationApplied());
+        }
       }
-
     }
     else
     {
@@ -500,23 +505,28 @@ public class APopupMenu extends java.awt.PopupMenu implements
   @Override
   public void itemStateChanged(ItemEvent evt)
   {
-    if (evt.getSource() == abovePIDColour)
+    Object source = evt.getSource();
+    if (source == abovePIDColour)
     {
       abovePIDColour_itemStateChanged();
     }
-    else if (evt.getSource() == showColourText)
+    else if (source == conservationMenuItem)
+    {
+      conservationMenuItem_itemStateChanged();
+    }
+    else if (source == showColourText)
     {
       showColourText_itemStateChanged();
     }
-    else if (evt.getSource() == showText)
+    else if (source == showText)
     {
       showText_itemStateChanged();
     }
-    else if (evt.getSource() == showBoxes)
+    else if (source == showBoxes)
     {
       showBoxes_itemStateChanged();
     }
-    else if (evt.getSource() == displayNonconserved)
+    else if (source == displayNonconserved)
     {
       this.showNonconserved_itemStateChanged();
     }
@@ -579,10 +589,6 @@ public class APopupMenu extends java.awt.PopupMenu implements
     {
       noColourmenuItem_actionPerformed();
     }
-    else if (source == conservationMenuItem)
-    {
-      conservationMenuItem_itemStateChanged();
-    }
     else if (source == unGroupMenuItem)
     {
       unGroupMenuItem_actionPerformed();
@@ -784,7 +790,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
     // now returns a full copy of sequence data
     // TODO consider using getSequenceSelection instead here
 
-    FileFormat fileFormat = FileFormat.valueOf(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     cap.setText(new AppletFormatAdapter().formatSequences(fileFormat,
             ap.av.getShowJVSuffix(), ap, true));
 
index f830fe6..86dc19b 100644 (file)
@@ -52,6 +52,8 @@ import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
 import jalview.io.FeaturesFile;
 import jalview.io.FileFormat;
+import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.TCoffeeScoreFile;
 import jalview.schemes.Blosum62ColourScheme;
 import jalview.schemes.BuriedColourScheme;
@@ -1362,7 +1364,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             "label.alignment_output_command",
             new Object[] { e.getActionCommand() }), 600, 500);
 
-    FileFormat fileFormat = FileFormat.valueOf(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     cap.setText(new AppletFormatAdapter(alignPanel).formatSequences(
             fileFormat, viewport.getAlignment(),
             viewport.getShowJVSuffix()));
@@ -1480,10 +1483,13 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       url.append(appendProtocol(viewport.applet.getParameter("annotations")));
     }
 
-    if (viewport.applet.getParameter("jnetfile") != null)
+    if (viewport.applet.getParameter("jnetfile") != null
+            || viewport.applet.getParameter("jpredfile") != null)
     {
       url.append("&annotations=");
-      url.append(appendProtocol(viewport.applet.getParameter("jnetfile")));
+      url.append(appendProtocol(viewport.applet.getParameter("jnetfile") != null ? viewport.applet
+              .getParameter("jnetfile") : viewport.applet
+              .getParameter("jpredfile")));
     }
 
     if (viewport.applet.getParameter("defaultColour") != null)
@@ -3236,7 +3242,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     inputText.addActionListener(this);
     Menu outputTextboxMenu = new Menu(
             MessageManager.getString("label.out_to_textbox"));
-    for (String ff : FileFormat.getWritableFormats(true))
+    for (String ff : FileFormats.getInstance().getWritableFormats(true))
     {
       MenuItem item = new MenuItem(ff);
 
index d50fcef..c658734 100644 (file)
@@ -28,7 +28,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
-import jalview.io.AlignmentFileI;
+import jalview.io.AlignmentFileReaderI;
 import jalview.io.AnnotationFile;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
@@ -68,7 +68,7 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
 
   AlignFrame alignFrame;
 
-  AlignmentFileI source = null;
+  AlignmentFileReaderI source = null;
 
   public CutAndPasteTransfer(boolean forImport, AlignFrame alignFrame)
   {
index 8d6e683..4278744 100644 (file)
@@ -1425,19 +1425,12 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     if (stretchGroup == null)
     {
-      stretchGroup = av.getAlignment().findGroup(sequence);
-      if (stretchGroup != null && res > stretchGroup.getStartRes()
-              && res < stretchGroup.getEndRes())
-      {
-        av.setSelectionGroup(stretchGroup);
-      }
-      else
-      {
-        stretchGroup = null;
-      }
+      stretchGroup = av.getAlignment().findGroup(sequence, res);
+      av.setSelectionGroup(stretchGroup);
     }
 
-    else if (!stretchGroup.getSequences(null).contains(sequence)
+    if (stretchGroup == null
+            || !stretchGroup.getSequences(null).contains(sequence)
             || stretchGroup.getStartRes() > res
             || stretchGroup.getEndRes() < res)
     {
index 9fd8a90..d7b064a 100644 (file)
@@ -38,8 +38,8 @@ import jalview.datamodel.SequenceI;
 import jalview.io.AnnotationFile;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
-import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileParse;
 import jalview.io.IdentifyFile;
 import jalview.io.JPredFile;
@@ -517,7 +517,7 @@ public class JalviewLite extends Applet implements
   {
     try
     {
-      FileFormatI theFormat = FileFormat.valueOf(format);
+      FileFormatI theFormat = FileFormats.getInstance().forName(format);
       boolean seqlimits = suffix.equalsIgnoreCase(TRUE);
       if (alf.viewport.getSelectionGroup() != null)
       {
@@ -715,7 +715,7 @@ public class JalviewLite extends Applet implements
     {
       boolean seqlimits = suffix.equalsIgnoreCase(TRUE);
 
-      FileFormatI theFormat = FileFormat.valueOf(format);
+      FileFormatI theFormat = FileFormats.getInstance().forName(format);
       String reply = new AppletFormatAdapter().formatSequences(theFormat,
               alf.viewport.getAlignment(), seqlimits);
       return reply;
@@ -2255,6 +2255,11 @@ public class JalviewLite extends Applet implements
     {
       boolean result = false;
       String param = applet.getParameter("jnetfile");
+      if (param == null)
+      {
+        // jnet became jpred around 2016
+        param = applet.getParameter("jpredfile");
+      }
       if (param != null)
       {
         try
index 156e146..d6fb090 100644 (file)
@@ -25,6 +25,7 @@ import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileParse;
 import jalview.io.IdentifyFile;
 
@@ -115,7 +116,8 @@ public class JalviewLiteURLRetrieve extends Applet
                 + " cannot be read with protocol==" + protocol);
         return;
       }
-      FileFormatI format = FileFormat.valueOf(getParameter("format"));
+      FileFormatI format = FileFormats.getInstance().forName(
+              getParameter("format"));
       if (format == null)
       {
         format = new IdentifyFile().identify(file, protocol);
index d651c1d..90bdcae 100755 (executable)
@@ -366,17 +366,18 @@ public class Alignment implements AlignmentI
    * @see jalview.datamodel.AlignmentI#findGroup(jalview.datamodel.SequenceI)
    */
   @Override
-  public SequenceGroup findGroup(SequenceI s)
+  public SequenceGroup findGroup(SequenceI seq, int position)
   {
     synchronized (groups)
     {
-      for (int i = 0; i < this.groups.size(); i++)
+      for (SequenceGroup sg : groups)
       {
-        SequenceGroup sg = groups.get(i);
-
-        if (sg.getSequences(null).contains(s))
+        if (sg.getSequences(null).contains(seq))
         {
-          return sg;
+          if (position >= sg.getStartRes() && position <= sg.getEndRes())
+          {
+            return sg;
+          }
         }
       }
     }
index 7274e5f..2df099a 100755 (executable)
@@ -156,15 +156,16 @@ public interface AlignmentI extends AnnotatedCollectionI
   int findIndex(SequenceI s);
 
   /**
-   * Finds group that given sequence is part of.
+   * Returns the first group (in the order in which groups were added) that
+   * includes the given sequence and aligned position (base 0), or null if none
+   * found
    * 
-   * @param s
-   *          Sequence in alignment.
+   * @param seq
+   * @param position
    * 
-   * @return First group found for sequence. WARNING : Sequences may be members
-   *         of several groups. This method is incomplete.
+   * @return
    */
-  SequenceGroup findGroup(SequenceI s);
+  SequenceGroup findGroup(SequenceI seq, int position);
 
   /**
    * Finds all groups that a given sequence is part of.
index d651c0b..c467f4a 100644 (file)
@@ -866,6 +866,24 @@ public class ColumnSelection
          */
         region[0] = Math.min(region[0], start);
         region[1] = Math.max(region[1], end);
+
+        /*
+         * also update or remove any subsequent ranges 
+         * that are overlapped
+         */
+        while (i < hiddenColumns.size() - 1)
+        {
+          int[] nextRegion = hiddenColumns.get(i + 1);
+          if (nextRegion[0] > end + 1)
+          {
+            /*
+             * gap to next hidden range - no more to update
+             */
+            break;
+          }
+          region[1] = Math.max(nextRegion[1], end);
+          hiddenColumns.remove(i + 1);
+        }
         return;
       }
     }
index 8ee6aaf..ab3b197 100644 (file)
@@ -61,9 +61,9 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
    * @see https://github.com/Ensembl/ensembl-rest/wiki/Change-log
    * @see http://rest.ensembl.org/info/rest?content-type=application/json
    */
-  private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "4.6";
+  private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "4.8";
 
-  private static final String LATEST_ENSEMBL_REST_VERSION = "4.7";
+  private static final String LATEST_ENSEMBL_REST_VERSION = "4.8";
 
   private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log";
 
index 9c4ff81..370e649 100644 (file)
@@ -66,6 +66,7 @@ import jalview.io.BioJsHTMLOutput;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileLoader;
 import jalview.io.FormatAdapter;
 import jalview.io.HtmlSvgOutput;
@@ -131,6 +132,8 @@ import java.awt.print.PageFormat;
 import java.awt.print.PrinterJob;
 import java.beans.PropertyChangeEvent;
 import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -857,7 +860,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     modifyConservation.setEnabled(!nucleotide);
     showGroupConservation.setEnabled(!nucleotide);
     rnahelicesColour.setEnabled(nucleotide);
+    nucleotideColour.setEnabled(nucleotide);
     purinePyrimidineColour.setEnabled(nucleotide);
+    RNAInteractionColour.setEnabled(nucleotide);
     showComplementMenuItem.setText(nucleotide ? MessageManager
             .getString("label.protein") : MessageManager
             .getString("label.nucleotide"));
@@ -1113,7 +1118,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void saveAs_actionPerformed(ActionEvent e)
   {
     String format = currentFileFormat == null ? null : currentFileFormat
-            .toString();
+            .getName();
     JalviewFileChooser chooser = JalviewFileChooser.forWrite(
             Cache.getProperty("LAST_DIRECTORY"), format);
 
@@ -1147,8 +1152,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
       fileName = chooser.getSelectedFile().getPath();
 
-      Cache.setProperty("DEFAULT_FILE_FORMAT",
-              currentFileFormat.toString());
+      Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
 
       Cache.setProperty("LAST_DIRECTORY", fileName);
       saveAlignment(fileName, currentFileFormat);
@@ -1178,17 +1182,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     else
     {
-      // if (!jalview.io.AppletFormatAdapter.isValidFormat(format, true))
-      // {
-      // warningMessage("Cannot save file " + fileName + " using format "
-      // + format, "Alignment output format not supported");
-      // if (!Jalview.isHeadlessMode())
-      // {
-      // saveAs_actionPerformed(null);
-      // }
-      // return false;
-      // }
-
       AlignmentExportData exportData = getAlignmentForExport(format,
               viewport, null);
       if (exportData.getSettings().isCancelled())
@@ -1213,15 +1206,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
         try
         {
-          java.io.PrintWriter out = new java.io.PrintWriter(
-                  new java.io.FileWriter(file));
+          PrintWriter out = new PrintWriter(new FileWriter(file));
 
           out.print(output);
           out.close();
           this.setTitle(file);
           statusBar.setText(MessageManager.formatMessage(
                   "label.successfully_saved_to_file_in_format",
-                  new Object[] { fileName, format }));
+                  new Object[] { fileName, format.getName() }));
         } catch (Exception ex)
         {
           success = false;
@@ -1266,8 +1258,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void outputText_actionPerformed(ActionEvent e)
   {
-
-    FileFormatI fileFormat = FileFormat.forName(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     AlignmentExportData exportData = getAlignmentForExport(fileFormat,
             viewport, null);
     if (exportData.getSettings().isCancelled())
index df0142c..7a0b0af 100644 (file)
@@ -30,7 +30,7 @@ import jalview.bin.Jalview;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SequenceI;
-import jalview.io.AlignmentFileI;
+import jalview.io.AlignmentFileReaderI;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormatException;
@@ -73,7 +73,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
 
   AlignViewportI viewport;
 
-  AlignmentFileI source = null;
+  AlignmentFileReaderI source = null;
 
   public CutAndPasteTransfer()
   {
@@ -233,7 +233,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
       if (!Jalview.isHeadlessMode())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                AppletFormatAdapter.SUPPORTED_FORMATS,
+                AppletFormatAdapter.getSupportedFormats(),
                 MessageManager.getString("label.couldnt_read_data"),
                 JvOptionPane.WARNING_MESSAGE);
       }
@@ -262,7 +262,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
     {
       String title = MessageManager.formatMessage(
               "label.input_cut_paste_params",
-              new String[] { format.toString() });
+              new String[] { format.getName() });
       FeatureSettingsModelI proxyColourScheme = source
               .getFeatureColourScheme();
 
@@ -340,7 +340,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
       if (!Jalview.isHeadlessMode())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                AppletFormatAdapter.SUPPORTED_FORMATS,
+                AppletFormatAdapter.getSupportedFormats(),
                 MessageManager.getString("label.couldnt_read_data"),
                 JvOptionPane.WARNING_MESSAGE);
       }
index ac957d8..4ce42dc 100644 (file)
@@ -31,6 +31,7 @@ import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatException;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileLoader;
 import jalview.io.IdentifyFile;
 import jalview.io.JalviewFileChooser;
@@ -1025,20 +1026,21 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       Cache.setProperty("LAST_DIRECTORY", chooser
               .getSelectedFile().getParent());
 
-      FileFormatI format = null;
-      FileFormatI selectedFormat = chooser.getSelectedFormat();
-      if (FileFormat.Jalview.equals(selectedFormat))
-      {
-        format = FileFormat.Jalview;
-      }
-      else
+      FileFormatI format = chooser.getSelectedFormat();
+
+      /*
+       * Call IdentifyFile to verify the file contains what its extension implies.
+       * Skip this step for dynamically added file formats, because
+       * IdentifyFile does not know how to recognise them.
+       */
+      if (FileFormats.getInstance().isIdentifiable(format))
       {
         try
         {
           format = new IdentifyFile().identify(choice, DataSourceType.FILE);
         } catch (FileFormatException e)
         {
-          // format is null
+          // format = null; //??
         }
       }
 
index 4f5a018..aa01bf5 100644 (file)
@@ -46,8 +46,9 @@ import javax.swing.ButtonGroup;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JColorChooser;
 import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
 import javax.swing.JRadioButtonMenuItem;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
 
 /**
  * DOCUMENT ME!
@@ -81,6 +82,7 @@ public class PCAPanel extends GPCAPanel implements Runnable,
    */
   public PCAPanel(AlignmentPanel ap)
   {
+    super();
     this.av = ap.av;
     this.ap = ap;
 
@@ -121,6 +123,16 @@ public class PCAPanel extends GPCAPanel implements Runnable,
 
       return;
     }
+
+    addInternalFrameListener(new InternalFrameAdapter()
+    {
+      @Override
+      public void internalFrameClosed(InternalFrameEvent e)
+      {
+        close_actionPerformed();
+      }
+    });
+
     pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
     PaintRefresher.Register(this, av.getSequenceSetId());
 
@@ -130,6 +142,15 @@ public class PCAPanel extends GPCAPanel implements Runnable,
     worker.start();
   }
 
+  /**
+   * Ensure references to potentially very large objects (the PCA matrices) are
+   * nulled when the frame is closed
+   */
+  protected void close_actionPerformed()
+  {
+    pcaModel = null;
+  }
+
   @Override
   protected void scoreMatrix_menuSelected()
   {
index e1b2560..e36204c 100644 (file)
@@ -38,8 +38,8 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FormatAdapter;
 import jalview.io.SequenceAnnotationReport;
 import jalview.schemes.AnnotationColourGradient;
@@ -79,7 +79,6 @@ import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JColorChooser;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
 import javax.swing.JPopupMenu;
 import javax.swing.JRadioButtonMenuItem;
 
@@ -249,14 +248,13 @@ public class PopupMenu extends JPopupMenu
     colours.add(strandColour);
     colours.add(turnColour);
     colours.add(buriedColour);
-    colours.add(abovePIDColour);
     colours.add(userDefinedColour);
     colours.add(PIDColour);
     colours.add(BLOSUM62Colour);
     colours.add(purinePyrimidineColour);
     colours.add(RNAInteractionColour);
 
-    for (String ff : FileFormat.getWritableFormats(true))
+    for (String ff : FileFormats.getInstance().getWritableFormats(true))
     {
       JMenuItem item = new JMenuItem(ff);
 
@@ -536,9 +534,16 @@ public class PopupMenu extends JPopupMenu
         noColourmenuItem.setSelected(true);
       }
 
-      if (sg.cs != null && sg.cs.conservationApplied())
+      if (sg.cs != null)
       {
+        if (sg.cs.conservationApplied())
+        {
         conservationMenuItem.setSelected(true);
+        }
+        if (sg.cs.getThreshold() > 0)
+        {
+          abovePIDColour.setSelected(true);
+        }
       }
       displayNonconserved.setSelected(sg.getShowNonconserved());
       showText.setSelected(sg.getDisplayText());
@@ -2274,7 +2279,8 @@ public class PopupMenu extends JPopupMenu
     // or we simply trust the user wants
     // wysiwig behaviour
 
-    FileFormatI fileFormat = FileFormat.forName(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     cap.setText(new FormatAdapter(ap).formatSequences(fileFormat, ap, true));
   }
 
index 0b65c1b..422745a 100755 (executable)
@@ -701,7 +701,7 @@ public class Preferences extends GPreferences
       if (format != null)
       {
         Cache.applicationProperties.setProperty("DEFAULT_FILE_FORMAT",
-                format.toString());
+                format.getName());
       }
       startupFileTextfield.setText(chooser.getSelectedFile()
               .getAbsolutePath());
index 0aa2459..00d465a 100755 (executable)
@@ -424,6 +424,9 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
   {
   }
 
+  /**
+   * Creates a tooltip when the mouse is over a hidden columns marker
+   */
   @Override
   public void mouseMoved(MouseEvent evt)
   {
@@ -448,11 +451,11 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
           ToolTipManager.sharedInstance().registerComponent(this);
           this.setToolTipText(MessageManager
                   .getString("label.reveal_hidden_columns"));
-          break;
+          repaint();
+          return;
         }
       }
     }
-    repaint();
   }
 
   /**
index 8726c4a..5b87445 100644 (file)
@@ -60,7 +60,6 @@ import java.awt.event.MouseWheelListener;
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.SwingUtilities;
 import javax.swing.ToolTipManager;
@@ -1589,19 +1588,11 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     if (stretchGroup == null)
     {
-      stretchGroup = av.getAlignment().findGroup(sequence);
-
-      if ((stretchGroup != null) && (res > stretchGroup.getStartRes())
-              && (res < stretchGroup.getEndRes()))
-      {
-        av.setSelectionGroup(stretchGroup);
-      }
-      else
-      {
-        stretchGroup = null;
-      }
+      stretchGroup = av.getAlignment().findGroup(sequence, res);
+      av.setSelectionGroup(stretchGroup);
     }
-    else if (!stretchGroup.getSequences(null).contains(sequence)
+    if (stretchGroup == null
+            || !stretchGroup.getSequences(null).contains(sequence)
             || (stretchGroup.getStartRes() > res)
             || (stretchGroup.getEndRes() < res))
     {
index 4de510a..7333075 100755 (executable)
@@ -40,7 +40,8 @@ import java.util.Vector;
  * @author $author$
  * @version $Revision$
  */
-public abstract class AlignFile extends FileParse implements AlignmentFileI
+public abstract class AlignFile extends FileParse implements
+        AlignmentFileReaderI, AlignmentFileWriterI
 {
   int noSeqs = 0;
 
@@ -416,4 +417,8 @@ public abstract class AlignFile extends FileParse implements AlignmentFileI
     }
   }
 
+  protected void addSequence(SequenceI seq)
+  {
+    seqs.add(seq);
+  }
 }
similarity index 69%
rename from src/jalview/io/AlignmentFileI.java
rename to src/jalview/io/AlignmentFileReaderI.java
index 1a000a3..77a7643 100644 (file)
@@ -6,7 +6,7 @@ import jalview.api.FeatureSettingsModelI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
 
-public interface AlignmentFileI
+public interface AlignmentFileReaderI
 {
 
   SequenceI[] getSeqsAsArray();
@@ -15,16 +15,8 @@ public interface AlignmentFileI
 
   void addGroups(AlignmentI al);
 
-  void setNewlineString(String newline);
-
-  void setExportSettings(AlignExportSettingI exportSettings);
-
-  void configureForView(AlignmentViewPanel viewpanel);
-
   void setSeqs(SequenceI[] sequencesArray);
 
-  String print(SequenceI[] seqs, boolean jvsuffix);
-
   boolean hasWarningMessage();
 
   String getWarningMessage();
diff --git a/src/jalview/io/AlignmentFileWriterI.java b/src/jalview/io/AlignmentFileWriterI.java
new file mode 100644 (file)
index 0000000..d8e2dd4
--- /dev/null
@@ -0,0 +1,24 @@
+package jalview.io;
+
+import jalview.api.AlignExportSettingI;
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureSettingsModelI;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+
+public interface AlignmentFileWriterI
+{
+
+  void setNewlineString(String newline);
+
+  void setExportSettings(AlignExportSettingI exportSettings);
+
+  void configureForView(AlignmentViewPanel viewpanel);
+
+  String print(SequenceI[] seqs, boolean jvsuffix);
+
+  boolean hasWarningMessage();
+
+  String getWarningMessage();
+
+}
index 45d65d6..c5a80e3 100755 (executable)
@@ -64,7 +64,7 @@ public class AppletFormatAdapter
    */
   boolean serviceSecondaryStruct = false;
 
-  private AlignmentFileI alignFile = null;
+  private AlignmentFileReaderI alignFile = null;
 
   String inFile;
 
@@ -77,9 +77,16 @@ public class AppletFormatAdapter
 
   public static String INVALID_CHARACTERS = "Contains invalid characters";
 
-  public static String SUPPORTED_FORMATS = "Formats currently supported are\n"
-          + prettyPrint(FileFormat.getReadableFormats());
-
+  /**
+   * Returns an error message with a list of supported readable file formats
+   * 
+   * @return
+   */
+  public static String getSupportedFormats()
+  {
+    return "Formats currently supported are\n"
+          + prettyPrint(FileFormats.getInstance().getReadableFormats());
+  }
   public AppletFormatAdapter()
   {
   }
@@ -157,7 +164,7 @@ public class AppletFormatAdapter
         }
         else
         {
-          // todo is MCview parsing obsolete yet?
+          // todo is MCview parsing obsolete yet? JAL-2120
           StructureImportSettings.setShowSeqFeatures(true);
           alignFile = new MCview.PDBfile(annotFromStructure,
                   localSecondaryStruct, serviceSecondaryStruct, inFile,
@@ -168,7 +175,9 @@ public class AppletFormatAdapter
       }
       else
       {
-        alignFile = fileFormat.getAlignmentFile(inFile, sourceType);
+        // alignFile = fileFormat.getAlignmentFile(inFile, sourceType);
+        alignFile = fileFormat.getReader(new FileParse(inFile,
+                sourceType));
       }
       return buildAlignmentFromFile();
     } catch (Exception e)
@@ -208,7 +217,7 @@ public class AppletFormatAdapter
         throw new IOException(e.getMessage());
       }
     }
-    throw new FileFormatException(SUPPORTED_FORMATS);
+    throw new FileFormatException(getSupportedFormats());
   }
 
   /**
@@ -248,7 +257,7 @@ public class AppletFormatAdapter
       }
       else
       {
-        alignFile = format.getAlignmentFile(source);
+        alignFile = format.getReader(source);
       }
 
       return buildAlignmentFromFile();
@@ -287,7 +296,7 @@ public class AppletFormatAdapter
       }
 
       // If we get to this stage, the format was not supported
-      throw new FileFormatException(SUPPORTED_FORMATS);
+      throw new FileFormatException(getSupportedFormats());
     }
   }
 
@@ -361,7 +370,7 @@ public class AppletFormatAdapter
   {
     try
     {
-      AlignmentFileI afile = format.getAlignmentFile(alignment);
+      AlignmentFileWriterI afile = format.getWriter(alignment);
 
       afile.setNewlineString(newline);
       afile.setExportSettings(exportSettings);
@@ -389,7 +398,8 @@ public class AppletFormatAdapter
       return afileresp;
     } catch (Exception e)
     {
-      System.err.println("Failed to write alignment as a '" + format
+      System.err.println("Failed to write alignment as a '"
+              + format.getName()
               + "' file\n");
       e.printStackTrace();
     }
@@ -638,7 +648,7 @@ public class AppletFormatAdapter
     return null;
   }
 
-  public AlignmentFileI getAlignFile()
+  public AlignmentFileReaderI getAlignFile()
   {
     return alignFile;
   }
index 5f441d2..a11147c 100644 (file)
@@ -6,31 +6,20 @@ import jalview.ext.jmol.JmolParser;
 import jalview.structure.StructureImportSettings;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 public enum FileFormat implements FileFormatI
 {
   Fasta("Fasta", "fa, fasta, mfa, fastq", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new FastaFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new FastaFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new FastaFile();
     }
@@ -38,21 +27,14 @@ public enum FileFormat implements FileFormatI
   Pfam("PFAM", "pfam", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PfamFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new PfamFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new PfamFile();
     }
@@ -60,20 +42,14 @@ public enum FileFormat implements FileFormatI
   Stockholm("Stockholm", "sto,stk", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new StockholmFile(inFile, sourceType);
-    }
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new StockholmFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new StockholmFile(al);
     }
@@ -83,20 +59,14 @@ public enum FileFormat implements FileFormatI
   PIR("PIR", "pir", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PIRFile(inFile, sourceType);
-    }
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new PIRFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new PIRFile();
     }
@@ -104,19 +74,14 @@ public enum FileFormat implements FileFormatI
   BLC("BLC", "BLC", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new BLCFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new BLCFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new BLCFile();
     }
@@ -124,21 +89,14 @@ public enum FileFormat implements FileFormatI
   AMSA("AMSA", "amsa", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new AMSAFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new AMSAFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new AMSAFile(al);
     }
@@ -146,19 +104,14 @@ public enum FileFormat implements FileFormatI
   Html("HTML", "html", true, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new HtmlFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new HtmlFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new HtmlFile();
     }
@@ -173,40 +126,30 @@ public enum FileFormat implements FileFormatI
   Rnaml("RNAML", "xml,rnaml", true, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new RnamlFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new RnamlFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new RnamlFile();
     }
 
   },
-  Json("JSON","json", true, true)
+  Json("JSON", "json", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new JSONFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new JSONFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new JSONFile();
     }
@@ -221,19 +164,14 @@ public enum FileFormat implements FileFormatI
   Pileup("PileUp", "pileup", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PileUpfile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new PileUpfile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new PileUpfile();
     }
@@ -242,19 +180,14 @@ public enum FileFormat implements FileFormatI
   MSF("MSF", "msf", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new MSFfile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new MSFfile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new MSFfile();
     }
@@ -263,19 +196,14 @@ public enum FileFormat implements FileFormatI
   Clustal("Clustal", "aln", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new ClustalFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new ClustalFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new ClustalFile();
     }
@@ -283,21 +211,14 @@ public enum FileFormat implements FileFormatI
   Phylip("PHYLIP", "phy", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PhylipFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new PhylipFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new PhylipFile();
     }
@@ -305,16 +226,7 @@ public enum FileFormat implements FileFormatI
   Jnet("JnetFile", "", false, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      JPredFile af = new JPredFile(inFile, sourceType);
-      af.removeNonSequences();
-      return af;
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       JPredFile af = new JPredFile(source);
@@ -323,7 +235,7 @@ public enum FileFormat implements FileFormatI
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return null; // todo is this called?
     }
@@ -332,54 +244,22 @@ public enum FileFormat implements FileFormatI
   Features("GFF or Jalview features", "gff2,gff3", true, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new FeaturesFile(true, inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new FeaturesFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new FeaturesFile();
     }
   },
   PDB("PDB", "pdb,ent", true, false)
   {
-
-    @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      // TODO obtain config value from preference settings.
-      // Set value to 'true' to test PDB processing with Jmol: JAL-1213
-      boolean isParseWithJMOL = StructureImportSettings
-              .getDefaultStructureFileFormat() != PDBEntry.Type.PDB;
-      if (isParseWithJMOL)
-      {
-        return new JmolParser(inFile, sourceType);
-      }
-      else
-      {
-        StructureImportSettings.setShowSeqFeatures(true);
-        return new MCview.PDBfile(
-                StructureImportSettings.isVisibleChainAnnotation(),
-                StructureImportSettings.isProcessSecondaryStructure(),
-                StructureImportSettings.isExternalSecondaryStructure(),
-                inFile,
-                sourceType);
-      }
-    }
-
     @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       boolean isParseWithJMOL = StructureImportSettings
@@ -400,7 +280,7 @@ public enum FileFormat implements FileFormatI
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new JmolParser(); // todo or null?
     }
@@ -413,23 +293,15 @@ public enum FileFormat implements FileFormatI
   },
   MMCif("mmCIF", "cif", true, false)
   {
-
-    @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new JmolParser(inFile, sourceType);
-    }
-
     @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return new JmolParser(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return new JmolParser(); // todo or null?
     }
@@ -442,23 +314,15 @@ public enum FileFormat implements FileFormatI
   },
   Jalview("Jalview", "jar,jvp", true, true)
   {
-
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return null;
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
+    public AlignmentFileReaderI getReader(FileParse source)
             throws IOException
     {
       return null;
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileWriterI getWriter(AlignmentI al)
     {
       return null;
     }
@@ -468,20 +332,13 @@ public enum FileFormat implements FileFormatI
     {
       return false;
     }
-  };
 
-  /**
-   * A lookup map of enums by upper-cased name
-   */
-  private static Map<String, FileFormat> names;
-  static
-  {
-    names = new HashMap<String, FileFormat>();
-    for (FileFormat format : FileFormat.values())
+    @Override
+    public boolean isIdentifiable()
     {
-      names.put(format.toString().toUpperCase(), format);
+      return false;
     }
-  }
+  };
 
   private boolean writable;
 
@@ -491,65 +348,12 @@ public enum FileFormat implements FileFormatI
 
   private String name;
 
-  /**
-   * Answers a list of writeable file formats (as string, corresponding to the
-   * toString() and forName() methods)
-   * 
-   * @return
-   */
-  public static List<String> getWritableFormats(boolean textOnly)
-  {
-    List<String> l = new ArrayList<String>();
-    for (FileFormatI ff : values())
-    {
-      if (ff.isWritable() && (!textOnly || ff.isTextFormat()))
-      {
-        l.add(ff.toString());
-      }
-    }
-    return l;
-  }
-
-  /**
-   * Answers a list of readable file formats (as string, corresponding to the
-   * toString() and forName() methods)
-   * 
-   * @return
-   */
-  public static List<String> getReadableFormats()
-  {
-    List<String> l = new ArrayList<String>();
-    for (FileFormatI ff : values())
-    {
-      if (ff.isReadable())
-      {
-        l.add(ff.toString());
-      }
-    }
-    return l;
-  }
-
   @Override
   public boolean isComplexAlignFile()
   {
     return false;
   }
 
-  /**
-   * Returns the file format with the given name, or null if format is null or
-   * invalid. Unlike valueOf(), this is not case-sensitive, to be kind to
-   * writers of javascript.
-   * 
-   * @param format
-   * @return
-   */
-  public static FileFormatI forName(String format)
-  {
-    // or could store format.getShortDescription().toUpperCase()
-    // in order to decouple 'given name' from enum name
-    return format == null ? null : names.get(format.toUpperCase());
-  }
-
   @Override
   public boolean isReadable()
   {
@@ -586,19 +390,17 @@ public enum FileFormat implements FileFormatI
     return extensions;
   }
 
+  /**
+   * Answers the display name of the file format (as for example shown in menu
+   * options). This name should not be locale (language) dependent.
+   */
   @Override
-  public String toString()
+  public String getName()
   {
     return name;
   }
 
   @Override
-  public AlignmentFileI getAlignmentFile()
-  {
-    return getAlignmentFile((AlignmentI) null);
-  }
-
-  @Override
   public boolean isTextFormat()
   {
     return true;
@@ -609,4 +411,14 @@ public enum FileFormat implements FileFormatI
   {
     return false;
   }
+
+  /**
+   * By default, answers true, indicating the format is one that can be
+   * identified by IdentifyFile. Formats that cannot be identified should
+   * override this method to return false.
+   */
+  public boolean isIdentifiable()
+  {
+    return true;
+  }
 }
index 0593d1e..e6f390d 100644 (file)
@@ -6,20 +6,19 @@ import java.io.IOException;
 
 public interface FileFormatI
 {
+  AlignmentFileReaderI getReader(FileParse source) throws IOException;
 
-  AlignmentFileI getAlignmentFile(String inFile, DataSourceType sourceType)
-          throws IOException;
-
-  // TODO can we get rid of one of these methods?
-  AlignmentFileI getAlignmentFile(FileParse source) throws IOException;
-
-  AlignmentFileI getAlignmentFile(AlignmentI al);
-
-  AlignmentFileI getAlignmentFile();
+  AlignmentFileWriterI getWriter(AlignmentI al);
 
   boolean isComplexAlignFile();
 
   /**
+   * Answers the display name of the file format (as for example shown in menu
+   * options). This name should not be locale (language) dependent.
+   */
+  String getName();
+
+  /**
    * Returns a comma-separated list of file extensions associated with the
    * format
    * 
@@ -29,9 +28,9 @@ public interface FileFormatI
 
   /**
    * Answers true if the format is one that Jalview can read. This implies that
-   * the format provides implementations for getAlignmentFile(FileParse) and
-   * getAlignmentFile(String, DataSourceType) which parse the data source for
-   * sequence data.
+   * the format provides an implementation for getReader which can parse a data
+   * source for sequence data. Readable formats are included in the options in
+   * the open file dialogue.
    * 
    * @return
    */
@@ -39,8 +38,9 @@ public interface FileFormatI
 
   /**
    * Answers true if the format is one that Jalview can write. This implies that
-   * the object returned by getAlignmentFile provides an implementation of the
-   * print() method.
+   * the object returned by getWriter provides an implementation of the print()
+   * method. Writable formats are included in the options in the Save As file
+   * dialogue, and the 'output to Textbox' option (if text format).
    * 
    * @return
    */
@@ -55,7 +55,7 @@ public interface FileFormatI
   boolean isTextFormat();
 
   /**
-   * Answers true if the file format is one that provides a 3D structure
+   * Answers true if the file format is one that provides 3D structure data
    * 
    * @return
    */
diff --git a/src/jalview/io/FileFormats.java b/src/jalview/io/FileFormats.java
new file mode 100644 (file)
index 0000000..158489e
--- /dev/null
@@ -0,0 +1,168 @@
+package jalview.io;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A singleton registry of alignment file formats known to Jalview. On startup,
+ * the 'built-in' formats are added (from the FileFormat enum). Additional
+ * formats can be registered (or formats deregistered) programmatically, for
+ * example with a Groovy script.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class FileFormats
+{
+  private static FileFormats instance = new FileFormats();
+
+  /*
+   * A lookup map of file formats by upper-cased name
+   */
+  private static Map<String, FileFormatI> formats;
+
+  /*
+   * Formats in this set are capable of being identified by IdentifyFile 
+   */
+  private static Set<FileFormatI> identifiable;
+
+  public static FileFormats getInstance()
+  {
+    return instance;
+  }
+
+  /**
+   * Private constructor registers Jalview's built-in file formats
+   */
+  private FileFormats()
+  {
+    reset();
+  }
+
+  /**
+   * Reset to just the built-in file formats packaged with Jalview. These are
+   * added (and will be shown in menus) in the order of their declaration in the
+   * FileFormat enum.
+   */
+  public synchronized void reset()
+  {
+    formats = new LinkedHashMap<String, FileFormatI>();
+    identifiable = new HashSet<FileFormatI>();
+    for (FileFormat format : FileFormat.values())
+    {
+      registerFileFormat(format, format.isIdentifiable());
+    }
+  }
+
+  /**
+   * Answers true if the format is one that can be identified by IdentifyFile.
+   * Answers false for a null value.
+   */
+  public boolean isIdentifiable(FileFormatI f)
+  {
+    return identifiable.contains(f);
+  }
+
+  /**
+   * Registers a file format for case-insensitive lookup by name
+   * 
+   * @param format
+   */
+  public void registerFileFormat(FileFormatI format)
+  {
+    registerFileFormat(format, false);
+  }
+
+  protected void registerFileFormat(FileFormatI format,
+          boolean isIdentifiable)
+  {
+    String name = format.getName().toUpperCase();
+    if (formats.containsKey(name))
+    {
+      System.err.println("Overwriting file format: " + format.getName());
+    }
+    formats.put(name, format);
+    if (isIdentifiable)
+    {
+      identifiable.add(format);
+    }
+  }
+
+  /**
+   * Deregisters a file format so it is no longer shown in menus
+   * 
+   * @param name
+   */
+  public void deregisterFileFormat(String name)
+  {
+    FileFormatI ff = formats.remove(name.toUpperCase());
+    identifiable.remove(ff);
+  }
+
+  /**
+   * Answers a list of writeable file formats (as strings, corresponding to the
+   * getName() and forName() methods)
+   * 
+   * @param textOnly
+   *          if true, only text (not binary) formats are included
+   * @return
+   */
+  public List<String> getWritableFormats(boolean textOnly)
+  {
+    List<String> l = new ArrayList<String>();
+    for (FileFormatI ff : formats.values())
+    {
+      if (ff.isWritable() && (!textOnly || ff.isTextFormat()))
+      {
+        l.add(ff.getName());
+      }
+    }
+    return l;
+  }
+
+  /**
+   * Answers a list of readable file formats (as strings, corresponding to the
+   * getName() and forName() methods)
+   * 
+   * @return
+   */
+  public List<String> getReadableFormats()
+  {
+    List<String> l = new ArrayList<String>();
+    for (FileFormatI ff : formats.values())
+    {
+      if (ff.isReadable())
+      {
+        l.add(ff.getName());
+      }
+    }
+    return l;
+  }
+
+  /**
+   * Returns the file format with the given name, or null if format is null or
+   * invalid. This is not case-sensitive.
+   * 
+   * @param format
+   * @return
+   */
+  public FileFormatI forName(String format)
+  {
+    return format == null ? null : formats.get(format.toUpperCase());
+  }
+
+  /**
+   * Returns an iterable collection of registered file formats (in the order in
+   * which they were registered)
+   * 
+   * @return
+   */
+  public Iterable<FileFormatI> getFormats()
+  {
+    return formats.values();
+  }
+}
index 3ad74c7..4f83ab1 100755 (executable)
@@ -53,7 +53,8 @@ public class FileLoader implements Runnable
 
   FileFormatI format;
 
-  AlignmentFileI source = null; // alternative specification of where data comes
+  AlignmentFileReaderI source = null; // alternative specification of where data
+                                      // comes
 
   // from
 
@@ -160,7 +161,7 @@ public class FileLoader implements Runnable
    * @param format
    * @return alignFrame constructed from file contents
    */
-  public AlignFrame LoadFileWaitTillLoaded(AlignmentFileI source,
+  public AlignFrame LoadFileWaitTillLoaded(AlignmentFileReaderI source,
           FileFormatI format)
   {
     this.source = source;
@@ -237,7 +238,7 @@ public class FileLoader implements Runnable
 
     if (protocol == DataSourceType.FILE)
     {
-      Cache.setProperty("DEFAULT_FILE_FORMAT", format.toString());
+      Cache.setProperty("DEFAULT_FILE_FORMAT", format.getName());
     }
   }
 
@@ -279,7 +280,7 @@ public class FileLoader implements Runnable
                   Desktop.desktop,
                   MessageManager.getString("label.couldnt_read_data")
                           + " in " + file + "\n"
-                          + AppletFormatAdapter.SUPPORTED_FORMATS,
+                          + AppletFormatAdapter.getSupportedFormats(),
                   MessageManager.getString("label.couldnt_read_data"),
                   JvOptionPane.WARNING_MESSAGE);
         }
@@ -311,27 +312,27 @@ public class FileLoader implements Runnable
       }
       else
       {
-        String error = AppletFormatAdapter.SUPPORTED_FORMATS;
-          try
+        String error = AppletFormatAdapter.getSupportedFormats();
+        try
+        {
+          if (source != null)
           {
-            if (source != null)
-            {
-              // read from the provided source
+            // read from the provided source
             al = new FormatAdapter().readFromFile(source, format);
-            }
-            else
-            {
-
-              // open a new source and read from it
-              FormatAdapter fa = new FormatAdapter();
-              al = fa.readFile(file, protocol, format);
-              source = fa.getAlignFile(); // keep reference for later if
-                                          // necessary.
-            }
-          } catch (java.io.IOException ex)
+          }
+          else
           {
-            error = ex.getMessage();
+
+            // open a new source and read from it
+            FormatAdapter fa = new FormatAdapter();
+            al = fa.readFile(file, protocol, format);
+            source = fa.getAlignFile(); // keep reference for later if
+                                        // necessary.
           }
+        } catch (java.io.IOException ex)
+        {
+          error = ex.getMessage();
+        }
 
         if ((al != null) && (al.getHeight() > 0) && al.hasValidSequence())
         {
index 1dbfdef..d9dd79d 100755 (executable)
@@ -155,84 +155,13 @@ public class FormatAdapter extends AppletFormatAdapter
    */
   public String formatSequences(FileFormatI format, SequenceI[] seqs)
   {
-    //
-    // try
-    // {
     boolean withSuffix = getCacheSuffixDefault(format);
-    return format.getAlignmentFile().print(seqs, withSuffix);
-      // null;
-      //
-      // if (format.equalsIgnoreCase("FASTA"))
-      // {
-      // afile = new FastaFile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("FASTA_JVSUFFIX",
-      // true));
-      // }
-      // else if (format.equalsIgnoreCase("MSF"))
-      // {
-      // afile = new MSFfile();
-      // afile.addJVSuffix(jalview.bin.Cache
-      // .getDefault("MSF_JVSUFFIX", true));
-      // }
-      // else if (format.equalsIgnoreCase("PileUp"))
-      // {
-      // afile = new PileUpfile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("PILEUP_JVSUFFIX",
-      // true));
-      // }
-      // else if (format.equalsIgnoreCase("CLUSTAL"))
-      // {
-      // afile = new ClustalFile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("CLUSTAL_JVSUFFIX",
-      // true));
-      // }
-      // else if (format.equalsIgnoreCase("BLC"))
-      // {
-      // afile = new BLCFile();
-      // afile.addJVSuffix(jalview.bin.Cache
-      // .getDefault("BLC_JVSUFFIX", true));
-      // }
-      // else if (format.equalsIgnoreCase("PIR"))
-      // {
-      // afile = new PIRFile();
-      // afile.addJVSuffix(jalview.bin.Cache
-      // .getDefault("PIR_JVSUFFIX", true));
-      // }
-      // else if (format.equalsIgnoreCase("PFAM"))
-      // {
-      // afile = new PfamFile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("PFAM_JVSUFFIX",
-      // true));
-      // }
-      // /*
-      // * amsa is not supported by this function - it requires an alignment
-      // * rather than a sequence vector else if
-      // (format.equalsIgnoreCase("AMSA"))
-      // * { afile = new AMSAFile(); afile.addJVSuffix(
-      // * jalview.bin.Cache.getDefault("AMSA_JVSUFFIX", true)); }
-      // */
-
-//      afile.setSeqs(seqs);
-//      String afileresp = afile.print();
-//      if (afile.hasWarningMessage())
-//      {
-//        System.err.println("Warning raised when writing as " + format
-//                + " : " + afile.getWarningMessage());
-//      }
-//      return afileresp;
-//    } catch (Exception e)
-//    {
-//      System.err.println("Failed to write alignment as a '" + format
-//              + "' file\n");
-//      e.printStackTrace();
-//    }
-//
-//    return null;
+    return format.getWriter(null).print(seqs, withSuffix);
   }
 
   public boolean getCacheSuffixDefault(FileFormatI format)
   {
-    return Cache.getDefault(format.toString() + "_JVSUFFIX", true);
+    return Cache.getDefault(format.getName() + "_JVSUFFIX", true);
   }
 
   public String formatSequences(FileFormatI format, AlignmentI alignment,
@@ -329,8 +258,8 @@ public class FormatAdapter extends AppletFormatAdapter
             selectedOnly);
   }
 
-  public AlignmentI readFromFile(AlignmentFileI source, FileFormatI format)
-          throws IOException
+  public AlignmentI readFromFile(AlignmentFileReaderI source,
+          FileFormatI format) throws IOException
   {
     FileParse fp = new FileParse(source.getInFile(),
             source.getDataSourceType());
index 72a1155..0556e76 100755 (executable)
@@ -72,7 +72,7 @@ public class IdentifyFile
     // preserves original behaviour prior to version 2.3
   }
 
-  public FileFormatI identify(AlignmentFileI file, boolean closeSource)
+  public FileFormatI identify(AlignmentFileReaderI file, boolean closeSource)
           throws IOException
   {
     FileParse fp = new FileParse(file.getInFile(), file.getDataSourceType());
index 7ccdaa9..2a0f8b1 100755 (executable)
@@ -68,12 +68,12 @@ public class JalviewFileChooser extends JFileChooser
   {
     List<String> extensions = new ArrayList<String>();
     List<String> descs = new ArrayList<String>();
-    for (FileFormatI format : FileFormat.values())
+    for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isReadable())
       {
         extensions.add(format.getExtensions());
-        descs.add(format.toString());
+        descs.add(format.getName());
       }
     }
     return new JalviewFileChooser(directory,
@@ -96,12 +96,12 @@ public class JalviewFileChooser extends JFileChooser
     // with a lambda expression parameter for isReadable/isWritable
     List<String> extensions = new ArrayList<String>();
     List<String> descs = new ArrayList<String>();
-    for (FileFormatI format : FileFormat.values())
+    for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isWritable())
       {
         extensions.add(format.getExtensions());
-        descs.add(format.toString());
+        descs.add(format.getName());
       }
     }
     return new JalviewFileChooser(directory,
@@ -269,7 +269,7 @@ public class JalviewFileChooser extends JFileChooser
       format = format.substring(0, parenPos).trim();
       try
       {
-        return FileFormat.valueOf(format);
+        return FileFormats.getInstance().forName(format);
       } catch (IllegalArgumentException e)
       {
         System.err.println("Unexpected format: " + format);
index 3461110..6bfb3b9 100755 (executable)
@@ -38,9 +38,9 @@ public class JalviewFileView extends FileView
   private void loadExtensions()
   {
     extensions = new HashMap<String, String>();
-    for (FileFormatI ff : FileFormat.values())
+    for (FileFormatI ff : FileFormats.getInstance().getFormats())
     {
-      String desc = ff.toString() + " file";
+      String desc = ff.getName() + " file";
       String exts = ff.getExtensions();
       for (String ext : exts.split(","))
       {
index 4de3d3a..dc17397 100755 (executable)
@@ -26,7 +26,7 @@ import jalview.bin.Cache;
 import jalview.gui.JvOptionPane;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.Preferences;
-import jalview.io.FileFormat;
+import jalview.io.FileFormats;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.util.MessageManager;
 
@@ -245,7 +245,7 @@ public class GAlignFrame extends JInternalFrame
       setJMenuBar(alignFrameMenuBar);
 
       // dynamically fill save as menu with available formats
-      for (String ff : FileFormat.getWritableFormats(true))
+      for (String ff : FileFormats.getInstance().getWritableFormats(true))
       {
         JMenuItem item = new JMenuItem(ff);
 
@@ -2319,7 +2319,7 @@ public class GAlignFrame extends JInternalFrame
     colourMenu.add(buriedColour);
     colourMenu.add(nucleotideColour);
     colourMenu.add(purinePyrimidineColour);
-    colourMenu.add(RNAInteractionColour);
+    // colourMenu.add(RNAInteractionColour);
     // colourMenu.add(covariationColour);
     colourMenu.add(tcoffeeColour);
     colourMenu.add(userDefinedColour);
index bb7ed37..28b9d67 100755 (executable)
@@ -57,24 +57,33 @@ public class Matrix
   int maxIter = 45; // fudge - add 15 iterations, just in case
 
   /**
-   * Creates a new Matrix object.
+   * Creates a new Matrix object. For example
    * 
-   * @param value
-   *          DOCUMENT ME!
+   * <pre>
+   *   new Matrix(new double[][] {{2, 3}, {4, 5}, 2, 2)
+   * constructs
+   *   (2 3)
+   *   (4 5)
+   * </pre>
+   * 
+   * Note that ragged arrays (with not all rows, or columns, of the same
+   * length), are not supported by this class. They can be constructed, but
+   * results of operations on them are undefined and may throw exceptions.
+   * 
+   * @param values
+   *          the matrix values in row-major order
    * @param rows
-   *          DOCUMENT ME!
    * @param cols
-   *          DOCUMENT ME!
    */
-  public Matrix(double[][] value, int rows, int cols)
+  public Matrix(double[][] values, int rows, int cols)
   {
     this.rows = rows;
     this.cols = cols;
-    this.value = value;
+    this.value = values;
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns a new matrix which is the transposes of this one
    * 
    * @return DOCUMENT ME!
    */
@@ -113,15 +122,24 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns a new matrix which is the result of premultiplying this matrix by
+   * the supplied argument. If this of size AxB (A rows and B columns), and the
+   * argument is CxA (C rows and A columns), the result is of size CxB.
    * 
    * @param in
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
+   * @throws IllegalArgumentException
+   *           if the number of columns in the pre-multiplier is not equal to
+   *           the number of rows in the multiplicand (this)
    */
   public Matrix preMultiply(Matrix in)
   {
+    if (in.cols != this.rows)
+    {
+      throw new IllegalArgumentException("Can't pre-multiply " + this.rows
+              + " rows by " + in.cols + " columns");
+    }
     double[][] tmp = new double[in.rows][this.cols];
 
     for (int i = 0; i < in.rows; i++)
@@ -141,12 +159,10 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
    * 
    * @param in
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   public double[] vectorPostMultiply(double[] in)
   {
@@ -166,37 +182,34 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns a new matrix which is the result of postmultiplying this matrix by
+   * the supplied argument. If this of size AxB (A rows and B columns), and the
+   * argument is BxC (B rows and C columns), the result is of size AxC.
+   * <p>
+   * This method simply returns the result of in.preMultiply(this)
    * 
    * @param in
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
+   * @throws IllegalArgumentException
+   *           if the number of rows in the post-multiplier is not equal to the
+   *           number of columns in the multiplicand (this)
+   * @see #preMultiply(Matrix)
    */
   public Matrix postMultiply(Matrix in)
   {
-    double[][] out = new double[this.rows][in.cols];
-
-    for (int i = 0; i < this.rows; i++)
+    if (in.rows != this.cols)
     {
-      for (int j = 0; j < in.cols; j++)
-      {
-        out[i][j] = 0.0;
-
-        for (int k = 0; k < rows; k++)
-        {
-          out[i][j] = out[i][j] + (value[i][k] * in.value[k][j]);
-        }
-      }
+      throw new IllegalArgumentException("Can't post-multiply " + this.cols
+              + " columns by " + in.rows + " rows");
     }
-
-    return new Matrix(out, this.cols, in.rows);
+    return in.preMultiply(this);
   }
 
   /**
-   * DOCUMENT ME!
+   * Answers a new matrix with a copy of the values in this one
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   public Matrix copy()
   {
@@ -204,10 +217,11 @@ public class Matrix
 
     for (int i = 0; i < rows; i++)
     {
-      for (int j = 0; j < cols; j++)
-      {
-        newmat[i][j] = value[i][j];
-      }
+      System.arraycopy(value[i], 0, newmat[i], 0, value[i].length);
+      // for (int j = 0; j < cols; j++)
+      // {
+      // newmat[i][j] = value[i][j];
+      // }
     }
 
     return new Matrix(newmat, rows, cols);
@@ -738,20 +752,19 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns an array containing the values in the specified column
    * 
-   * @param n
-   *          DOCUMENT ME!
+   * @param col
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
-  public double[] getColumn(int n)
+  public double[] getColumn(int col)
   {
     double[] out = new double[rows];
 
     for (int i = 0; i < rows; i++)
     {
-      out[i] = value[i][n];
+      out[i] = value[i][col];
     }
 
     return out;
@@ -784,85 +797,4 @@ public class Matrix
       Format.print(ps, "%15.4e", e[j]);
     }
   }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param args
-   *          DOCUMENT ME!
-   */
-  public static void main(String[] args) throws Exception
-  {
-    int n = Integer.parseInt(args[0]);
-    double[][] in = new double[n][n];
-
-    for (int i = 0; i < n; i++)
-    {
-      for (int j = 0; j < n; j++)
-      {
-        in[i][j] = (double) Math.random();
-      }
-    }
-
-    Matrix origmat = new Matrix(in, n, n);
-
-    // System.out.println(" --- Original matrix ---- ");
-    // / origmat.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- transpose matrix ---- ");
-    Matrix trans = origmat.transpose();
-
-    // trans.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- OrigT * Orig ---- ");
-    Matrix symm = trans.postMultiply(origmat);
-
-    // symm.print(System.out);
-    // System.out.println();
-    // Copy the symmetric matrix for later
-    // Matrix origsymm = symm.copy();
-
-    // This produces the tridiagonal transformation matrix
-    // long tstart = System.currentTimeMillis();
-    symm.tred();
-
-    // long tend = System.currentTimeMillis();
-
-    // System.out.println("Time take for tred = " + (tend-tstart) + "ms");
-    // System.out.println(" ---Tridiag transform matrix ---");
-    // symm.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- D vector ---");
-    // symm.printD(System.out);
-    // System.out.println();
-    // System.out.println(" --- E vector ---");
-    // symm.printE(System.out);
-    // System.out.println();
-    // Now produce the diagonalization matrix
-    // tstart = System.currentTimeMillis();
-    symm.tqli();
-    // tend = System.currentTimeMillis();
-
-    // System.out.println("Time take for tqli = " + (tend-tstart) + " ms");
-    // System.out.println(" --- New diagonalization matrix ---");
-    // symm.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- D vector ---");
-    // symm.printD(System.out);
-    // System.out.println();
-    // System.out.println(" --- E vector ---");
-    // symm.printE(System.out);
-    // System.out.println();
-    // System.out.println(" --- First eigenvector --- ");
-    // double[] eigenv = symm.getColumn(0);
-    // for (int i=0; i < eigenv.length;i++) {
-    // Format.print(System.out,"%15.4f",eigenv[i]);
-    // }
-    // System.out.println();
-    // double[] neigenv = origsymm.vectorPostMultiply(eigenv);
-    // for (int i=0; i < neigenv.length;i++) {
-    // Format.print(System.out,"%15.4f",neigenv[i]/symm.d[0]);
-    // }
-    // System.out.println();
-  }
 }
index 389afcd..bf52027 100755 (executable)
@@ -884,21 +884,18 @@ public class Format
     String f = "";
     int e = 0;
     double dd = d;
-    double factor = 1;
 
     if (d != 0)
     {
       while (dd > 10)
       {
         e++;
-        factor /= 10;
         dd = dd / 10;
       }
 
       while (dd < 1)
       {
         e--;
-        factor *= 10;
         dd = dd * 10;
       }
     }
@@ -908,8 +905,7 @@ public class Format
       return fixed_format(d);
     }
 
-    d = d * factor;
-    f = f + fixed_format(d);
+    f = f + fixed_format(dd);
 
     if ((fmt == 'e') || (fmt == 'g'))
     {
index 7258f51..ba4054e 100644 (file)
@@ -222,7 +222,7 @@ public class Discoverer implements Runnable
                             + "\nNucleic Acids Research, Web Server issue (first published 15th April 2015)"
                             + "\ndoi://10.1093/nar/gkv332",
                     "http://www.compbio.dundee.ac.uk/JalviewWS/services/jpred",
-                    "JNet Secondary Structure Prediction") };
+                    "JPred Secondary Structure Prediction") };
         services = new Hashtable();
         serviceList = new Vector();
         buildServiceLists(defServices, serviceList, services);
index 2c05386..65847e6 100644 (file)
@@ -238,7 +238,7 @@ public class JPredClient extends WS1Client
 
     SequenceI seq = msf[0];
 
-    String altitle = "JNet prediction on " + seq.getName()
+    String altitle = "JPred prediction on " + seq.getName()
             + " using alignment from " + title;
 
     wsInfo.setProgressText("Job details for MSA based prediction (" + title
@@ -275,7 +275,7 @@ public class JPredClient extends WS1Client
     wsInfo.setProgressText("Job details for prediction on sequence :\n>"
             + seq.getName() + "\n"
             + AlignSeq.extractGaps("-. ", seq.getSequenceAsString()) + "\n");
-    String altitle = "JNet prediction for sequence " + seq.getName()
+    String altitle = "JPred prediction for sequence " + seq.getName()
             + " from " + title;
 
     Hashtable SequenceInfo = jalview.analysis.SeqsetUtils
index 4e5cadc..e685d00 100644 (file)
@@ -180,8 +180,8 @@ class JPredThread extends JWS1Thread implements WSClientI
         else
         {
           throw (new Exception(MessageManager.formatMessage(
-                  "exception.unknown_format_for_file", new String[] {
-                      format.toString(), result.getAligfile() })));
+                  "exception.unknown_format_for_file", new String[] { "",
+                      result.getAligfile() })));
         }
       }
       else
index 08a242d..a8258e2 100644 (file)
@@ -23,6 +23,7 @@ package jalview.ws.rest.params;
 import jalview.datamodel.AlignmentI;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FormatAdapter;
 import jalview.ws.params.OptionI;
 import jalview.ws.params.simple.BooleanOption;
@@ -147,9 +148,9 @@ public class Alignment extends InputType
 
     if (tok.startsWith("format"))
     {
-      for (FileFormatI fmt : FileFormat.values())
+      for (FileFormatI fmt : FileFormats.getInstance().getFormats())
       {
-        if (fmt.isWritable() && val.equalsIgnoreCase(fmt.toString()))
+        if (fmt.isWritable() && val.equalsIgnoreCase(fmt.getName()))
         {
           format = fmt;
           return true;
@@ -157,12 +158,9 @@ public class Alignment extends InputType
       }
       warnings.append("Invalid alignment format '" + val
               + "'. Must be one of (");
-      for (FileFormatI fmt : FileFormat.values())
+      for (String fmt : FileFormats.getInstance().getWritableFormats(true))
       {
-        if (fmt.isWritable())
-        {
-          warnings.append(" " + fmt).toString();
-        }
+        warnings.append(" ").append(fmt);
       }
       warnings.append(")\n");
     }
@@ -197,28 +195,14 @@ public class Alignment extends InputType
             "Append jalview style /start-end suffix to ID", false, false,
             writeAsFile, null));
 
+    List<String> writable = FileFormats
+            .getInstance().getWritableFormats(true);
     lst.add(new Option("format", "Alignment upload format", true,
-            FileFormat.Fasta.toString(), format.toString(), getWritableFormats(),
+            FileFormat.Fasta.toString(), format.getName(), writable,
             null));
     lst.add(createMolTypeOption("type", "Sequence type", false, type, null));
 
     return lst;
   }
 
-  /**
-   * @return
-   */
-  protected List<String> getWritableFormats()
-  {
-    List<String> formats = new ArrayList<String>();
-    for (FileFormatI ff : FileFormat.values())
-    {
-      if (ff.isWritable())
-      {
-        formats.add(ff.toString());
-      }
-    }
-    return formats;
-  }
-
 }
index 37388d3..ea65125 100644 (file)
@@ -295,6 +295,7 @@ public class SiftsClient implements SiftsClientI
       siftsDownloadDir.mkdirs();
     }
     // System.out.println(">> Download ftp url : " + siftsFileFTPURL);
+    // long now = System.currentTimeMillis();
     URL url = new URL(siftsFileFTPURL);
     URLConnection conn = url.openConnection();
     InputStream inputStream = conn.getInputStream();
@@ -308,7 +309,8 @@ public class SiftsClient implements SiftsClientI
     }
     outputStream.close();
     inputStream.close();
-    // System.out.println(">>> File downloaded : " + downloadedSiftsFile);
+//    System.out.println(">>> File downloaded : " + downloadedSiftsFile
+//            + " took " + (System.currentTimeMillis() - now) + "ms");
     return new File(downloadedSiftsFile);
   }
 
@@ -51,9 +51,8 @@ import org.testng.annotations.BeforeClass;
  * @author gmcarstairs
  *
  */
-public class DnaAlignmentGenerator
+public class AlignmentGenerator
 {
-
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
   {
@@ -65,7 +64,11 @@ public class DnaAlignmentGenerator
 
   private static final char ZERO = '0';
 
-  private static final char[] BASES = new char[] { 'G', 'T', 'C', 'A' };
+  private static final char[] NUCS = "GTCA".toCharArray();
+
+  private static final char[] PEPS = "MILVFYWHKRDEQNTCGASNP".toCharArray();
+
+  private static char[] BASES;
 
   private Random random;
 
@@ -78,17 +81,19 @@ public class DnaAlignmentGenerator
    */
   public static void main(String[] args)
   {
-    if (args.length != 5)
+    if (args.length != 6)
     {
       usage();
       return;
     }
-    int width = Integer.parseInt(args[0]);
-    int height = Integer.parseInt(args[1]);
-    long randomSeed = Long.valueOf(args[2]);
-    int gapPercentage = Integer.valueOf(args[3]);
-    int changePercentage = Integer.valueOf(args[4]);
-    AlignmentI al = new DnaAlignmentGenerator().generate(width, height,
+    boolean nucleotide = args[0].toLowerCase().startsWith("n");
+    int width = Integer.parseInt(args[1]);
+    int height = Integer.parseInt(args[2]);
+    long randomSeed = Long.valueOf(args[3]);
+    int gapPercentage = Integer.valueOf(args[4]);
+    int changePercentage = Integer.valueOf(args[5]);
+    AlignmentI al = new AlignmentGenerator(nucleotide).generate(width,
+            height,
             randomSeed, gapPercentage, changePercentage);
 
     System.out.println("; " + height + " sequences of " + width
@@ -104,25 +109,26 @@ public class DnaAlignmentGenerator
   private static void usage()
   {
     System.out.println("Usage:");
-    System.out.println("arg0: number of (non-gap) bases per sequence");
-    System.out.println("arg1: number sequences");
+    System.out.println("arg0: n (for nucleotide) or p (for peptide)");
+    System.out.println("arg1: number of (non-gap) bases per sequence");
+    System.out.println("arg2: number sequences");
     System.out
-            .println("arg2: an integer as random seed (same seed = same results)");
-    System.out.println("arg3: percentage of gaps to (randomly) generate");
+            .println("arg3: an integer as random seed (same seed = same results)");
+    System.out.println("arg4: percentage of gaps to (randomly) generate");
     System.out
-            .println("arg4: percentage of 'mutations' to (randomly) generate");
-    System.out.println("Example: DnaAlignmentGenerator 12 15 387 10 5");
+            .println("arg5: percentage of 'mutations' to (randomly) generate");
+    System.out.println("Example: AlignmentGenerator n 12 15 387 10 5");
     System.out
-            .println("- 15 sequences of 12 bases each, approx 10% gaps and 5% mutations, random seed = 387");
+            .println("- 15 nucleotide sequences of 12 bases each, approx 10% gaps and 5% mutations, random seed = 387");
 
   }
 
   /**
-   * Default constructor
+   * Constructor that sets nucleotide or peptide symbol set
    */
-  public DnaAlignmentGenerator()
+  public AlignmentGenerator(boolean nuc)
   {
-
+    BASES = nuc ? NUCS : PEPS;
   }
 
   /**
@@ -168,7 +174,8 @@ public class DnaAlignmentGenerator
     for (int count = 0; count < length;)
     {
       boolean addGap = random.nextInt(100) < gapPercentage;
-      char c = addGap ? GAP : BASES[random.nextInt(Integer.MAX_VALUE) % 4];
+      char c = addGap ? GAP : BASES[random.nextInt(Integer.MAX_VALUE)
+              % BASES.length];
       seq.append(c);
       if (!addGap)
       {
@@ -277,7 +284,7 @@ public class DnaAlignmentGenerator
     char newchar = c;
     while (newchar == c)
     {
-      newchar = BASES[random.nextInt(Integer.MAX_VALUE) % 4];
+      newchar = BASES[random.nextInt(Integer.MAX_VALUE) % BASES.length];
     }
     return newchar;
   }
index cd5d3ca..2e21d9c 100644 (file)
@@ -294,7 +294,8 @@ public class DnaTest
     /*
      * Generate cDNA - 8 sequences of 12 bases each.
      */
-    AlignmentI cdna = new DnaAlignmentGenerator().generate(12, 8, 97, 5, 5);
+    AlignmentI cdna = new AlignmentGenerator(true)
+            .generate(12, 8, 97, 5, 5);
     ColumnSelection cs = new ColumnSelection();
     AlignViewportI av = new AlignViewport(cdna, cs);
     Dna dna = new Dna(av, new int[] { 0, cdna.getWidth() - 1 });
index d2f4b4d..618bac5 100644 (file)
@@ -1131,4 +1131,63 @@ public class AlignmentTest
     assertSame(pep.getDatasetSequence(), cds.getDBRefs()[0].map.to);
   }
 
+  @Test(groups = { "Functional" })
+  public void testFindGroup()
+  {
+    SequenceI seq1 = new Sequence("seq1", "ABCDEF---GHI");
+    SequenceI seq2 = new Sequence("seq2", "---JKLMNO---");
+    AlignmentI a = new Alignment(new SequenceI[] { seq1, seq2 });
+
+    assertNull(a.findGroup(null, 0));
+    assertNull(a.findGroup(seq1, 1));
+    assertNull(a.findGroup(seq1, -1));
+
+    /*
+     * add a group consisting of just "DEF"
+     */
+    SequenceGroup sg1 = new SequenceGroup();
+    sg1.addSequence(seq1, false);
+    sg1.setStartRes(3);
+    sg1.setEndRes(5);
+    a.addGroup(sg1);
+
+    assertNull(a.findGroup(seq1, 2)); // position not in group
+    assertNull(a.findGroup(seq1, 6)); // position not in group
+    assertNull(a.findGroup(seq2, 5)); // sequence not in group
+    assertSame(a.findGroup(seq1, 3), sg1); // yes
+    assertSame(a.findGroup(seq1, 4), sg1);
+    assertSame(a.findGroup(seq1, 5), sg1);
+
+    /*
+     * add a group consisting of 
+     * EF--
+     * KLMN
+     */
+    SequenceGroup sg2 = new SequenceGroup();
+    sg2.addSequence(seq1, false);
+    sg2.addSequence(seq2, false);
+    sg2.setStartRes(4);
+    sg2.setEndRes(7);
+    a.addGroup(sg2);
+
+    assertNull(a.findGroup(seq1, 2)); // unchanged
+    assertSame(a.findGroup(seq1, 3), sg1); // unchanged
+    /*
+     * if a residue is in more than one group, method returns
+     * the first found (in order groups were added)
+     */
+    assertSame(a.findGroup(seq1, 4), sg1);
+    assertSame(a.findGroup(seq1, 5), sg1);
+
+    /*
+     * seq2 only belongs to the second group
+     */
+    assertSame(a.findGroup(seq2, 4), sg2);
+    assertSame(a.findGroup(seq2, 5), sg2);
+    assertSame(a.findGroup(seq2, 6), sg2);
+    assertSame(a.findGroup(seq2, 7), sg2);
+    assertNull(a.findGroup(seq2, 3));
+    assertNull(a.findGroup(seq2, 8));
+  }
+
 }
index a9ad4c2..4faa482 100644 (file)
@@ -205,12 +205,11 @@ public class ColumnSelectionTest
     assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
 
     // hiding column 4 expands [3, 3] to [3, 4]
-    // not fancy enough to coalesce this into [3, 5] though
+    // and merges to [5, 5] to make [3, 5]
     cs.hideColumns(4);
     hidden = cs.getHiddenColumns();
-    assertEquals(2, hidden.size());
-    assertEquals("[3, 4]", Arrays.toString(hidden.get(0)));
-    assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
+    assertEquals(1, hidden.size());
+    assertEquals("[3, 5]", Arrays.toString(hidden.get(0)));
 
     // clear hidden columns (note they are added to selected)
     cs.revealAllHiddenColumns();
@@ -761,4 +760,59 @@ public class ColumnSelectionTest
     assertEquals("[5, 7]", Arrays.toString(cs2.getHiddenColumns().get(0)));
     assertEquals("[10, 11]", Arrays.toString(cs2.getHiddenColumns().get(1)));
   }
+
+  /**
+   * Test for the case when a hidden range encloses more one already hidden
+   * range
+   */
+  @Test(groups = { "Functional" })
+  public void testHideColumns_subsumingHidden()
+  {
+    /*
+     * JAL-2370 bug scenario:
+     * two hidden ranges subsumed by a third
+     */
+    ColumnSelection cs = new ColumnSelection();
+    cs.hideColumns(49, 59);
+    cs.hideColumns(69, 79);
+    List<int[]> hidden = cs.getHiddenColumns();
+    assertEquals(2, hidden.size());
+    assertEquals("[49, 59]", Arrays.toString(hidden.get(0)));
+    assertEquals("[69, 79]", Arrays.toString(hidden.get(1)));
+  
+    cs.hideColumns(48, 80);
+    hidden = cs.getHiddenColumns();
+    assertEquals(1, hidden.size());
+    assertEquals("[48, 80]", Arrays.toString(hidden.get(0)));
+
+    /*
+     * another...joining hidden ranges
+     */
+    cs = new ColumnSelection();
+    cs.hideColumns(10, 20);
+    cs.hideColumns(30, 40);
+    cs.hideColumns(50, 60);
+    // hiding 21-49 should merge to one range
+    cs.hideColumns(21, 49);
+    hidden = cs.getHiddenColumns();
+    assertEquals(1, hidden.size());
+    assertEquals("[10, 60]", Arrays.toString(hidden.get(0)));
+
+    /*
+     * another...lef overlap, subsumption, right overlap,
+     * no overlap of existing hidden ranges
+     */
+    cs = new ColumnSelection();
+    cs.hideColumns(10, 20);
+    cs.hideColumns(10, 20);
+    cs.hideColumns(30, 35);
+    cs.hideColumns(40, 50);
+    cs.hideColumns(60, 70);
+
+    cs.hideColumns(15, 45);
+    hidden = cs.getHiddenColumns();
+    assertEquals(2, hidden.size());
+    assertEquals("[10, 50]", Arrays.toString(hidden.get(0)));
+    assertEquals("[60, 70]", Arrays.toString(hidden.get(1)));
+  }
 }
diff --git a/test/jalview/io/FileFormatsTest.java b/test/jalview/io/FileFormatsTest.java
new file mode 100644 (file)
index 0000000..8df228f
--- /dev/null
@@ -0,0 +1,156 @@
+package jalview.io;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+public class FileFormatsTest
+{
+  @AfterMethod()
+  public void tearDown()
+  {
+    FileFormats.getInstance().reset();
+  }
+
+  @Test(groups = "Functional")
+  public void testIsDynamic()
+  {
+    FileFormats formats = FileFormats.getInstance();
+    for (FileFormatI ff : FileFormat.values())
+    {
+      assertFalse(formats.isIdentifiable(ff));
+    }
+    assertTrue(formats.isIdentifiable(null));
+
+    /*
+     * remove and re-add a format: it is now considered 'dynamically added'
+     */
+    formats.deregisterFileFormat(FileFormat.Fasta.getName());
+    assertNull(formats.forName(FileFormat.Fasta.getName()));
+    formats.registerFileFormat(FileFormat.Fasta);
+    assertSame(FileFormat.Fasta,
+            formats.forName(FileFormat.Fasta.getName()));
+    assertTrue(formats.isIdentifiable(FileFormat.Fasta));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetReadableFormats()
+  {
+    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    FileFormats formats = FileFormats.getInstance();
+    assertEquals(formats.getReadableFormats().toString(), expected);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetWritableFormats()
+  {
+    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
+    FileFormats formats = FileFormats.getInstance();
+    assertEquals(formats.getWritableFormats(true).toString(), expected);
+    expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, Jalview]";
+    assertEquals(formats.getWritableFormats(false).toString(), expected);
+  }
+
+  @Test(groups = "Functional")
+  public void testDeregisterFileFormat()
+  {
+    String writable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
+    String readable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    FileFormats formats = FileFormats.getInstance();
+    assertEquals(formats.getWritableFormats(true).toString(), writable);
+    assertEquals(formats.getReadableFormats().toString(), readable);
+
+    formats.deregisterFileFormat(FileFormat.Fasta.getName());
+    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
+    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    assertEquals(formats.getWritableFormats(true).toString(), writable);
+    assertEquals(formats.getReadableFormats().toString(), readable);
+
+    /*
+     * re-register the format: it gets added to the end of the list
+     */
+    formats.registerFileFormat(FileFormat.Fasta);
+    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, Fasta]";
+    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview, Fasta]";
+    assertEquals(formats.getWritableFormats(true).toString(), writable);
+    assertEquals(formats.getReadableFormats().toString(), readable);
+  }
+
+  @Test(groups = "Functional")
+  public void testForName()
+  {
+    FileFormats formats = FileFormats.getInstance();
+    for (FileFormatI ff : FileFormat.values())
+    {
+      assertSame(ff, formats.forName(ff.getName()));
+      assertSame(ff, formats.forName(ff.getName().toUpperCase()));
+      assertSame(ff, formats.forName(ff.getName().toLowerCase()));
+    }
+    assertNull(formats.forName(null));
+    assertNull(formats.forName("rubbish"));
+  }
+
+  @Test(groups = "Functional")
+  public void testRegisterFileFormat()
+  {
+    FileFormats formats = FileFormats.getInstance();
+    assertSame(FileFormat.MMCif,
+            formats.forName(FileFormat.MMCif.getName()));
+    assertFalse(formats.isIdentifiable(FileFormat.MMCif));
+
+    /*
+     * deregister mmCIF format
+     */
+    formats.deregisterFileFormat(FileFormat.MMCif.getName());
+    assertNull(formats.forName(FileFormat.MMCif.getName()));
+
+    /*
+     * re-register mmCIF format
+     * it is reinstated (but now classed as 'dynamic')
+     */
+    formats.registerFileFormat(FileFormat.MMCif);
+    assertSame(FileFormat.MMCif,
+            formats.forName(FileFormat.MMCif.getName()));
+    assertTrue(formats.isIdentifiable(FileFormat.MMCif));
+    // repeating does nothing
+    formats.registerFileFormat(FileFormat.MMCif);
+    assertSame(FileFormat.MMCif,
+            formats.forName(FileFormat.MMCif.getName()));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFormats()
+  {
+    /*
+     * verify the list of file formats registered matches the enum values
+     */
+    FileFormats instance = FileFormats.getInstance();
+    Iterator<FileFormatI> formats = instance.getFormats()
+            .iterator();
+    FileFormatI[] builtIn = FileFormat.values();
+
+    for (FileFormatI ff : builtIn)
+    {
+      assertSame(ff, formats.next());
+    }
+    assertFalse(formats.hasNext());
+
+    /*
+     * remove the first format, check it is no longer in 
+     * the list of formats
+     */
+    String firstFormatName = instance.getFormats().iterator().next()
+            .getName();
+    instance.deregisterFileFormat(firstFormatName);
+    assertNotEquals(instance.getFormats().iterator().next().getName(),
+            firstFormatName);
+  }
+}
index 7aa5769..b500266 100644 (file)
@@ -132,7 +132,7 @@ public class FormatAdapterTest
   static Object[][] getFormats()
   {
     List<FileFormatI> both = new ArrayList<FileFormatI>();
-    for (FileFormat format : FileFormat.values())
+    for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isReadable() && format.isWritable()
               && format.isTextFormat())
diff --git a/test/jalview/math/MatrixTest.java b/test/jalview/math/MatrixTest.java
new file mode 100644 (file)
index 0000000..795b2fa
--- /dev/null
@@ -0,0 +1,239 @@
+package jalview.math;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+
+public class MatrixTest
+{
+  @Test(groups = "Timing")
+  public void testPreMultiply_timing()
+  {
+    int rows = 500;
+    int cols = 1000;
+    double[][] d1 = new double[rows][cols];
+    double[][] d2 = new double[cols][rows];
+    Matrix m1 = new Matrix(d1, rows, cols);
+    Matrix m2 = new Matrix(d2, cols, rows);
+    long start = System.currentTimeMillis();
+    m1.preMultiply(m2);
+    long elapsed = System.currentTimeMillis() - start;
+    System.out.println(rows + "x" + cols
+            + " multiplications of double took " + elapsed + "ms");
+  }
+
+  @Test(groups = "Functional")
+  public void testPreMultiply()
+  {
+    Matrix m1 = new Matrix(new double[][] { { 2, 3, 4 } }, 1, 3); // 1x3
+    Matrix m2 = new Matrix(new double[][] { { 5 }, { 6 }, { 7 } }, 3, 1); // 3x1
+
+    /*
+     * 1x3 times 3x1 is 1x1
+     * 2x5 + 3x6 + 4*7 =  56
+     */
+    Matrix m3 = m2.preMultiply(m1);
+    assertEquals(m3.rows, 1);
+    assertEquals(m3.cols, 1);
+    assertEquals(m3.value[0][0], 56d);
+
+    /*
+     * 3x1 times 1x3 is 3x3
+     */
+    m3 = m1.preMultiply(m2);
+    assertEquals(m3.rows, 3);
+    assertEquals(m3.cols, 3);
+    assertEquals(Arrays.toString(m3.value[0]), "[10.0, 15.0, 20.0]");
+    assertEquals(Arrays.toString(m3.value[1]), "[12.0, 18.0, 24.0]");
+    assertEquals(Arrays.toString(m3.value[2]), "[14.0, 21.0, 28.0]");
+  }
+
+  @Test(
+    groups = "Functional",
+    expectedExceptions = { IllegalArgumentException.class })
+  public void testPreMultiply_tooManyColumns()
+  {
+    Matrix m1 = new Matrix(new double[][] { { 2, 3, 4 }, { 3, 4, 5 } }, 2,
+            3); // 2x3
+
+    /*
+     * 2x3 times 2x3 invalid operation - 
+     * multiplier has more columns than multiplicand has rows
+     */
+    m1.preMultiply(m1);
+    fail("Expected exception");
+  }
+
+  @Test(
+    groups = "Functional",
+    expectedExceptions = { IllegalArgumentException.class })
+  public void testPreMultiply_tooFewColumns()
+  {
+    Matrix m1 = new Matrix(new double[][] { { 2, 3, 4 }, { 3, 4, 5 } }, 2,
+            3); // 2x3
+
+    /*
+     * 3x2 times 3x2 invalid operation - 
+     * multiplier has more columns than multiplicand has row
+     */
+    m1.preMultiply(m1);
+    fail("Expected exception");
+  }
+  
+  
+  private boolean matrixEquals(Matrix m1, Matrix m2) {
+    return Arrays.deepEquals(m1.value, m2.value);
+  }
+
+  @Test(groups = "Functional")
+  public void testPostMultiply()
+  {
+    /*
+     * Square matrices
+     * (2 3) . (10   100)
+     * (4 5)   (1000 10000)
+     * =
+     * (3020 30200)
+     * (5040 50400)
+     */
+    Matrix m1 = new Matrix(new double[][] { { 2, 3 }, { 4, 5 } }, 2, 2);
+    Matrix m2 = new Matrix(new double[][] { { 10, 100 }, { 1000, 10000 } },
+            2, 2);
+    Matrix m3 = m1.postMultiply(m2);
+    assertEquals(Arrays.toString(m3.value[0]), "[3020.0, 30200.0]");
+    assertEquals(Arrays.toString(m3.value[1]), "[5040.0, 50400.0]");
+
+    /*
+     * also check m2.preMultiply(m1) - should be same as m1.postMultiply(m2) 
+     */
+    m3 = m2.preMultiply(m1);
+    assertEquals(Arrays.toString(m3.value[0]), "[3020.0, 30200.0]");
+    assertEquals(Arrays.toString(m3.value[1]), "[5040.0, 50400.0]");
+
+    /*
+     * m1 has more rows than columns
+     * (2).(10 100 1000) = (20 200 2000)
+     * (3)                 (30 300 3000)
+     */
+    m1 = new Matrix(new double[][] { { 2 }, { 3 } }, 2, 1);
+    m2 = new Matrix(new double[][] { { 10, 100, 1000 } }, 1, 3);
+    m3 = m1.postMultiply(m2);
+    assertEquals(m3.rows, 2);
+    assertEquals(m3.cols, 3);
+    assertEquals(Arrays.toString(m3.value[0]), "[20.0, 200.0, 2000.0]");
+    assertEquals(Arrays.toString(m3.value[1]), "[30.0, 300.0, 3000.0]");
+    m3 = m2.preMultiply(m1);
+    assertEquals(m3.rows, 2);
+    assertEquals(m3.cols, 3);
+    assertEquals(Arrays.toString(m3.value[0]), "[20.0, 200.0, 2000.0]");
+    assertEquals(Arrays.toString(m3.value[1]), "[30.0, 300.0, 3000.0]");
+
+    /*
+     * m1 has more columns than rows
+     * (2 3 4) . (5 4) = (56 25)
+     *           (6 3) 
+     *           (7 2)
+     * [0, 0] = 2*5 + 3*6 + 4*7 = 56
+     * [0, 1] = 2*4 + 3*3 + 4*2 = 25  
+     */
+    m1 = new Matrix(new double[][] { { 2, 3, 4 } }, 1, 3);
+    m2 = new Matrix(new double[][] { { 5, 4 }, { 6, 3 }, { 7, 2 } }, 3, 2);
+    m3 = m1.postMultiply(m2);
+    assertEquals(m3.rows, 1);
+    assertEquals(m3.cols, 2);
+    assertEquals(m3.value[0][0], 56d);
+    assertEquals(m3.value[0][1], 25d);
+
+    /*
+     * and check premultiply equivalent
+     */
+    m3 = m2.preMultiply(m1);
+    assertEquals(m3.rows, 1);
+    assertEquals(m3.cols, 2);
+    assertEquals(m3.value[0][0], 56d);
+    assertEquals(m3.value[0][1], 25d);
+  }
+
+  /**
+   * main method extracted from Matrix
+   * 
+   * @param args
+   */
+  public static void main(String[] args) throws Exception
+  {
+    int n = Integer.parseInt(args[0]);
+    double[][] in = new double[n][n];
+  
+    for (int i = 0; i < n; i++)
+    {
+      for (int j = 0; j < n; j++)
+      {
+        in[i][j] = Math.random();
+      }
+    }
+  
+    Matrix origmat = new Matrix(in, n, n);
+  
+    // System.out.println(" --- Original matrix ---- ");
+    // / origmat.print(System.out);
+    // System.out.println();
+    // System.out.println(" --- transpose matrix ---- ");
+    Matrix trans = origmat.transpose();
+  
+    // trans.print(System.out);
+    // System.out.println();
+    // System.out.println(" --- OrigT * Orig ---- ");
+    Matrix symm = trans.postMultiply(origmat);
+  
+    // symm.print(System.out);
+    // System.out.println();
+    // Copy the symmetric matrix for later
+    // Matrix origsymm = symm.copy();
+  
+    // This produces the tridiagonal transformation matrix
+    // long tstart = System.currentTimeMillis();
+    symm.tred();
+  
+    // long tend = System.currentTimeMillis();
+  
+    // System.out.println("Time take for tred = " + (tend-tstart) + "ms");
+    // System.out.println(" ---Tridiag transform matrix ---");
+    // symm.print(System.out);
+    // System.out.println();
+    // System.out.println(" --- D vector ---");
+    // symm.printD(System.out);
+    // System.out.println();
+    // System.out.println(" --- E vector ---");
+    // symm.printE(System.out);
+    // System.out.println();
+    // Now produce the diagonalization matrix
+    // tstart = System.currentTimeMillis();
+    symm.tqli();
+    // tend = System.currentTimeMillis();
+  
+    // System.out.println("Time take for tqli = " + (tend-tstart) + " ms");
+    // System.out.println(" --- New diagonalization matrix ---");
+    // symm.print(System.out);
+    // System.out.println();
+    // System.out.println(" --- D vector ---");
+    // symm.printD(System.out);
+    // System.out.println();
+    // System.out.println(" --- E vector ---");
+    // symm.printE(System.out);
+    // System.out.println();
+    // System.out.println(" --- First eigenvector --- ");
+    // double[] eigenv = symm.getColumn(0);
+    // for (int i=0; i < eigenv.length;i++) {
+    // Format.print(System.out,"%15.4f",eigenv[i]);
+    // }
+    // System.out.println();
+    // double[] neigenv = origsymm.vectorPostMultiply(eigenv);
+    // for (int i=0; i < neigenv.length;i++) {
+    // Format.print(System.out,"%15.4f",neigenv[i]/symm.d[0]);
+    // }
+    // System.out.println();
+  }
+}
index 1404f0b..999e456 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.util;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
 import jalview.gui.JvOptionPane;
 
@@ -96,4 +97,69 @@ public class FormatTest
     assertEquals(Format.repeat('b', 0), "");
     assertEquals(Format.repeat('c', -1), "");
   }
+
+  @Test(groups = "Functional")
+  public void testFormat_scientific()
+  {
+    Format f = new Format("%3.4e");
+    double d = 1d;
+    assertEquals(f.form(d), "1.0000e+000");
+    assertEquals(String.format("%3.4e", d), "1.0000e+00");
+
+    d = 12345678.12345678d;
+    assertEquals(f.form(d), "1.2346e+007");
+    assertEquals(String.format("%3.4e", d), "1.2346e+07");
+  }
+
+  /**
+   * Test that fails (in 2.10.1) with timeout as there is an infinite loop in
+   * Format.exp_format()
+   */
+  @Test(groups = "Functional", timeOut = 500)
+  public void testFormat_scientific_overflow()
+  {
+    Format f = new Format("%3.4e");
+    double d = 1.12E-310;
+    /*
+     * problem: exp_format() scales up 'd' to the range 1-10
+     * while computing a scaling factor, but this factor acquires
+     * the value Double.POSITIVE_INFINITY instead of 1.0E+309
+     * the value to be formatted is multipled by factor and becomes Infinity
+     * resulting in an infinite loop in the recursive call to exp_format()
+     */
+    assertEquals(f.form(d), "1.1200e-310");
+  }
+
+  /**
+   * This test shows that Format.form() is faster for this case than
+   * String.format()
+   */
+  @Test(groups = "Timing")
+  public void testFormat_scientificTiming()
+  {
+    Format f = new Format("%3.4e");
+    double d = 12345678.12345678d;
+
+    int iterations = 1000;
+    long start = System.currentTimeMillis();
+    for (int i = 0; i < iterations; i++)
+    {
+      f.form(d);
+    }
+    long stop = System.currentTimeMillis();
+    long elapsed1 = stop - start;
+    System.out.println(iterations + " x Format.form took " + elapsed1
+            + "ms");
+
+    start = System.currentTimeMillis();
+    for (int i = 0; i < iterations; i++)
+    {
+      String.format("%3.4e", d);
+    }
+    stop = System.currentTimeMillis();
+    long elapsed2 = stop - start;
+    System.out.println(iterations + " x String.format took " + elapsed2
+            + "ms");
+    assertTrue(elapsed2 > elapsed1);
+  }
 }
index 3573f50..2d317e4 100644 (file)
@@ -138,7 +138,7 @@ public class DisorderAnnotExportImport
   {
     try
     {
-      String aligfileout = FileFormat.Pfam.getAlignmentFile().print(
+      String aligfileout = FileFormat.Pfam.getWriter(al).print(
               al.getSequencesArray(), true);
       String anfileout = new AnnotationFile()
               .printAnnotationsForAlignment(al);
index b8fe0a3..d5b6ed1 100644 (file)
@@ -188,7 +188,7 @@ public class JpredJabaStructExportImport
     try
     {
       // what format would be appropriate for RNAalifold annotations?
-      String aligfileout = FileFormat.Pfam.getAlignmentFile().print(
+      String aligfileout = FileFormat.Pfam.getWriter(null).print(
               al.getSequencesArray(), true);
 
       String anfileout = new AnnotationFile()
index 06c803f..f1430f6 100644 (file)
@@ -201,7 +201,7 @@ public class RNAStructExportImport
     try
     {
       // what format would be appropriate for RNAalifold annotations?
-      String aligfileout = FileFormat.Pfam.getAlignmentFile().print(
+      String aligfileout = FileFormat.Pfam.getWriter(null).print(
               al.getSequencesArray(), true);
 
       String anfileout = new AnnotationFile()
index 45c5412..d805e47 100644 (file)
@@ -20,6 +20,9 @@
  */
 package jalview.ws.sifts;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
 import jalview.api.DBRefEntryI;
 import jalview.bin.Cache;
 import jalview.datamodel.DBRefEntry;
@@ -178,7 +181,7 @@ public class SiftsClientTest
   }
 
   @BeforeTest(alwaysRun = true)
-  public void setUpSiftsClient() throws SiftsException
+  public void setUpSiftsClient() throws SiftsException, IOException
   {
     // read test props before manipulating config
     Cache.loadProperties("test/jalview/io/testProps.jvprops");
@@ -191,15 +194,9 @@ public class SiftsClientTest
     SiftsSettings.setCacheThresholdInDays("2");
     SiftsSettings.setFailSafePIDThreshold("70");
     PDBfile pdbFile;
-    try
-    {
-      pdbFile = new PDBfile(false, false, false, "test/jalview/io/"
-              + testPDBId + ".pdb", DataSourceType.FILE);
-      siftsClient = new SiftsClient(pdbFile);
-    } catch (Exception e)
-    {
-      e.printStackTrace();
-    }
+    pdbFile = new PDBfile(false, false, false, "test/jalview/io/"
+            + testPDBId + ".pdb", DataSourceType.FILE);
+    siftsClient = new SiftsClient(pdbFile);
   }
 
   @AfterTest(alwaysRun = true)
@@ -208,44 +205,56 @@ public class SiftsClientTest
     siftsClient = null;
   }
 
-  @Test(groups = { "Functional" })
-  public void getSIFTsFileTest() throws SiftsException
+  @Test(groups = { "Network" })
+  public void getSIFTsFileTest() throws SiftsException, IOException
   {
     File siftsFile;
-    try
-    {
-      siftsFile = SiftsClient.downloadSiftsFile(testPDBId);
-      FileAssert.assertFile(siftsFile);
-      // test for SIFTs file caching
-      SiftsSettings.setCacheThresholdInDays("0");
-      siftsFile = SiftsClient.getSiftsFile(testPDBId);
-      FileAssert.assertFile(siftsFile);
-      SiftsSettings.setCacheThresholdInDays("2");
-    } catch (IOException e)
+    siftsFile = SiftsClient.downloadSiftsFile(testPDBId);
+    FileAssert.assertFile(siftsFile);
+    long t1 = siftsFile.lastModified();
+
+    // re-read file should be returned from cache
+    siftsFile = SiftsClient.downloadSiftsFile(testPDBId);
+    FileAssert.assertFile(siftsFile);
+    long t2 = siftsFile.lastModified();
+    assertEquals(t1, t2);
+
+    /*
+     * force fetch by having 0 expiry of cache
+     * also wait one second, because file timestamp does not
+     * give millisecond resolution :-(
+     */
+    synchronized (this)
     {
-      e.printStackTrace();
+      try
+      {
+        wait(1000);
+      } catch (InterruptedException e)
+      {
+      }
     }
+    SiftsSettings.setCacheThresholdInDays("0");
+    siftsFile = SiftsClient.getSiftsFile(testPDBId);
+    FileAssert.assertFile(siftsFile);
+    long t3 = siftsFile.lastModified();
+    assertTrue(t3 > t2, "file timestamp unchanged at " + t3);
+
+    SiftsSettings.setCacheThresholdInDays("2");
   }
 
-  @Test(groups = { "Functional" })
-  public void downloadSiftsFileTest() throws SiftsException
+  @Test(groups = { "Network" })
+  public void downloadSiftsFileTest() throws SiftsException, IOException
   {
     // Assert that file isn't yet downloaded - if already downloaded, assert it
     // is deleted
     Assert.assertTrue(SiftsClient.deleteSiftsFileByPDBId(testPDBId));
     File siftsFile;
-    try
-    {
-      siftsFile = SiftsClient.downloadSiftsFile(testPDBId);
-      FileAssert.assertFile(siftsFile);
-      SiftsClient.downloadSiftsFile(testPDBId);
-    } catch (IOException e)
-    {
-      e.printStackTrace();
-    }
+    siftsFile = SiftsClient.downloadSiftsFile(testPDBId);
+    FileAssert.assertFile(siftsFile);
+    SiftsClient.downloadSiftsFile(testPDBId);
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void getAllMappingAccessionTest()
   {
     Assert.assertNotNull(siftsClient);
@@ -253,7 +262,7 @@ public class SiftsClientTest
     Assert.assertTrue(siftsClient.getAllMappingAccession().size() > 1);
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void getGreedyMappingTest()
   {
     Assert.assertNotNull(siftsClient);
@@ -279,7 +288,7 @@ public class SiftsClientTest
     }
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   private void getAtomIndexTest()
   {
     ArrayList<Atom> atoms = new ArrayList<Atom>();
@@ -294,21 +303,21 @@ public class SiftsClientTest
   }
 
   @Test(
-    groups = { "Functional" },
+    groups = { "Network" },
     expectedExceptions = IllegalArgumentException.class)
   private void getAtomIndexNullTest()
   {
     siftsClient.getAtomIndex(1, null);
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   private void padWithGapsTest()
   {
 
   }
 
   @Test(
-    groups = { "Functional" },
+groups = { "Network" },
     expectedExceptions = SiftsException.class)
   private void populateAtomPositionsNullTest1()
           throws IllegalArgumentException, SiftsException
@@ -317,7 +326,7 @@ public class SiftsClientTest
   }
 
   @Test(
-    groups = { "Functional" },
+groups = { "Network" },
     expectedExceptions = SiftsException.class)
   private void populateAtomPositionsNullTest2()
           throws IllegalArgumentException, SiftsException
@@ -325,40 +334,29 @@ public class SiftsClientTest
     siftsClient.populateAtomPositions("A", null);
   }
 
-  @Test(groups = { "Functional" })
-  public void getValidSourceDBRefTest()
+  @Test(groups = { "Network" })
+  public void getValidSourceDBRefTest() throws SiftsException
   {
-    try
-    {
-      DBRefEntryI actualValidSrcDBRef = siftsClient
-              .getValidSourceDBRef(testSeq);
-      DBRefEntryI expectedDBRef = new DBRefEntry();
-      expectedDBRef.setSource(DBRefSource.UNIPROT);
-      expectedDBRef.setAccessionId("P00221");
-      expectedDBRef.setVersion("");
-      Assert.assertEquals(actualValidSrcDBRef, expectedDBRef);
-    } catch (Exception e)
-    {
-    }
+    DBRefEntryI actualValidSrcDBRef = siftsClient
+            .getValidSourceDBRef(testSeq);
+    DBRefEntryI expectedDBRef = new DBRefEntry();
+    expectedDBRef.setSource(DBRefSource.UNIPROT);
+    expectedDBRef.setAccessionId("P00221");
+    expectedDBRef.setVersion("");
+    Assert.assertEquals(actualValidSrcDBRef, expectedDBRef);
   }
 
   @Test(
-    groups = { "Functional" },
+groups = { "Network" },
     expectedExceptions = SiftsException.class)
   public void getValidSourceDBRefExceptionTest() throws SiftsException
   {
     SequenceI invalidTestSeq = new Sequence("testSeq", "ABCDEFGH");
-    try
-    {
-      siftsClient.getValidSourceDBRef(invalidTestSeq);
-    } catch (SiftsException e)
-    {
-      throw new SiftsException(e.getMessage());
-    }
+    siftsClient.getValidSourceDBRef(invalidTestSeq);
   }
 
   @Test(
-    groups = { "Functional" },
+groups = { "Network" },
     expectedExceptions = SiftsException.class)
   public void getValidSourceDBRefExceptionXTest() throws SiftsException
   {
@@ -366,17 +364,10 @@ public class SiftsClientTest
     DBRefEntry invalidDBRef = new DBRefEntry();
     invalidDBRef.setAccessionId("BLAR");
     invalidTestSeq.addDBRef(invalidDBRef);
-    try
-    {
-      siftsClient.getValidSourceDBRef(invalidTestSeq);
-    } catch (SiftsException e)
-    {
-      throw new SiftsException(e.getMessage());
-    }
-
+    siftsClient.getValidSourceDBRef(invalidTestSeq);
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void isValidDBRefEntryTest()
   {
     DBRefEntryI validDBRef = new DBRefEntry();
@@ -386,38 +377,32 @@ public class SiftsClientTest
     Assert.assertTrue(siftsClient.isValidDBRefEntry(validDBRef));
   }
 
-  @Test(groups = { "Functional" })
-  public void getSiftsStructureMappingTest()
+  @Test(groups = { "Network" })
+  public void getSiftsStructureMappingTest() throws SiftsException
   {
-    try
-    {
-      Assert.assertTrue(SiftsSettings.isMapWithSifts());
-      StructureMapping strucMapping = siftsClient.getSiftsStructureMapping(
-              testSeq, testPDBId, "A");
-      String expectedMappingOutput = "\nSequence ⟷ Structure mapping details\n"
-              + "Method: SIFTS\n\n"
-              + "P00221 :  51 - 147 Maps to \n"
-              + "1A70|A :  1 - 97\n\n"
-              + "P00221 AAYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDDQSFLD\n"
-              + "       |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n"
-              + "1A70|A AAYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDDQSFLD\n\n"
-
-              + "P00221 DDQIDEGWVLTCAAYPVSDVTIETHKEEELTA\n"
-              + "       |||||||||||||||||||||||||| |||||\n"
-              + "1A70|A DDQIDEGWVLTCAAYPVSDVTIETHKKEELTA\n\n" +
-
-              "Length of alignment = 97\n" + "Percentage ID = 98.97\n";
-
-      Assert.assertEquals(strucMapping.getMappingDetailsOutput(),
-              expectedMappingOutput);
-      Assert.assertEquals(strucMapping.getMapping(), expectedMapping);
-    } catch (SiftsException e)
-    {
-      e.printStackTrace();
-    }
+    Assert.assertTrue(SiftsSettings.isMapWithSifts());
+    StructureMapping strucMapping = siftsClient.getSiftsStructureMapping(
+            testSeq, testPDBId, "A");
+    String expectedMappingOutput = "\nSequence ⟷ Structure mapping details\n"
+            + "Method: SIFTS\n\n"
+            + "P00221 :  51 - 147 Maps to \n"
+            + "1A70|A :  1 - 97\n\n"
+            + "P00221 AAYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDDQSFLD\n"
+            + "       |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n"
+            + "1A70|A AAYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDDQSFLD\n\n"
+
+            + "P00221 DDQIDEGWVLTCAAYPVSDVTIETHKEEELTA\n"
+            + "       |||||||||||||||||||||||||| |||||\n"
+            + "1A70|A DDQIDEGWVLTCAAYPVSDVTIETHKKEELTA\n\n" +
+
+            "Length of alignment = 97\n" + "Percentage ID = 98.97\n";
+
+    Assert.assertEquals(strucMapping.getMappingDetailsOutput(),
+            expectedMappingOutput);
+    Assert.assertEquals(strucMapping.getMapping(), expectedMapping);
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void getEntityCountTest()
   {
     int actualEntityCount = siftsClient.getEntityCount();
@@ -425,7 +410,7 @@ public class SiftsClientTest
     Assert.assertEquals(actualEntityCount, 1);
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void getDbAccessionIdTest()
   {
     String actualDbAccId = siftsClient.getDbAccessionId();
@@ -433,7 +418,7 @@ public class SiftsClientTest
     Assert.assertEquals(actualDbAccId, "1a70");
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void getDbCoordSysTest()
   {
     String actualDbCoordSys = siftsClient.getDbCoordSys();
@@ -441,7 +426,7 @@ public class SiftsClientTest
     Assert.assertEquals(actualDbCoordSys, "PDBe");
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void getDbSourceTest()
   {
     String actualDbSource = siftsClient.getDbSource();
@@ -449,7 +434,7 @@ public class SiftsClientTest
     Assert.assertEquals(actualDbSource, "PDBe");
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Network" })
   public void getDbVersionTest()
   {
     String actualDbVersion = siftsClient.getDbVersion();
@@ -457,20 +442,15 @@ public class SiftsClientTest
     Assert.assertEquals(actualDbVersion, "2.0");
   }
 
-  @Test(groups = { "Functional" })
-  public void getEntityByMostOptimalMatchedIdTest1()
+  @Test(groups = { "Network" })
+  public void getEntityByMostOptimalMatchedIdTest1() throws IOException,
+          SiftsException
   {
     SiftsClient siftsClientX = null;
     PDBfile pdbFile;
-    try
-    {
-      pdbFile = new PDBfile(false, false, false, "test/jalview/io/2nq2"
-              + ".pdb", DataSourceType.FILE);
-      siftsClientX = new SiftsClient(pdbFile);
-    } catch (Exception e)
-    {
-      e.printStackTrace();
-    }
+    pdbFile = new PDBfile(false, false, false, "test/jalview/io/2nq2"
+            + ".pdb", DataSourceType.FILE);
+    siftsClientX = new SiftsClient(pdbFile);
     Entity entityA = siftsClientX.getEntityByMostOptimalMatchedId("A");
     Assert.assertEquals(entityA.getEntityId(), "A");
     Entity entityB = siftsClientX.getEntityByMostOptimalMatchedId("B");
@@ -482,23 +462,18 @@ public class SiftsClientTest
 
   }
 
-  @Test(groups = { "Functional" })
-  public void getEntityByMostOptimalMatchedIdTest2()
+  @Test(groups = { "Network" })
+  public void getEntityByMostOptimalMatchedIdTest2() throws IOException,
+          SiftsException
   {
     // This test is for a SIFTS file in which entity A should map to chain P for
     // the given PDB Id. All the other chains shouldn't be mapped as there are
     // no SIFTS entity records for them.
     SiftsClient siftsClientX = null;
     PDBfile pdbFile;
-    try
-    {
-      pdbFile = new PDBfile(false, false, false,
-              "test/jalview/io/3ucu.cif", DataSourceType.FILE);
-      siftsClientX = new SiftsClient(pdbFile);
-    } catch (Exception e)
-    {
-      e.printStackTrace();
-    }
+    pdbFile = new PDBfile(false, false, false, "test/jalview/io/3ucu.cif",
+            DataSourceType.FILE);
+    siftsClientX = new SiftsClient(pdbFile);
     Entity entityA = siftsClientX.getEntityByMostOptimalMatchedId("P");
     Entity entityP = siftsClientX.getEntityByMostOptimalMatchedId("A");
     Entity entityR = siftsClientX.getEntityByMostOptimalMatchedId("R");