JAL-2629 update spikes/mungo to latest
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 20 Apr 2018 21:01:08 +0000 (22:01 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 20 Apr 2018 21:01:08 +0000 (22:01 +0100)
53 files changed:
.ant-targets-build.xml
.classpath
benchmarking/src/main/java/org/jalview/HiddenColsIteratorsBenchmark.java [new file with mode: 0644]
benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java [new file with mode: 0644]
build.xml
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/analysis/SeqsetUtils.java
src/jalview/appletgui/OverviewCanvas.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/HiddenMarkovModel.java
src/jalview/datamodel/Sequence.java
src/jalview/datamodel/SequenceCollectionI.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/datamodel/SequenceI.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AquaInternalFrameManager.java
src/jalview/gui/JvSwingUtils.java
src/jalview/gui/OptsAndParamsPage.java
src/jalview/gui/OverviewCanvas.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/gui/WsJobParameters.java
src/jalview/hmmer/HMMAlign.java
src/jalview/hmmer/HMMBuild.java
src/jalview/hmmer/HMMERParamStore.java
src/jalview/hmmer/HMMSearch.java
src/jalview/hmmer/HmmerCommand.java
src/jalview/io/FileLoader.java
src/jalview/jbgui/GPreferences.java
src/jalview/jbgui/GRestInputParamEditDialog.java
src/jalview/jbgui/GRestServiceEditorPane.java
src/jalview/renderer/OverviewRenderer.java
src/jalview/schemes/HmmerColourScheme.java
src/jalview/schemes/HmmerGlobalBackground.java
src/jalview/schemes/HmmerLocalBackground.java
src/jalview/util/FileUtils.java [new file with mode: 0644]
src/jalview/util/Platform.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/workers/InformationThread.java
src/jalview/ws/jws2/Jws2Client.java
src/jalview/ws/params/simple/BooleanOption.java
src/jalview/ws/params/simple/DoubleParameter.java
src/jalview/ws/params/simple/IntegerParameter.java
src/jalview/ws/params/simple/LogarithmicParameter.java
src/jalview/ws/params/simple/Option.java
test/jalview/hmmer/HMMERTest.java
test/jalview/renderer/OverviewRendererTest.java [new file with mode: 0644]
test/jalview/renderer/seqfeatures/FeatureRendererTest.java
test/jalview/schemes/HmmerGlobalBackgroundTest.java
test/jalview/schemes/HmmerLocalBackgroundTest.java
test/jalview/ws/gui/Jws2ParamView.java
utils/i18nAnt.xml

index 15432a1..7ef21f1 100644 (file)
@@ -1,31 +1,2 @@
-build
-buildPropertiesFile
-buildTests
-buildextclients
-buildindices
-castorbinding
-clean
-compileApplet
-distclean
 help
-init
-linkcheck
-makeApplet
-makedist
-makefulldist
-obfuscate
-packageApplet
-prepare
-prepareTests
-preparejnlp
-prepubapplet_1
-pubapplet
-runenv
-signApplet
-sourcedist
-sourcedoc
-sourcescrub
-testclean
-testng
 usage
-writejnlpf
index 896611c..f4b8cf8 100644 (file)
@@ -66,9 +66,8 @@
        <classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
        <classpathentry kind="lib" path="lib/biojava-core-4.1.0.jar"/>
        <classpathentry kind="lib" path="lib/biojava-ontology-4.1.0.jar"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
        <classpathentry kind="lib" path="lib/htsjdk-2.12.0.jar"/>
        <classpathentry kind="lib" path="lib/groovy-all-2.4.12-indy.jar"/>
-       <classpathentry exported="true" kind="con" path="GROOVY_DSL_SUPPORT"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
        <classpathentry kind="output" path="classes"/>
 </classpath>
diff --git a/benchmarking/src/main/java/org/jalview/HiddenColsIteratorsBenchmark.java b/benchmarking/src/main/java/org/jalview/HiddenColsIteratorsBenchmark.java
new file mode 100644 (file)
index 0000000..477bfad
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+
+package org.jalview;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Param;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+
+/*
+ * A class to benchmark hidden columns performance
+ */
+@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
+public class HiddenColsIteratorsBenchmark {
+       /*
+        * State with multiple hidden columns and a start position set
+        */
+       @State(Scope.Thread)
+       public static class HiddenColsAndStartState
+       {
+               @Param({"300", "10000", "100000"})
+               public int maxcols;
+               
+               @Param({"1", "50", "90"})
+               public int startpcnt; // position as percentage of maxcols
+               
+               @Param({"1","15","100"})
+               public int hide;
+               
+               HiddenColumns h = new HiddenColumns();
+               Random rand = new Random();
+               
+               public int hiddenColumn;
+               public int visibleColumn;
+       
+               @Setup
+               public void setup()
+               {
+                       rand.setSeed(1234);
+                       int lastcol = 0;
+               while (lastcol < maxcols)
+               {
+                       int count = rand.nextInt(100); 
+                       lastcol += count;
+                       h.hideColumns(lastcol, lastcol+hide);
+                       lastcol+=hide;
+               }
+               
+               // make sure column at start is hidden
+               hiddenColumn = (int)(maxcols * startpcnt/100.0);
+               h.hideColumns(hiddenColumn, hiddenColumn);
+               
+               // and column <hide> after start is visible
+               ColumnSelection sel = new ColumnSelection();
+               h.revealHiddenColumns(hiddenColumn+hide, sel);
+               visibleColumn = hiddenColumn+hide;
+               
+               System.out.println("Maxcols: " + maxcols + " HiddenCol: " + hiddenColumn + " Hide: " + hide);
+               System.out.println("Number of hidden columns: " + h.getSize());
+               }
+       }
+       
+       /* Convention: functions in alphabetical order */
+       
+       @Benchmark
+       @BenchmarkMode({Mode.Throughput})
+       public int benchStartIterator(HiddenColsAndStartState tstate)
+       {
+               int res = 0;
+               int startx = tstate.visibleColumn;
+               Iterator<Integer> it = tstate.h.getStartRegionIterator(startx,
+                               startx+60);
+        while (it.hasNext())
+        {
+          res = it.next() - startx;
+          Blackhole.consumeCPU(5);
+        }
+        return res;
+       }
+       
+       @Benchmark
+       @BenchmarkMode({Mode.Throughput})
+       public int benchBoundedIterator(HiddenColsAndStartState tstate)
+       {
+               int startx = tstate.visibleColumn;
+               int blockStart = startx;
+               int blockEnd;
+               int screenY = 0;
+               Iterator<int[]> it = tstate.h.getBoundedIterator(startx,
+                               startx+60);
+        while (it.hasNext())
+        {
+               int[] region = it.next();
+          
+               blockEnd = Math.min(region[0] - 1, blockStart + 60 - screenY);
+             
+               screenY += blockEnd - blockStart + 1;
+               blockStart = region[1] + 1;
+               
+               Blackhole.consumeCPU(5);
+        }
+        return blockStart;
+       }
+}
diff --git a/benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java b/benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java
new file mode 100644 (file)
index 0000000..a92d4f0
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+
+package org.jalview;
+
+import org.jalview.HiddenColumnsBenchmark.HiddenColsAndStartState;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Param;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+/*
+ * A class to benchmark hidden columns performance
+ */
+@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
+public class SeqWidthBenchmark {
+
+       /*
+        * State with multiple hidden columns and a start position set
+        */
+       @State(Scope.Thread)
+       public static class AlignmentState
+       {
+               @Param({"100", "1000", "10000", "100000"})
+               public int numSeqs;
+               
+               Random rand = new Random();
+               
+               AlignmentI al;
+               
+               @Setup
+               public void setup()
+               {
+                       rand.setSeed(1234);
+                       
+                       SequenceI[] seqs = new Sequence[numSeqs];
+                   for (int i = 0; i < numSeqs; i++)
+                   {
+                     int count = rand.nextInt(10000); 
+                     StringBuilder aas = new StringBuilder();
+                     for (int j=0; j<count; j++)
+                     {
+                        aas.append("a");
+                     }
+
+                     seqs[i] = new Sequence("Sequence" + i, aas.toString());
+                   }
+                       al = new Alignment(seqs);
+               }
+       }
+       
+       
+       @Benchmark
+       @BenchmarkMode({Mode.Throughput})
+       public int benchSeqGetWidth(AlignmentState tstate)
+       {
+               return tstate.al.getWidth();
+       }
+       
+}
index d636a42..3bacc1c 100755 (executable)
--- a/build.xml
+++ b/build.xml
@@ -38,7 +38,7 @@
     <echo message="testng - run jalview's tests via testNG. Default group is '${testng-groups}'" />
     <echo message="      you can specify particular test groups as a list via -Dtestng-groups=" />
     <echo message="See docs/building.html and the comments in build file for other targets." />
-    <echo message="note: compile and makeApplet require the property java118.home to be set to point to a java 1.1.8 jdk." />
+    <echo message="note: compile and makeApplet optionally compile/obfuscate applet against a different Java version by specifying -Djava118.home=PathtoJDK/lib which is the lib directory in the JDK install that contains rt.jar " />
     <echo message="Useful -D flags: -Ddonotobfuscate will prevent applet obfuscation" />
   </target>
 
     </path>
     <property name="source.dist.name" value="${basedir}/jalview-src.tar.gz" />
     <!-- The Location of the java 1.1.8 jdk -->
-    <!--<property name="java118.home" value="C:\Sun\jdk1.1.8" /> -->
     <property name="java118.home" value="${java.home}" />
-    <!-- <property name="applet.jre.tools" value="${java118.home}/lib/classes.zip" />
-               -->
     <!-- jre for 1.4 version -->
-    <property name="applet.jre.tools" value="${java.home}/lib/rt.jar" />
+    <property name="applet.jre.tools" value="${java118.home}/lib/rt.jar" />
 
     <!-- the classpath for building the 1.1 applet -->
     <path id="jalviewlite.deps">
       <fileset dir="${java118.home}">
-        <include name="lib/classes.zip" />
+        <include name="lib/rt.jar" />
       </fileset>
       <fileset dir="${java.home}/lib">
         <include name="plugin.jar" />
index 06c8b6b..609c6a8 100644 (file)
@@ -822,8 +822,8 @@ label.fetch_retrieve_from_all_sources = Retrieve from all {0} sources in {1}<br>
 label.feature_settings_click_drag = Drag up or down to change render order.<br/>Double click to select columns containing feature.
 label.transparency_tip = Adjust transparency to 'see through' feature colours.
 label.opt_and_params_further_details = see further details by right-clicking
-label.opt_and_params_show_brief_desc_image_link = <html>Click to show brief description<br><img src="{0}"/> Right click for further information.</html> 
-label.opt_and_params_show_brief_desc = <html>Click to show brief description<br></html>
+label.opt_and_params_show_brief_desc_image_link = Click to show brief description<br><img src="{0}"/> Right click for further information. 
+label.opt_and_params_show_brief_desc = Click to show brief description<br>
 label.adjusts_width_generated_eps_png = <html>Adjusts the width of the generated EPS or PNG file to ensure even the longest sequence ID or annotation label is displayed</html>
 label.manually_specify_width_left_column = <html>Manually specify the width of the left hand column where sequence IDs and annotation labels will be rendered in exported alignment figures. This setting will be ignored if 'Automatically set ID width' is set</html>
 label.job_created_when_checked = <html>When checked, a job is created for every sequence in the current selection.</html>
@@ -885,7 +885,6 @@ label.error_unsupported_owwner_user_colour_scheme = Unsupported owner for User C
 label.save_alignment_to_file = Save Alignment to file
 label.save_features_to_file = Save Features to File
 label.save_annotation_to_file = Save Annotation to File
-label.no_features_on_alignment = No features found on alignment
 label.save_pdb_file = Save PDB File
 label.save_text_to_file = Save Text to File
 label.save_state = Save State
@@ -964,7 +963,6 @@ label.groovy_support_failed = Jalview Groovy Support Failed
 label.couldnt_create_groovy_shell = Couldn't create the groovy Shell. Check the error log for the details of what went wrong.
 error.unsupported_version_calcIdparam = Unsupported Version for calcIdparam {0}
 error.implementation_error_cant_reorder_tree = Implementation Error: Can't reorder this tree. Not DefaultMutableTreeNode.
-error.invalid_value_for_option = Invalid value {0} for option {1}
 error.implementation_error_cannot_import_vamsas_doc = Implementation Error - cannot import existing vamsas document into an existing session, Yet!
 label.vamsas_doc_couldnt_be_opened_as_new_session = VAMSAS Document could not be opened as a new session - please choose another
 error.implementation_error_vamsas_operation_not_init = Impementation error! Vamsas Operations when client not initialised and connected
@@ -1374,35 +1372,28 @@ label.most_polymer_residues = Most Polymer Residues
 label.cached_structures = Cached Structures
 label.free_text_search = Free Text Search
 label.hmmalign = hmmalign
+label.use_hmm = HMM profile to use
 label.hmmbuild = hmmbuild
-label.hmmbuild_group = Build HMM from Selected Group
-label.group_hmmbuild = Build HMM from Group
 label.hmmsearch = hmmsearch
+label.installation = Installation
 label.hmmer_location = HMMER Binaries Installation Location
-warn.null_hmm = Please ensure the alignment contains a hidden Markov model.
+label.cygwin_location = Cygwin Binaries Installation Location (Windows)
+label.information_annotation = Information Annotation
 label.ignore_below_background_frequency = Ignore Below Background Frequency
 label.information_description = Information content, measured in bits
-warn.no_selected_hmm = Please select a hidden Markov model sequence.
-label.select_hmm = Select HMM
-warn.no_sequence_data = No sequence data found.
-warn.empty_grp_or_alignment = An empty group or alignment was found.
+warn.no_hmm = No Hidden Markov model found.\nRun hmmbuild or load an HMM file first.
 label.no_sequences_found = No matching sequences, or an error occurred.
 label.hmmer = HMMER
 label.trim_termini = Trim Non-Matching Termini
 label.trim_termini_desc = If true, non-matching regions on either end of the resulting alignment are removed.
-label.no_of_sequences = Sequences Returned
-label.freq_alignment = Use Alignment Background Frequencies
-label.freq_uniprot = Use Uniprot Background Frequencies
-label.hmmalign_label = hmmalign Options
-label.hmmsearch_label = hmmsearch Options
-label.hmmbuild_not_found = The hmmbuild binary was not found
-label.hmmalign_not_found = The hmmalign binary was not found
-label.hmmsearch_not_found = The hmmsearch binary was not found
-warn.hmm_command_failed = hmm command not found
+label.no_of_sequences = Number of sequences returned
+label.freq_alignment = Use alignment background frequencies
+label.freq_uniprot = Use Uniprot background frequencies
+label.hmmalign_options = hmmalign options
+label.hmmsearch_options = hmmsearch options
+label.executable_not_found = The ''{0}'' executable file was not found
+warn.command_failed = {0} failed
 label.invalid_folder = Invalid Folder
-label.folder_not_exists = HMMER binaries not found. \n Please enter the path to the HMMER binaries (if installed).
-label.hmmer_installed = HMMER installed
-label.hmmer_no_sequences_found = No sequences found
 label.number_of_results = Number of Results to Return
 label.auto_align_seqs = Automatically Align Fetched Sequences
 label.use_accessions = Return Accessions
@@ -1410,26 +1401,24 @@ label.seq_e_value = Sequence E-value Cutoff
 label.seq_score = Sequence Score Threshold
 label.dom_e_value = Domain E-value Cutoff
 label.dom_score = Domain Score Threshold
-label.number_of_results_desc = The maximum number of results that hmmsearch will return
+label.number_of_results_desc = The maximum number of hmmsearch results to display
 label.auto_align_seqs_desc = If true, all fetched sequences will be aligned to the hidden Markov model with which the search was performed
-label.use_accessions_desc = If true, the accession number of each sequence is returned, rather than that sequences name
-label.seq_e_value_desc = The E-value cutoff for returned sequences
+label.use_accessions_desc = If true, the accession number of each sequence is returned, rather than that sequence's name
+label.seq_e_value_desc = The E-value cutoff for returned sequences (hmmsearch -E)
 label.seq_score_desc = The score threshold for returned sequences
-label.dom_e_value_desc = The E-value cutoff for returned domains
+label.dom_e_value_desc = The E-value cutoff for returned domains (hmmsearch -domE)
 label.dom_score_desc = The score threshold for returned domains
-label.not_enough_sequences = There are not enough sequences to run {0}
 label.add_database = Add Database
 label.this_alignment = This alignment
-warn.file_not_exists = File does not exist
 warn.invalid_format = This is not a valid database file format. The current supported formats are Fasta, Stockholm and Pfam.
 label.database_for_hmmsearch = The database hmmsearch will search through
 label.use_reference = Use Reference Annotation
 label.use_reference_desc = If true, hmmbuild will keep all columns defined as a reference position by the reference annotation
-label.hmm_name = HMM Name
-label.hmm_name_desc = The name given to the HMM.
-warn.no_reference_annotation = No reference annotation found.
+label.hmm_name = Alignment HMM Name
+label.hmm_name_desc = The name given to the HMM for the alignment
+warn.no_reference_annotation = No reference annotation found
 label.hmmbuild_for = Build HMM for
-label.hmmbuild_for_desc = Build an HMM for the selected sequence groups.
+label.hmmbuild_for_desc = Build an HMM for the selected sets of sequences
 label.alignment = Alignment
 label.groups_and_alignment = All groups and alignment
 label.groups = All groups
index e42d6b8..6dfefa3 100644 (file)
@@ -808,7 +808,6 @@ label.error_unsupported_owwner_user_colour_scheme = Propietario no soportado par
 label.save_alignment_to_file = Guardar Alineamiento en fichero
 label.save_features_to_file = Guardar Características en un fichero
 label.save_annotation_to_file = Guardar Anotación en un fichero
-label.no_features_on_alignment = No se han encontrado características en el alineamiento
 label.save_pdb_file = Guardar fichero PDB 
 label.save_text_to_file = Guardar Texto en un fichero
 label.save_state = Guardar estado
@@ -887,7 +886,6 @@ label.groovy_support_failed = El soporte Groovy de Jalview ha fallado
 label.couldnt_create_groovy_shell = No es posible crear el shell de Groovy. Compruebe el fichero de log para conocer los detalles.
 error.unsupported_version_calcIdparam = Versión no soportada de {0}
 error.implementation_error_cant_reorder_tree = Error de implementación: no es posible reordenar este Ã¡rbol. No DefaultMutableTreeNode.
-error.invalid_value_for_option = Valor no válido de {0} para la opción {1}
 error.implementation_error_cannot_import_vamsas_doc = Error de implementación - todavía no es posible importar el documento VAMSAS existente en una sesión existente.
 label.vamsas_doc_couldnt_be_opened_as_new_session = El documento VAMSAS no ha podido abrirse como una nueva sesión. Por favor, escoja otra.
 error.implementation_error_vamsas_operation_not_init = Â¡Error de implementación! Operaciones VAMSAS cuando el cliente no estaba inicializado ni conectado
index 2c077b6..921ab2a 100755 (executable)
@@ -53,7 +53,7 @@ public class SeqsetUtils
       sqinfo.put("Description", seq.getDescription());
     }
 
-    Vector<SequenceFeature> sfeat = new Vector<SequenceFeature>();
+    Vector<SequenceFeature> sfeat = new Vector<>();
     List<SequenceFeature> sfs = seq.getFeatures().getAllFeatures();
     sfeat.addAll(sfs);
 
@@ -70,7 +70,7 @@ public class SeqsetUtils
               (seq.getDatasetSequence() != null) ? seq.getDatasetSequence()
                       : new Sequence("THISISAPLACEHOLDER", ""));
     }
-    if (seq.isHMMConsensusSequence())
+    if (seq.hasHMMProfile())
     {
       sqinfo.put("HMM", seq.getHMM());
     }
@@ -143,8 +143,7 @@ public class SeqsetUtils
 
     if (hmm != null)
     {
-      sq.setHMM(new HiddenMarkovModel(hmm));
-      sq.setIsHMMConsensusSequence(true);
+      sq.setHMM(new HiddenMarkovModel(hmm, sq));
     }
     return namePresent;
   }
index ecc90b8..e99c021 100644 (file)
@@ -128,8 +128,7 @@ public class OverviewCanvas extends Component
     {
       mg.translate(0, od.getSequencesHeight());
       or.drawGraph(mg, av.getAlignmentConservationAnnotation(),
-              av.getCharWidth(), od.getGraphHeight(),
-              od.getColumns(av.getAlignment()));
+              od.getGraphHeight(), od.getColumns(av.getAlignment()));
       mg.translate(0, -od.getSequencesHeight());
     }
 
index 6b100ea..e3b4c64 100755 (executable)
@@ -53,8 +53,6 @@ public class Alignment implements AlignmentI
 
   private List<SequenceI> sequences;
 
-  private SequenceI hmmConsensus;
-
   protected List<SequenceGroup> groups;
 
   protected char gapCharacter = '-';
@@ -1956,18 +1954,6 @@ public class Alignment implements AlignmentI
   }
 
   @Override
-  public SequenceI getHmmConsensus()
-  {
-    return hmmConsensus;
-  }
-
-  @Override
-  public void setHmmConsensus(SequenceI hmmConsensus)
-  {
-    this.hmmConsensus = hmmConsensus;
-  }
-
-  @Override
   public void setupJPredAlignment()
   {
     SequenceI repseq = getSequenceAt(0);
@@ -2078,4 +2064,19 @@ public class Alignment implements AlignmentI
       }
     }
   }
+
+  @Override
+  public List<SequenceI> getHmmSequences()
+  {
+    List<SequenceI> result = new ArrayList<>();
+    for (int i = 0; i < sequences.size(); i++)
+    {
+      SequenceI seq = sequences.get(i);
+      if (seq.hasHMMProfile())
+      {
+        result.add(seq);
+      }
+    }
+    return result;
+  }
 }
index a4270cd..3c2c437 100644 (file)
@@ -1,5 +1,6 @@
 package jalview.datamodel;
 
+import jalview.bin.Cache;
 import jalview.io.HMMFile;
 import jalview.schemes.ResidueProperties;
 import jalview.util.Comparison;
@@ -82,11 +83,13 @@ public class HiddenMarkovModel
   }
 
   /**
-   * Copy constructor
+   * Copy constructor given a new aligned sequence with which to associate the
+   * HMM profile
    * 
    * @param hmm
+   * @param sq
    */
-  public HiddenMarkovModel(HiddenMarkovModel hmm)
+  public HiddenMarkovModel(HiddenMarkovModel hmm, SequenceI sq)
   {
     super();
     this.fileProperties = new HashMap<>(hmm.fileProperties);
@@ -94,6 +97,15 @@ public class HiddenMarkovModel
     this.nodes = new ArrayList<>(hmm.nodes);
     this.symbolIndexLookup = hmm.symbolIndexLookup;
     this.fileHeader = new String(hmm.fileHeader);
+    this.hmmSeq = sq;
+    if (sq.getDatasetSequence() == hmm.mapToHmmConsensus.getTo())
+    {
+      this.mapToHmmConsensus = hmm.mapToHmmConsensus;
+    }
+    else
+    {
+      Cache.log.error("Error: HMM copied with change of mapped sequence");
+    }
   }
 
   /**
@@ -549,8 +561,6 @@ public class HiddenMarkovModel
             lastResNo - gapCount);
     seq.createDatasetSequence();
     seq.setHMM(this);
-    seq.setIsHMMConsensusSequence(true);
-
     this.hmmSeq = seq;
 
     /*
@@ -606,7 +616,20 @@ public class HiddenMarkovModel
   public void setNodes(List<HMMNode> nodeList)
   {
     nodes = nodeList;
-    buildConsensusSequence();
+    if (nodes.size() > 1)
+    {
+      buildConsensusSequence();
+    }
+  }
+
+  /**
+   * Sets the aligned consensus sequence this HMM is the model for
+   * 
+   * @param hmmSeq
+   */
+  public void setHmmSeq(SequenceI hmmSeq)
+  {
+    this.hmmSeq = hmmSeq;
   }
 }
 
index 755abbb..9464c74 100755 (executable)
@@ -343,13 +343,9 @@ public class Sequence extends ASequence implements SequenceI
         this.addPDBId(new PDBEntry(pdb));
       }
     }
-    if (seq.isHMMConsensusSequence())
-    {
-      this.isHMMConsensusSequence = true;
-    }
     if (seq.getHMM() != null)
     {
-      this.hmm = new HiddenMarkovModel(seq.getHMM());
+      this.hmm = new HiddenMarkovModel(seq.getHMM(), this);
     }
 
   }
@@ -1916,18 +1912,6 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   @Override
-  public boolean isHMMConsensusSequence()
-  {
-    return isHMMConsensusSequence;
-  }
-
-  @Override
-  public void setIsHMMConsensusSequence(boolean value)
-  {
-    this.isHMMConsensusSequence = value;
-  }
-
-  @Override
   public boolean hasHMMAnnotation()
   {
     if (this.annotation == null) {
@@ -2107,4 +2091,10 @@ public class Sequence extends ASequence implements SequenceI
     // otherwise, sequence was completely hidden
     return 0;
   }
+
+  @Override
+  public boolean hasHMMProfile()
+  {
+    return hmm != null;
+  }
 }
index ee4b844..a280079 100644 (file)
@@ -72,14 +72,10 @@ public interface SequenceCollectionI
   boolean isNucleotide();
 
   /**
-   * Returns the HMM consensus sequence (if any) for the collection, or null
+   * Returns the (possibly empty) list of HMM consensus sequences in the
+   * collection
    * 
    * @return
    */
-  SequenceI getHmmConsensus();
-
-  /**
-   * Sets the HMM consensus sequence for the collection
-   */
-  void setHmmConsensus(SequenceI hmmSeq);
+  List<SequenceI> getHmmSequences();
 }
index aebcbb3..b558f40 100755 (executable)
@@ -88,11 +88,6 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   private SequenceI seqrep;
 
-  /*
-   * HMM consensus sequence for group (if any)
-   */
-  private SequenceI hmmConsensus;
-
   private int width = -1;
 
   /*
@@ -283,7 +278,6 @@ public class SequenceGroup implements AnnotatedCollectionI
         seqs[ipos].setDescription(seq.getDescription());
         seqs[ipos].setDBRefs(seq.getDBRefs());
         seqs[ipos].setSequenceFeatures(seq.getSequenceFeatures());
-        seqs[ipos].setIsHMMConsensusSequence(seq.isHMMConsensusSequence());
         if (seq.getDatasetSequence() != null)
         {
           seqs[ipos].setDatasetSequence(seq.getDatasetSequence());
@@ -1600,18 +1594,6 @@ public class SequenceGroup implements AnnotatedCollectionI
     hmmNormaliseSequenceLogo = state;
   }
 
-  @Override
-  public SequenceI getHmmConsensus()
-  {
-    return hmmConsensus;
-  }
-
-  @Override
-  public void setHmmConsensus(SequenceI hmmSeq)
-  {
-    this.hmmConsensus = hmmSeq;
-  }
-
   public ProfilesI getConsensusData()
   {
     return consensusProfiles;
@@ -1627,4 +1609,19 @@ public class SequenceGroup implements AnnotatedCollectionI
     this.hmmProfiles = hmmProfiles;
   }
 
+  @Override
+  public List<SequenceI> getHmmSequences()
+  {
+    List<SequenceI> result = new ArrayList<>();
+    for (int i = 0; i < sequences.size(); i++)
+    {
+      SequenceI seq = sequences.get(i);
+      if (seq.hasHMMProfile())
+      {
+        result.add(seq);
+      }
+    }
+    return result;
+  }
+
 }
index 5b3d782..6d34d07 100755 (executable)
@@ -499,10 +499,6 @@ public interface SequenceI extends ASequenceI
    */
   public List<DBRefEntry> getPrimaryDBRefs();
 
-  boolean isHMMConsensusSequence();
-
-  void setIsHMMConsensusSequence(boolean isHMMConsensusSequence);
-
   /**
    * Answers true if the sequence has annotation for Hidden Markov Model
    * information content, else false
@@ -576,7 +572,7 @@ public interface SequenceI extends ASequenceI
    *          the iterator to use
    * @return a String corresponding to the sequence
    */
-  public String getSequenceStringFromIterator(Iterator<int[]> it);
+  String getSequenceStringFromIterator(Iterator<int[]> it);
 
   /**
    * Locate the first position in this sequence which is not contained in an
@@ -586,5 +582,12 @@ public interface SequenceI extends ASequenceI
    *          iterator over regions
    * @return first residue not contained in regions
    */
-  public int firstResidueOutsideIterator(Iterator<int[]> it);
+  int firstResidueOutsideIterator(Iterator<int[]> it);
+
+  /**
+   * Answers true if this sequence has an associated Hidden Markov Model
+   * 
+   * @return
+   */
+  boolean hasHMMProfile();
 }
index 009d946..bcb8423 100644 (file)
@@ -54,7 +54,6 @@ import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SeqCigar;
@@ -106,7 +105,6 @@ import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.ParamDatastoreI;
 import jalview.ws.params.WsParamSetI;
-import jalview.ws.params.simple.Option;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.awt.BorderLayout;
@@ -153,7 +151,6 @@ import java.util.Vector;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JEditorPane;
 import javax.swing.JFileChooser;
-import javax.swing.JFrame;
 import javax.swing.JInternalFrame;
 import javax.swing.JLayeredPane;
 import javax.swing.JMenu;
@@ -186,10 +183,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   AlignViewport viewport;
 
   public AlignViewControllerI avc;
-  /*
-   * The selected HMM for this align frame
-   */
-  SequenceI selectedHMMSequence;
 
   List<AlignmentPanel> alignPanels = new ArrayList<>();
 
@@ -1031,21 +1024,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       return;
     }
-    List<ArgumentI> args = new ArrayList<>();
-    if (withDefaults)
-    {
-      // todo: construct this in HMMERPreset?
-      String argName = MessageManager.getString("label.hmmbuild_for");
-      String argValue = MessageManager.getString("label.alignment");
-      args.add(
-              new Option(argName, null, false, null, argValue, null, null));
-    }
-    else
+
+    /*
+     * get default parameters, and optionally show a dialog
+     * to allow them to be modified
+     */
+    ParamDatastoreI store = HMMERParamStore.forBuild(viewport);
+    List<ArgumentI> args = store.getServiceParameters();
+
+    if (!withDefaults)
     {
       WsParamSetI set = new HMMERPreset();
-      ParamDatastoreI store = HMMERParamStore.forBuild();
-      WsJobParameters params = new WsJobParameters(new JFrame(), store, set,
-              args);
+      WsJobParameters params = new WsJobParameters(store, set, args);
       if (params.showRunDialog())
       {
         args = params.getJobParams();
@@ -1065,13 +1055,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       return;
     }
-    List<ArgumentI> args = new ArrayList<>();
+
+    /*
+     * get default parameters, and optionally show a dialog
+     * to allow them to be modified
+     */
+    ParamDatastoreI store = HMMERParamStore.forAlign(viewport);
+    List<ArgumentI> args = store.getServiceParameters();
+
     if (!withDefaults)
     {
       WsParamSetI set = new HMMERPreset();
-      ParamDatastoreI store = HMMERParamStore.forAlign();
-      WsJobParameters params = new WsJobParameters(new JFrame(), store, set,
-              args);
+      WsJobParameters params = new WsJobParameters(store, set, args);
       if (params.showRunDialog())
       {
         args = params.getJobParams();
@@ -1091,13 +1086,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       return;
     }
-    List<ArgumentI> args = new ArrayList<>();
+
+    /*
+     * get default parameters, and (if requested) show 
+     * dialog to allow modification
+     */
+    ParamDatastoreI store = HMMERParamStore.forSearch(viewport);
+    List<ArgumentI> args = store.getServiceParameters();
+
     if (!withDefaults)
     {
       WsParamSetI set = new HMMERPreset();
-      ParamDatastoreI store = HMMERParamStore.forSearch();
-      WsJobParameters params = new WsJobParameters(new JFrame(), store, set,
-              args);
+      WsJobParameters params = new WsJobParameters(store, set, args);
       if (params.showRunDialog())
       {
         args = params.getJobParams();
@@ -1112,16 +1112,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
-   * Checks if the frame has a selected hidden Markov model
+   * Checks if the alignment has at least one hidden Markov model, if not shows
+   * a dialog advising to run hmmbuild or load an HMM profile
    * 
    * @return
    */
   private boolean checkForHMM()
   {
-    if (getSelectedHMM() == null)
+    if (viewport.getAlignment().getHmmSequences().isEmpty())
     {
       JOptionPane.showMessageDialog(this,
-              MessageManager.getString("warn.no_selected_hmm"));
+              MessageManager.getString("warn.no_hmm"));
       return false;
     }
     return true;
@@ -1138,7 +1139,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     if (getViewport().getAlignment().getSequences().size() < required)
     {
       JOptionPane.showMessageDialog(this,
-              MessageManager.getString("warn.not_enough_sequences"));
+              MessageManager.getString("label.not_enough_sequences"));
       return false;
     }
     return true;
@@ -1185,7 +1186,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     else
     {
       JOptionPane.showMessageDialog(this,
-              MessageManager.getString("warn.not_enough_sequences"));
+              MessageManager.getString("label.not_enough_sequences"));
     }
   }
 
@@ -5811,44 +5812,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     hmmerMenu.setEnabled(HmmerCommand.isHmmerAvailable());
   }
 
-  /**
-   * Returns the selected hidden Markov model.
-   * 
-   * @return
-   */
-  public HiddenMarkovModel getSelectedHMM()
-  {
-    if (selectedHMMSequence == null)
-    {
-      return null;
-    }
-    return selectedHMMSequence.getHMM();
-  }
-
-  /**
-   * Returns the selected hidden Markov model.
-   * 
-   * @return
-   */
-  public SequenceI getSelectedHMMSequence()
-  {
-    return selectedHMMSequence;
-  }
-
-  /**
-   * Sets the selected hidden Markov model
-   * 
-   * @param selectedHMM
-   */
-  public void setSelectedHMMSequence(SequenceI selectedHMM)
-  {
-    this.selectedHMMSequence = selectedHMM;
-    hmmAlign.setText(MessageManager.getString("label.hmmalign") + " to "
-            + selectedHMM.getHMM().getName());
-    hmmSearch.setText(MessageManager.getString("label.hmmsearch") + " with "
-            + selectedHMM.getHMM().getName());
-  }
-
   @Override
   public void hmmerMenu_actionPerformed(ActionEvent e)
   {
index 829135b..537ec17 100644 (file)
@@ -60,6 +60,7 @@ import javax.swing.JInternalFrame;
  * around to the bottom of the window stack (as the original implementation
  * does)
  * 
+ * see com.sun.java.swing.plaf.windows.WindowsDesktopManager
  */
 public class AquaInternalFrameManager extends DefaultDesktopManager
 {
@@ -253,4 +254,4 @@ public class AquaInternalFrameManager extends DefaultDesktopManager
   {
     switchFrame(false);
   }
-}
\ No newline at end of file
+}
index 4658668..190eda1 100644 (file)
@@ -22,12 +22,10 @@ package jalview.gui;
 
 import jalview.util.MessageManager;
 
-import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
+import java.awt.Container;
 import java.awt.Font;
-import java.awt.GridLayout;
-import java.awt.Rectangle;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -39,10 +37,8 @@ import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JComboBox;
 import javax.swing.JComponent;
-import javax.swing.JLabel;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-import javax.swing.JPanel;
 import javax.swing.JScrollBar;
 import javax.swing.SwingConstants;
 import javax.swing.border.Border;
@@ -144,54 +140,23 @@ public final class JvSwingUtils
   }
 
   /**
+   * A convenience method that that adds a component with label to a container,
+   * sets a tooltip on both component and label, and optionally specifies layout
+   * constraints for the added component (but not the label)
    * 
-   * @param panel
+   * @param container
    * @param tooltip
    * @param label
-   * @param valBox
-   * @return the GUI element created that was added to the layout so it's
-   *         attributes can be changed.
+   * @param comp
+   * @param constraints
    */
-  public static JPanel addtoLayout(JPanel panel, String tooltip,
-          JComponent label, JComponent valBox)
-  {
-    JPanel laypanel = new JPanel(new GridLayout(1, 2));
-    JPanel labPanel = new JPanel(new BorderLayout());
-    JPanel valPanel = new JPanel();
-    labPanel.setBounds(new Rectangle(7, 7, 158, 23));
-    valPanel.setBounds(new Rectangle(172, 7, 270, 23));
-    labPanel.add(label, BorderLayout.WEST);
-    valPanel.add(valBox);
-    laypanel.add(labPanel);
-    laypanel.add(valPanel);
-    valPanel.setToolTipText(tooltip);
-    labPanel.setToolTipText(tooltip);
-    valBox.setToolTipText(tooltip);
-    panel.add(laypanel);
-    panel.validate();
-    return laypanel;
-  }
-
-  public static void mgAddtoLayout(JPanel cpanel, String tooltip,
-          JLabel jLabel, JComponent name)
-  {
-    mgAddtoLayout(cpanel, tooltip, jLabel, name, null);
-  }
-
-  public static void mgAddtoLayout(JPanel cpanel, String tooltip,
-          JLabel jLabel, JComponent name, String params)
+  public static void addtoLayout(Container container, String tooltip,
+          JComponent label, JComponent comp, String constraints)
   {
-    cpanel.add(jLabel);
-    if (params == null)
-    {
-      cpanel.add(name);
-    }
-    else
-    {
-      cpanel.add(name, params);
-    }
-    name.setToolTipText(tooltip);
-    jLabel.setToolTipText(tooltip);
+    container.add(label);
+    container.add(comp, constraints);
+    comp.setToolTipText(tooltip); // this doesn't seem to show?
+    label.setToolTipText(tooltip);
   }
 
   /**
@@ -356,7 +321,7 @@ public final class JvSwingUtils
 
   /**
    * Adds a titled border to the component in the default font and position (top
-   * left), optionally witht italic text
+   * left), optionally with italic text
    * 
    * @param comp
    * @param title
index 1505df8..fcb293c 100644 (file)
@@ -27,21 +27,24 @@ import jalview.ws.params.ParameterI;
 import jalview.ws.params.ValueConstrainI;
 import jalview.ws.params.ValueConstrainI.ValueType;
 import jalview.ws.params.simple.LogarithmicParameter;
+import jalview.ws.params.simple.StringParameter;
 
 import java.awt.BorderLayout;
+import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
+import java.awt.FlowLayout;
 import java.awt.Font;
-import java.awt.GridLayout;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -72,11 +75,29 @@ import net.miginfocom.swing.MigLayout;
  */
 public class OptsAndParamsPage
 {
-  /**
+  public static final int PARAM_WIDTH = 340;
+
+  public static final int PARAM_HEIGHT = 150;
+
+  public static final int PARAM_CLOSEDHEIGHT = 80;
+
+  URL linkImageURL = getClass().getResource("/images/link.gif");
+
+  Map<String, OptionBox> optSet = new LinkedHashMap<>();
+
+  Map<String, ParamBox> paramSet = new LinkedHashMap<>();
+
+  /*
    * compact or verbose style parameters
    */
   boolean compact = false;
 
+  OptsParametersContainerI poparent;
+
+  /**
+   * A class that models a panel rendering a single option (checkbox or choice
+   * list)
+   */
   public class OptionBox extends JPanel
           implements MouseListener, ActionListener
   {
@@ -94,12 +115,12 @@ public class OptsAndParamsPage
 
     JLabel optlabel = new JLabel();
 
-    JComboBox val = new JComboBox();
+    JComboBox<String> val = new JComboBox<>();
 
     public OptionBox(OptionI opt)
     {
       option = opt;
-      setLayout(new BorderLayout());
+      setLayout(new FlowLayout(FlowLayout.LEFT));
       enabled.setSelected(opt.isRequired()); // TODO: lock required options
       enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
       enabled.setText("");
@@ -127,17 +148,16 @@ public class OptsAndParamsPage
                   JvSwingUtils.wrapTooltip(true, opt.getDescription()));
         }
       }
-      add(enabled, BorderLayout.NORTH);
-      for (Object str : opt.getPossibleValues())
+      add(enabled);
+      for (String str : opt.getPossibleValues())
       {
         val.addItem(str);
       }
       val.setSelectedItem(opt.getValue());
-      if (opt.getPossibleValues().size() > 1)
+      if (opt.getPossibleValues().size() > 1 || opt.isRequired())
       {
-        setLayout(new GridLayout(1, 2));
         val.addActionListener(this);
-        add(val, BorderLayout.SOUTH);
+        add(val);
       }
       // TODO: add actionListeners for popup (to open further info),
       // and to update list of parameters if an option is enabled
@@ -219,15 +239,11 @@ public class OptsAndParamsPage
     @Override
     public void mouseEntered(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
     public void mouseExited(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -269,30 +285,47 @@ public class OptsAndParamsPage
       }
     }
 
+    /**
+     * toString representation for identification in the debugger only
+     */
+    @Override
+    public String toString()
+    {
+      return option == null ? super.toString() : option.toString();
+    }
+
   }
 
+  /**
+   * A class that models a panel rendering a single parameter
+   */
   public class ParamBox extends JPanel
           implements ChangeListener, ActionListener, MouseListener
   {
+    /*
+     * parameter values (or their logs) are multiplied by this
+     * scaling factor to ensure an integer range for the slider
+     */
+    private int sliderScaleFactor = 1;
+
+    boolean isLogarithmicParameter;
 
-    boolean isLogarithmic;
+    boolean isChoiceParameter;
 
-    boolean adjusting = false;
+    boolean isIntegerParameter;
 
-    boolean choice = false;
+    boolean adjusting;
 
-    JComboBox choicebox;
+    JComboBox<String> choicebox;
 
-    JPanel controlPanel = new JPanel();
+    JPanel controlsPanel = new JPanel();
 
-    boolean descisvisible = false;
+    boolean descriptionIsVisible = false;
 
     JScrollPane descPanel = new JScrollPane();
 
     final URL finfo;
 
-    boolean integ = false;
-
     Object lastVal;
 
     ParameterI parameter;
@@ -301,62 +334,78 @@ public class OptsAndParamsPage
 
     JPanel settingPanel = new JPanel();
 
-    JButton showDesc = new JButton();
+    JSlider slider;
 
-    JSlider slider = null;
+    JTextArea descriptionText = new JTextArea();
 
-    JTextArea string = new JTextArea();
+    ValueConstrainI validator;
 
-    ValueConstrainI validator = null;
+    JTextField valueField;
 
-    JTextField valueField = null;
+    private String descTooltip;
 
-    public ParamBox(final OptsParametersContainerI pmlayout,
+    public ParamBox(final OptsParametersContainerI paramContainer,
             ParameterI parm)
     {
-      pmdialogbox = pmlayout;
+      pmdialogbox = paramContainer;
       finfo = parm.getFurtherDetails();
       validator = parm.getValidValue();
       parameter = parm;
+
+      isLogarithmicParameter = parm instanceof LogarithmicParameter;
+
       if (validator != null)
       {
-        integ = validator.getType() == ValueType.Integer;
-      }
-      else
-      {
-        if (parameter.getPossibleValues() != null)
+        ValueType type = validator.getType();
+        isIntegerParameter = type == ValueType.Integer;
+
+        /*
+         * ensure slider has an integer range corresponding to
+         * the min-max range of the parameter
+         */
+        if (validator.getMin() != null && !isIntegerParameter)
         {
-          choice = true;
+          double min = validator.getMin().doubleValue();
+          double max = validator.getMax().doubleValue();
+          if (isLogarithmicParameter)
+          {
+            min = Math.log(min);
+            max = Math.log(max);
+          }
+          sliderScaleFactor = (int) (1000000 / (max - min));
+          // todo scaleMin, scaleMax could also be final fields
         }
       }
-      if (parm instanceof LogarithmicParameter)
+      else
       {
-        isLogarithmic = true;
+        isChoiceParameter = parameter.getPossibleValues() != null;
       }
 
-      if (!compact)
+      if (compact)
       {
-        makeExpanderParam(parm);
+        addCompactParameter(parm);
       }
       else
       {
-        makeCompactParam(parm);
-
+        addExpandableParam(parm);
       }
     }
 
-    private void makeCompactParam(ParameterI parm)
+    /**
+     * Adds a 'compact' format parameter, with any help text shown as a tooltip
+     * 
+     * @param parm
+     */
+    private void addCompactParameter(ParameterI parm)
     {
       setLayout(new MigLayout("", "[][grow]"));
-
       String ttipText = null;
 
-      controlPanel.setLayout(new BorderLayout());
+      controlsPanel.setLayout(new BorderLayout());
 
       if (parm.getDescription() != null
               && parm.getDescription().trim().length() > 0)
       {
-        // Only create description boxes if there actually is a description.
         ttipText = (JvSwingUtils.wrapTooltip(true,
                 parm.getDescription() + (finfo != null ? "<br><img src=\""
                         + linkImageURL + "\"/>"
@@ -365,91 +414,57 @@ public class OptsAndParamsPage
                         : "")));
       }
 
-      JvSwingUtils.mgAddtoLayout(this, ttipText, new JLabel(parm.getName()),
-              controlPanel, "");
+      JvSwingUtils.addtoLayout(this, ttipText, new JLabel(parm.getName()),
+              controlsPanel, "");
       updateControls(parm);
       validate();
     }
 
-    private void makeExpanderParam(ParameterI parm)
+    /**
+     * Adds an 'expanded' format parameter, with any help shown in a panel that
+     * may be shown or hidden
+     * 
+     * @param parm
+     */
+    private void addExpandableParam(ParameterI parm)
     {
       setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT));
       setBorder(new TitledBorder(parm.getName()));
       setLayout(null);
-      showDesc.setFont(new Font("Verdana", Font.PLAIN, 6));
-      showDesc.setText("+");
-      string.setFont(new Font("Verdana", Font.PLAIN, 11));
-      string.setBackground(getBackground());
+      descriptionText.setFont(new Font("Verdana", Font.PLAIN, 11));
+      descriptionText.setBackground(getBackground());
 
-      string.setEditable(false);
-      descPanel.getViewport().setView(string);
+      descriptionText.setEditable(false);
+      descPanel.getViewport().setView(descriptionText);
 
       descPanel.setVisible(false);
 
       JPanel firstrow = new JPanel();
       firstrow.setLayout(null);
-      controlPanel.setLayout(new BorderLayout());
-      controlPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
+      controlsPanel.setLayout(new BorderLayout());
+      controlsPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
               PARAM_CLOSEDHEIGHT - 50));
-      firstrow.add(controlPanel);
+      firstrow.add(controlsPanel);
       firstrow.setBounds(new Rectangle(10, 20, PARAM_WIDTH - 30,
               PARAM_CLOSEDHEIGHT - 30));
 
-      final ParamBox me = this;
-
       if (parm.getDescription() != null
               && parm.getDescription().trim().length() > 0)
       {
-        // Only create description boxes if there actually is a description.
-        if (finfo != null)
-        {
-          showDesc.setToolTipText(JvSwingUtils.wrapTooltip(true,
-                  MessageManager.formatMessage(
-                          "label.opt_and_params_show_brief_desc_image_link",
-                          new String[]
-                          { linkImageURL.toExternalForm() })));
-          showDesc.addMouseListener(this);
-        }
-        else
-        {
-          showDesc.setToolTipText(
-                  JvSwingUtils.wrapTooltip(true, MessageManager.getString(
-                          "label.opt_and_params_show_brief_desc")));
-        }
-        showDesc.addActionListener(new ActionListener()
-        {
-
-          @Override
-          public void actionPerformed(ActionEvent e)
-          {
-            descisvisible = !descisvisible;
-            descPanel.setVisible(descisvisible);
-            descPanel.getVerticalScrollBar().setValue(0);
-            me.setPreferredSize(new Dimension(PARAM_WIDTH,
-                    (descisvisible) ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT));
-            me.validate();
-            pmdialogbox.refreshParamLayout();
-          }
-        });
-        string.setWrapStyleWord(true);
-        string.setLineWrap(true);
-        string.setColumns(32);
-        string.setText(parm.getDescription());
-        showDesc.setBounds(new Rectangle(10, 10, 16, 16));
-        firstrow.add(showDesc);
+        addExpandableHelp(firstrow, parm);
       }
       add(firstrow);
       validator = parm.getValidValue();
       parameter = parm;
       if (validator != null)
       {
-        integ = validator.getType() == ValueType.Integer;
+        isIntegerParameter = validator.getType() == ValueType.Integer;
       }
       else
       {
         if (parameter.getPossibleValues() != null)
         {
-          choice = true;
+          isChoiceParameter = true;
         }
       }
       updateControls(parm);
@@ -459,6 +474,57 @@ public class OptsAndParamsPage
       validate();
     }
 
+    /**
+     * Adds a button which can be clicked to show or hide help text
+     * 
+     * @param container
+     * @param param
+     */
+    protected void addExpandableHelp(JPanel container, ParameterI param)
+    {
+      JButton showDescBtn = new JButton("+");
+      showDescBtn.setFont(new Font("Verdana", Font.PLAIN, 8));
+      if (finfo != null)
+      {
+        descTooltip = JvSwingUtils.wrapTooltip(true,
+                MessageManager.formatMessage(
+                        "label.opt_and_params_show_brief_desc_image_link",
+                        new String[]
+                        { linkImageURL.toExternalForm() }));
+        showDescBtn.addMouseListener(this);
+      }
+      else
+      {
+        descTooltip = JvSwingUtils.wrapTooltip(true, MessageManager
+                .getString("label.opt_and_params_show_brief_desc"));
+      }
+      showDescBtn.setToolTipText(descTooltip);
+      showDescBtn.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          descriptionIsVisible = !descriptionIsVisible;
+          showDescBtn.setText(descriptionIsVisible ? "-" : "+");
+          showDescBtn.setToolTipText(
+                  descriptionIsVisible ? null : descTooltip);
+          descPanel.setVisible(descriptionIsVisible);
+          descPanel.getVerticalScrollBar().setValue(0);
+          ParamBox.this.setPreferredSize(new Dimension(PARAM_WIDTH,
+                  (descriptionIsVisible) ? PARAM_HEIGHT
+                          : PARAM_CLOSEDHEIGHT));
+          ParamBox.this.validate();
+          pmdialogbox.refreshParamLayout();
+        }
+      });
+      descriptionText.setWrapStyleWord(true);
+      descriptionText.setLineWrap(true);
+      descriptionText.setColumns(32);
+      descriptionText.setText(param.getDescription());
+      showDescBtn.setBounds(new Rectangle(10, 10, 16, 16));
+      container.add(showDescBtn);
+    }
+
     @Override
     public void actionPerformed(ActionEvent e)
     {
@@ -466,33 +532,26 @@ public class OptsAndParamsPage
       {
         return;
       }
-      if (!choice)
+      if (!isChoiceParameter)
       {
         updateSliderFromValueField();
       }
       checkIfModified();
     }
 
+    /**
+     * Checks whether the value of this parameter has been changed and notifies
+     * the parent page accordingly
+     */
     private void checkIfModified()
     {
-      Object cstate = updateSliderFromValueField();
-      boolean notmod = false;
-      if (cstate.getClass() == lastVal.getClass())
+      Object newValue = updateSliderFromValueField();
+      boolean modified = true;
+      if (newValue.getClass() == lastVal.getClass())
       {
-        if (cstate instanceof int[])
-        {
-          notmod = (((int[]) cstate)[0] == ((int[]) lastVal)[0]);
-        }
-        else if (cstate instanceof float[])
-        {
-          notmod = (((float[]) cstate)[0] == ((float[]) lastVal)[0]);
-        }
-        else if (cstate instanceof String[])
-        {
-          notmod = (((String[]) cstate)[0].equals(((String[]) lastVal)[0]));
-        }
+        modified = !newValue.equals(lastVal);
       }
-      pmdialogbox.argSetModified(this, !notmod);
+      pmdialogbox.argSetModified(this, modified);
     }
 
     @Override
@@ -510,15 +569,10 @@ public class OptsAndParamsPage
       return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
     }
 
-    public int getBoxHeight()
-    {
-      return (descisvisible ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT);
-    }
-
     public ParameterI getParameter()
     {
       ParameterI prm = parameter.copy();
-      if (choice)
+      if (isChoiceParameter)
       {
         prm.setValue((String) choicebox.getSelectedItem());
       }
@@ -547,15 +601,11 @@ public class OptsAndParamsPage
     @Override
     public void mouseEntered(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
     public void mouseExited(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -570,8 +620,6 @@ public class OptsAndParamsPage
     @Override
     public void mouseReleased(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -579,60 +627,72 @@ public class OptsAndParamsPage
     {
       if (!adjusting)
       {
-        if (!isLogarithmic)
+        if (!isLogarithmicParameter)
         {
-          valueField.setText("" + ((integ) ? ("" + slider.getValue())
-                  : ("" + slider.getValue() / 1000f)));
+          /*
+           * set (int or float formatted) text field value
+           */
+          valueField.setText(isIntegerParameter
+                  ? String.valueOf(slider.getValue())
+                  : formatDouble(
+                          slider.getValue() / (float) sliderScaleFactor));
         }
         else
         {
-          Double base = ((LogarithmicParameter) parameter).getBase();
-          Double value = Math.pow(
-                  base,
-                  slider.getValue() / 1000000f);
+          double value = Math.pow(Math.E,
+                  slider.getValue() / (double) sliderScaleFactor);
           valueField.setText(formatDouble(value));
         }
         checkIfModified();
       }
+    }
 
+    /**
+     * Answers the value formatted as a string to 3 decimal places - in
+     * scientific notation if the value is less than 0.001
+     * 
+     * @param value
+     * @return
+     */
+    String formatDouble(double value)
+    {
+      String format = value < 0.001 ? "%3.1E" : "%3.3f";
+      return String.format(format, value);
     }
 
-    public String formatDouble(Double value)
+    /**
+     * Formats a number as integer or float (3dp) or scientific notation (1dp)
+     * 
+     * @param n
+     * @return
+     */
+    String formatNumber(Number n)
     {
-      String string = String.format("%3.3f", value);
-      if (value < 0.001)
-      {
-        string = String.format("%3.3e", value);
-      }
-      return string;
+      return n instanceof Integer ? String.valueOf(n.intValue())
+              : formatDouble(n.doubleValue());
     }
 
-    public void updateControls(ParameterI parm)
+    void updateControls(ParameterI parm)
     {
       adjusting = true;
       boolean init = (choicebox == null && valueField == null);
       if (init)
       {
-        if (choice)
+        if (isChoiceParameter)
         {
-          choicebox = new JComboBox();
+          choicebox = new JComboBox<>();
           choicebox.addActionListener(this);
-          controlPanel.add(choicebox, BorderLayout.CENTER);
+          controlsPanel.add(choicebox, BorderLayout.CENTER);
         }
         else
         {
           slider = new JSlider();
           slider.addChangeListener(this);
-          valueField = new JTextField();
+          int cols = parm instanceof StringParameter ? 20 : 0;
+          valueField = new JTextField(cols);
           valueField.addActionListener(this);
-          valueField.addKeyListener(new KeyListener()
+          valueField.addKeyListener(new KeyAdapter()
           {
-
-            @Override
-            public void keyTyped(KeyEvent e)
-            {
-            }
-
             @Override
             public void keyReleased(KeyEvent e)
             {
@@ -644,32 +704,24 @@ public class OptsAndParamsPage
                 }
               }
             }
-
-            @Override
-            public void keyPressed(KeyEvent e)
-            {
-            }
           });
-          valueField.setPreferredSize(new Dimension(60, 25));
-          controlPanel.add(slider, BorderLayout.WEST);
-          controlPanel.add(valueField, BorderLayout.EAST);
-
+          valueField.setPreferredSize(new Dimension(65, 25));
+          controlsPanel.add(slider, BorderLayout.WEST);
+          controlsPanel.add(valueField, BorderLayout.EAST);
         }
       }
 
       if (parm != null)
       {
-        if (choice)
+        if (isChoiceParameter)
         {
           if (init)
           {
-            List vals = parm.getPossibleValues();
-            for (Object val : vals)
+            for (String val : parm.getPossibleValues())
             {
               choicebox.addItem(val);
             }
           }
-
           if (parm.getValue() != null)
           {
             choicebox.setSelectedItem(parm.getValue());
@@ -677,187 +729,153 @@ public class OptsAndParamsPage
         }
         else
         {
-          if (parm instanceof LogarithmicParameter)
-          {
-            Double base = ((LogarithmicParameter) parm).getBase();
-            Double value = Math.pow(base,
-                    Double.parseDouble(parm.getValue()) / 1000000);
-            valueField.setText(formatDouble(value));
-          }
-          else
-          {
-            valueField.setText(parm.getValue());
-          }
+          valueField.setText(parm.getValue());
         }
       }
       lastVal = updateSliderFromValueField();
       adjusting = false;
     }
 
-    public Object updateSliderFromValueField()
-    {
-      int iVal;
-      float fVal;
-      double dVal;
-      if (validator != null)
+    /**
+     * Action depends on the type of the input parameter:
+     * <ul>
+     * <li>if a text input, returns the trimmed value</li>
+     * <li>if a choice list, returns the selected value</li>
+     * <li>if a value slider and input field, sets the value of the slider from
+     * the value in the text field, limiting it to any defined min-max
+     * range.</li>
+     * </ul>
+     * Answers the (possibly modified) input value, as a String, Integer, Float
+     * or Double.
+     * 
+     * @return
+     */
+    Object updateSliderFromValueField()
+    {
+      if (validator == null)
+      {
+        if (isChoiceParameter)
+        {
+          return choicebox.getSelectedItem();
+        }
+        slider.setVisible(false);
+        return valueField.getText().trim();
+      }
+
+      valueField.setText(valueField.getText().trim());
+
+      /*
+       * ensure not outside min-max range
+       * TODO: provide some visual indicator if limit reached
+       */
+      try
       {
-        if (integ)
+        valueField.setBackground(Color.WHITE);
+        double d = Double.parseDouble(valueField.getText());
+        if (validator.getMin() != null
+                && validator.getMin().doubleValue() > d)
         {
-          iVal = 0;
-          try
-          {
-            valueField.setText(valueField.getText().trim());
-            iVal = Integer.valueOf(valueField.getText());
-            if (validator.getMin() != null
-                    && validator.getMin().intValue() > iVal)
-            {
-              iVal = validator.getMin().intValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-            }
-            if (validator.getMax() != null
-                    && validator.getMax().intValue() < iVal)
-            {
-              iVal = validator.getMax().intValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-            }
-          } catch (Exception e)
-          {
-          }
-          ;
-          // update value field to reflect any bound checking we performed.
-          valueField.setText("" + iVal);
-          if (validator.getMin() != null && validator.getMax() != null)
-          {
-            slider.getModel().setRangeProperties(iVal, 1,
-                    validator.getMin().intValue(),
-                    validator.getMax().intValue() + 1, true);
-          }
-          else
-          {
-            slider.setVisible(false);
-          }
-          return new int[] { iVal };
+          valueField.setText(formatNumber(validator.getMin()));
         }
-        else if (isLogarithmic)
+        if (validator.getMax() != null
+                && validator.getMax().doubleValue() < d)
         {
-          double eValue;
-          dVal = 0d;
-          try
-          {
-            valueField.setText(valueField.getText().trim());
-            eValue = Double.valueOf(valueField.getText());
+          valueField.setText(formatNumber(validator.getMax()));
+        }
+      } catch (NumberFormatException e)
+      {
+        valueField.setBackground(Color.yellow);
+        return Float.NaN;
+      }
 
-            dVal = Math.log(eValue) / Math
-                    .log(((LogarithmicParameter) parameter).getBase())
-                    * 1000000;
+      if (isIntegerParameter)
+      {
+        int iVal = 0;
+        try
+        {
+          iVal = Integer.valueOf(valueField.getText());
+        } catch (Exception e)
+        {
+          valueField.setBackground(Color.yellow);
+          return Integer.valueOf(0);
+        }
 
-            if (validator.getMin() != null
-                    && validator.getMin().doubleValue() > dVal)
-            {
-              dVal = validator.getMin().doubleValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-              // update value field to reflect any bound checking we performed.
-              valueField.setText("" + formatDouble(eValue));
-            }
-            if (validator.getMax() != null
-                    && validator.getMax().doubleValue() < dVal)
-            {
-              dVal = validator.getMax().doubleValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-              // update value field to reflect any bound checking we performed.
-              valueField.setText("" + formatDouble(eValue));
-            }
-          } catch (Exception e)
-          {
-          }
-          ;
-          if (validator.getMin() != null && validator.getMax() != null)
-          {
-            slider.getModel().setRangeProperties((int) (dVal), 1,
-                    (int) (validator.getMin().doubleValue()),
-                    1 + (int) (validator.getMax().doubleValue()),
-                    true);
-          }
-          else
-          {
-            slider.setVisible(false);
-          }
-          return new double[] { dVal };
+        if (validator.getMin() != null && validator.getMax() != null)
+        {
+          slider.getModel().setRangeProperties(iVal, 1,
+                  validator.getMin().intValue(),
+                  validator.getMax().intValue() + 1, true);
         }
         else
         {
-          fVal = 0f;
-          try
-          {
-            valueField.setText(valueField.getText().trim());
-            fVal = Float.valueOf(valueField.getText());
-            if (validator.getMin() != null
-                    && validator.getMin().floatValue() > fVal)
-            {
-              fVal = validator.getMin().floatValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-              // update value field to reflect any bound checking we performed.
-              valueField.setText("" + fVal);
-            }
-            if (validator.getMax() != null
-                    && validator.getMax().floatValue() < fVal)
-            {
-              fVal = validator.getMax().floatValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-              // update value field to reflect any bound checking we performed.
-              valueField.setText("" + fVal);
-            }
-          } catch (Exception e)
-          {
-          }
-          ;
-          if (validator.getMin() != null && validator.getMax() != null)
-          {
-            slider.getModel().setRangeProperties((int) (fVal * 1000f), 1,
-                    (int) (validator.getMin().floatValue() * 1000f),
-                    1 + (int) (validator.getMax().floatValue() * 1000f),
-                    true);
-          }
-          else
-          {
-            slider.setVisible(false);
-          }
-          return new float[] { fVal };
+          slider.setVisible(false);
         }
+        return new Integer(iVal);
       }
-      else
+
+      if (isLogarithmicParameter)
       {
-        if (!choice)
+        double dVal = 0d;
+        try
         {
-          slider.setVisible(false);
-          return new String[] { valueField.getText().trim() };
+          double eValue = Double.valueOf(valueField.getText());
+          dVal = Math.log(eValue) * sliderScaleFactor;
+        } catch (Exception e)
+        {
+          // shouldn't be possible here
+          valueField.setBackground(Color.yellow);
+          return Double.NaN;
+        }
+        if (validator.getMin() != null && validator.getMax() != null)
+        {
+          double scaleMin = Math.log(validator.getMin().doubleValue())
+                  * sliderScaleFactor;
+          double scaleMax = Math.log(validator.getMax().doubleValue())
+                  * sliderScaleFactor;
+          slider.getModel().setRangeProperties((int) (dVal), 1,
+                  (int) scaleMin, 1 + (int) scaleMax, true);
         }
         else
         {
-          return new String[] { (String) choicebox.getSelectedItem() };
+          slider.setVisible(false);
         }
+        return new Double(dVal);
       }
 
+      float fVal = 0f;
+      try
+      {
+        fVal = Float.valueOf(valueField.getText());
+      } catch (Exception e)
+      {
+        return Float.valueOf(0f); // shouldn't happen
+      }
+      if (validator.getMin() != null && validator.getMax() != null)
+      {
+        float scaleMin = validator.getMin().floatValue()
+                * sliderScaleFactor;
+        float scaleMax = validator.getMax().floatValue()
+                * sliderScaleFactor;
+        slider.getModel().setRangeProperties(
+                (int) (fVal * sliderScaleFactor), 1, (int) scaleMin,
+                1 + (int) scaleMax, true);
+      }
+      else
+      {
+        slider.setVisible(false);
+      }
+      return new Float(fVal);
     }
   }
 
-  public static final int PARAM_WIDTH = 340;
-
-  public static final int PARAM_HEIGHT = 150;
-
-  public static final int PARAM_CLOSEDHEIGHT = 80;
-
-  public OptsAndParamsPage(OptsParametersContainerI paramContainer)
-  {
-    this(paramContainer, false);
-  }
-
+  /**
+   * Constructor with the option to show 'compact' format (parameter description
+   * as tooltip) or 'expanded' format (parameter description in a textbox which
+   * may be opened or closed). Use compact for simple description text, expanded
+   * for more wordy or formatted text.
+   * 
+   * @param paramContainer
+   */
   public OptsAndParamsPage(OptsParametersContainerI paramContainer,
           boolean compact)
   {
@@ -887,12 +905,6 @@ public class OptsAndParamsPage
     mnu.show(invoker, x, y);
   }
 
-  URL linkImageURL = getClass().getResource("/images/link.gif");
-
-  Map<String, OptionBox> optSet = new java.util.LinkedHashMap<>();
-
-  Map<String, ParamBox> paramSet = new java.util.LinkedHashMap<>();
-
   public Map<String, OptionBox> getOptSet()
   {
     return optSet;
@@ -913,8 +925,6 @@ public class OptsAndParamsPage
     this.paramSet = paramSet;
   }
 
-  OptsParametersContainerI poparent;
-
   OptionBox addOption(OptionI opt)
   {
     OptionBox cb = optSet.get(opt.getName());
@@ -958,11 +968,9 @@ public class OptsAndParamsPage
       }
       else
       {
-        throw new Error(MessageManager.formatMessage(
-                "error.invalid_value_for_option", new String[]
-                { string, option.getName() }));
+        throw new Error(String.format("Invalid value '%s' for option '%s'",
+                string, option.getName()));
       }
-
     }
     if (option.isRequired() && !cb.enabled.isSelected())
     {
@@ -1012,5 +1020,4 @@ public class OptsAndParamsPage
 
     return argSet;
   }
-
 }
index 7994bf2..cc361a5 100644 (file)
@@ -157,8 +157,7 @@ public class OverviewCanvas extends JComponent
     {
       mg.translate(0, od.getSequencesHeight());
       or.drawGraph(mg, av.getAlignmentConservationAnnotation(),
-              av.getCharWidth(), od.getGraphHeight(),
-              od.getColumns(av.getAlignment()));
+              od.getGraphHeight(), od.getColumns(av.getAlignment()));
       mg.translate(0, -od.getSequencesHeight());
     }
 
index e3becf6..a3a2422 100644 (file)
@@ -360,21 +360,6 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       });
       add(menuItem);
 
-      if (sequence.isHMMConsensusSequence())
-      {
-        JMenuItem selectHMM = new JCheckBoxMenuItem();
-        selectHMM.setText(MessageManager.getString("label.select_hmm"));
-        selectHMM.addActionListener(new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent e)
-          {
-            selectHMM_actionPerformed(sequence);
-          }
-        });
-        add(selectHMM);
-      }
-
       if (alignPanel.av.getSelectionGroup() != null
               && alignPanel.av.getSelectionGroup().getSize() > 1)
       {
@@ -1368,15 +1353,6 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     jMenu1.add(displayNonconserved);
   }
 
-  protected void selectHMM_actionPerformed(SequenceI seq)
-  {
-    // TODO move this to Viewport
-    if (seq.isHMMConsensusSequence())
-    {
-      ap.alignFrame.setSelectedHMMSequence(seq);
-    }
-  }
-
   /**
    * Constructs the entries for the colour menu
    */
index df35b5e..5382f8d 100755 (executable)
@@ -37,6 +37,7 @@ import jalview.urls.UrlLinkTableModel;
 import jalview.urls.api.UrlProviderFactoryI;
 import jalview.urls.api.UrlProviderI;
 import jalview.urls.desktop.DesktopUrlProviderFactory;
+import jalview.util.FileUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.util.UrlConstants;
@@ -61,6 +62,7 @@ import javax.swing.JColorChooser;
 import javax.swing.JFileChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JPanel;
+import javax.swing.JTextField;
 import javax.swing.ListSelectionModel;
 import javax.swing.RowFilter;
 import javax.swing.RowSorter;
@@ -84,6 +86,12 @@ import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
  */
 public class Preferences extends GPreferences
 {
+  public static final String HMMSEARCH_SEQCOUNT = "HMMSEARCH_SEQCOUNT";
+
+  public static final String HMMINFO_GLOBAL_BACKGROUND = "HMMINFO_GLOBAL_BACKGROUND";
+
+  public static final String HMMALIGN_TRIM_TERMINI = "HMMALIGN_TRIM_TERMINI";
+
   public static final String ENABLE_SPLIT_FRAME = "ENABLE_SPLIT_FRAME";
 
   public static final String SCALE_PROTEIN_TO_CDNA = "SCALE_PROTEIN_TO_CDNA";
@@ -108,6 +116,8 @@ public class Preferences extends GPreferences
   
   public static final String HMMER_PATH = "HMMER_PATH";
 
+  public static final String CYGWIN_PATH = "CYGWIN_PATH";
+
   public static final String HMMSEARCH_DB_PATHS = "HMMSEARCH_DB_PATHS";
 
   public static final String HMMSEARCH_DBS = "HMMSEARCH_DBS";
@@ -218,8 +228,8 @@ public class Preferences extends GPreferences
     /*
      * Set HMMER tab defaults
      */
-    hmmrTrimTermini.setSelected(Cache.getDefault("TRIM_TERMINI", false));
-    if (Cache.getDefault("USE_UNIPROT", false))
+    hmmrTrimTermini.setSelected(Cache.getDefault(HMMALIGN_TRIM_TERMINI, false));
+    if (Cache.getDefault(HMMINFO_GLOBAL_BACKGROUND, false))
     {
       hmmerBackgroundUniprot.setSelected(true);
     }
@@ -228,14 +238,14 @@ public class Preferences extends GPreferences
       hmmerBackgroundAlignment.setSelected(true);
     }
     hmmerSequenceCount
-            .setText(Cache.getProperty("SEQUENCES_TO_KEEP"));
+            .setText(Cache.getProperty(HMMSEARCH_SEQCOUNT));
     hmmerPath.setText(Cache.getProperty(HMMER_PATH));
     hmmerPath.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        validateHMMERPath(true);
+        validateHmmerPath();
       }
     });
     hmmerPath.addFocusListener(new FocusAdapter()
@@ -243,9 +253,34 @@ public class Preferences extends GPreferences
       @Override
       public void focusLost(FocusEvent e)
       {
-        validateHMMERPath(true);
+        validateHmmerPath();
       }
     });
+    if (cygwinPath != null)
+    {
+      String path = Cache.getProperty(CYGWIN_PATH);
+      if (path == null)
+      {
+        path = FileUtils.getPathTo("bash");
+      }
+      cygwinPath.setText(path);
+      cygwinPath.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          validateCygwinPath();
+        }
+      });
+      cygwinPath.addFocusListener(new FocusAdapter()
+      {
+        @Override
+        public void focusLost(FocusEvent e)
+        {
+          validateCygwinPath();
+        }
+      });
+    }
 
     /*
      * Set Visual tab defaults
@@ -706,14 +741,17 @@ public class Preferences extends GPreferences
     /*
      * Save HMMER settings
      */
-    Cache.applicationProperties.setProperty("TRIM_TERMINI",
+    Cache.applicationProperties.setProperty(HMMALIGN_TRIM_TERMINI,
             Boolean.toString(hmmrTrimTermini.isSelected()));
-    Cache.applicationProperties.setProperty("USE_UNIPROT",
+    Cache.applicationProperties.setProperty(HMMINFO_GLOBAL_BACKGROUND,
             Boolean.toString(hmmerBackgroundUniprot.isSelected()));
-    Cache.applicationProperties.setProperty("SEQUENCES_TO_KEEP",
+    Cache.applicationProperties.setProperty(HMMSEARCH_SEQCOUNT,
             hmmerSequenceCount.getText());
-    Cache.applicationProperties.setProperty(HMMER_PATH,
-            hmmerPath.getText());
+    Cache.setOrRemove(HMMER_PATH, hmmerPath.getText());
+    if (cygwinPath != null)
+    {
+      Cache.setOrRemove(CYGWIN_PATH, cygwinPath.getText());
+    }
     AlignFrame[] frames = Desktop.getAlignFrames();
     if (frames != null && frames.length > 0)
     {
@@ -723,8 +761,8 @@ public class Preferences extends GPreferences
       }
     }
     
-    hmmrTrimTermini.setSelected(Cache.getDefault("TRIM_TERMINI", false));
-    if (Cache.getDefault("USE_UNIPROT", false))
+    hmmrTrimTermini.setSelected(Cache.getDefault(HMMALIGN_TRIM_TERMINI, false));
+    if (Cache.getDefault(HMMINFO_GLOBAL_BACKGROUND, false))
     {
       hmmerBackgroundUniprot.setSelected(true);
     }
@@ -733,7 +771,7 @@ public class Preferences extends GPreferences
       hmmerBackgroundAlignment.setSelected(true);
     }
     hmmerSequenceCount
-            .setText(Cache.getProperty("SEQUENCES_TO_KEEP"));
+            .setText(Cache.getProperty(HMMSEARCH_SEQCOUNT));
     hmmerPath.setText(Cache.getProperty(HMMER_PATH));
 
     /*
@@ -1264,23 +1302,27 @@ public class Preferences extends GPreferences
   }
   
   /**
-   * Returns true if hmmer path is to a folder that contains an executable
-   * hmmbuild or hmmbuild.exe, else false (optionally after showing a warning
-   * dialog)
+   * Returns true if the given text field contains a path to a folder that
+   * contains an executable with the given name, else false (after showing a
+   * warning dialog). The executable name will be tried with .exe appended if not
+   * found.
+   * 
+   * @param textField
+   * @param executable
    */
-  @Override
-  protected boolean validateHMMERPath(boolean showWarning)
+  protected boolean validateExecutablePath(JTextField textField, String executable)
   {
-    String folder = hmmerPath.getText().trim();
+    String folder = textField.getText().trim();
 
-    if (HmmerCommand.getExecutable(HmmerCommand.HMMBUILD, folder) != null)
+    if (FileUtils.getExecutable(executable, folder) != null)
     {
       return true;
     }
-    if (showWarning && folder.length() > 0)
+    if (folder.length() > 0)
     {
       JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-              MessageManager.getString("label.hmmbuild_not_found"),
+              MessageManager.formatMessage("label.executable_not_found",
+                      executable),
               MessageManager.getString("label.invalid_folder"),
               JvOptionPane.ERROR_MESSAGE);
     }
@@ -1357,6 +1399,18 @@ public class Preferences extends GPreferences
     }
   }
 
+  @Override
+  protected void validateHmmerPath()
+  {
+    validateExecutablePath(hmmerPath, HmmerCommand.HMMBUILD);
+  }
+
+  @Override
+  protected void validateCygwinPath()
+  {
+    validateExecutablePath(cygwinPath, "run");
+  }
+
   public class OptionsParam
   {
     private String name;
index af52d43..8377a16 100644 (file)
@@ -50,7 +50,6 @@ import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
-import java.net.URL;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
@@ -63,7 +62,6 @@ import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
 import javax.swing.JTextArea;
 import javax.swing.border.TitledBorder;
 import javax.swing.event.DocumentEvent;
@@ -74,7 +72,6 @@ import compbio.metadata.Option;
 import compbio.metadata.Parameter;
 import compbio.metadata.Preset;
 import compbio.metadata.PresetManager;
-import compbio.metadata.RunnerConfig;
 import net.miginfocom.swing.MigLayout;
 
 /**
@@ -95,36 +92,33 @@ import net.miginfocom.swing.MigLayout;
 public class WsJobParameters extends JPanel implements ItemListener,
         ActionListener, DocumentListener, OptsParametersContainerI
 {
-  URL linkImageURL = getClass().getResource("/images/link.gif");
+  private static final int PREFERRED_WIDTH = 540;
 
-  private static final String SVC_DEF = "Defaults"; // this is the null
-                                                    // parameter set as shown to
-                                                    // user
+  private static final int DEFAULT_HEIGHT = 640;
 
-  /**
-   * manager for options and parameters.
+  // the default parameter set shown to the user
+  private static final String SVC_DEF = "Defaults";
+
+  private int maxOptWidth = 200;
+
+  // URL linkImageURL = getClass().getResource("/images/link.gif");
+
+  /*
+   * controller for options and parameters layout
    */
-  OptsAndParamsPage opanp = new OptsAndParamsPage(this);
+  OptsAndParamsPage opanp;
 
-  /**
+  /*
    * panel containing job options
    */
-  JPanel jobOptions = new JPanel();
+  JPanel optionsPanel = new JPanel();
 
-  /**
+  /*
    * panel containing job parameters
    */
-  JPanel paramList = new JPanel();
-
-  JPanel SetNamePanel = new JPanel();
-
-  JPanel setDetails = new JPanel();
-
-  JSplitPane settingsPanel = new JSplitPane();
+  JPanel paramsPanel = new JPanel();
 
-  JPanel jobPanel = new JPanel();
-
-  JScrollPane jobOptionsPane = new JScrollPane();
+  JPanel setNamePanel = new JPanel();
 
   JButton createpref = new JButton();
 
@@ -134,96 +128,80 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   JButton updatepref = new JButton();
 
-  JButton startjob = new JButton();
-
-  JButton canceljob = new JButton();
-
-  JComboBox setName = new JComboBox();
+  JComboBox<String> setName = new JComboBox<>();
 
   JTextArea setDescr = new JTextArea();
 
   JScrollPane paramPane = new JScrollPane();
 
-  // ScrollablePanel optsAndparams = new ScrollablePanel();
-  JPanel optsAndparams = new JPanel();
+  ParamDatastoreI paramStore;
 
-  RunnerConfig serviceOptions;
+  // set true when 'Start Job' is clicked
+  boolean startJob = false;
 
-  ParamDatastoreI paramStore;
+  JDialog frame = null;
 
-  private int MAX_OPTWIDTH = 200;
+  Jws2Instance service;
 
-  WsJobParameters(Jws2Instance service)
-  {
-    this(service, null);
-  }
+  /*
+   * list of service presets in the gui
+   */
+  Hashtable<String, String> servicePresets = null;
+
+  /*
+   * set if dialog is being set - so handlers will avoid spurious events
+   */
+  boolean settingDialog = false;
 
-  public WsJobParameters(JFrame parent, ParamDatastoreI store,
-          WsParamSetI preset,
+  private Hashtable<Object, Object> modifiedElements = new Hashtable<>();
+
+  String lastParmSet = null;
+
+  public WsJobParameters(ParamDatastoreI store, WsParamSetI preset,
           List<ArgumentI> args)
   {
     super();
+
+    // parameters dialog in 'compact' format (help as tooltips)
+    opanp = new OptsAndParamsPage(this, true);
     jbInit();
     this.paramStore = store;
     this.service = null;
-    // argSetModified(false);
-    // populate parameter table
     init(preset, args);
-    // display in new JFrame attached to parent.
     validate();
   }
 
-  public WsJobParameters(Jws2Instance service, WsParamSetI preset)
-  {
-    this(null, service, preset, null);
-  }
-
-  /**
-   * 
-   * @param desktop
-   *          - if null, create new JFrame outside of desktop
-   * @param service
-   * @param preset
-   */
-  public WsJobParameters(JFrame parent, Jws2Instance service,
-          WsParamSetI preset, List<Argument> jobArgset)
-  {
-    this(parent, null, service, preset, jobArgset);
-  }
-
   /**
+   * Constructor given a set of parameters and presets, a service to be invoked,
+   * and a list of (Jabaws client) arguments
    * 
-   * @param parent
    * @param paramStorei
    * @param service
    * @param preset
    * @param jobArgset
    */
-  public WsJobParameters(JFrame parent, ParamDatastoreI paramStorei,
-          Jws2Instance service, WsParamSetI preset,
-          List<Argument> jobArgset)
+  public WsJobParameters(ParamDatastoreI paramStorei, Jws2Instance service,
+          WsParamSetI preset, List<Argument> jobArgset)
   {
     super();
+
+    // parameters dialog in 'expanded' format (help text boxes)
+    opanp = new OptsAndParamsPage(this, false);
+
     jbInit();
     this.paramStore = paramStorei;
-    if (paramStore == null)
+    if (paramStore == null && service != null)
     {
       paramStore = service.getParamStore();
     }
     this.service = service;
-    // argSetModified(false);
-    // populate parameter table
-    initForService(service, preset, jobArgset);
-    // display in new JFrame attached to parent.
+    initForService(preset, jobArgset);
     validate();
   }
 
-  int response = -1;
-
-  JDialog frame = null;
-
   /**
-   * shows a modal dialog containing the parameters.
+   * Shows a modal dialog containing the parameters and Start or Cancel options.
+   * Answers true if the job is started, false if cancelled.
    * 
    * @return
    */
@@ -260,11 +238,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     });
     frame.setVisible(true);
 
-    if (response > 0)
-    {
-      return true;
-    }
-    return false;
+    return startJob;
   }
 
   private void jbInit()
@@ -294,7 +268,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                update_actionPerformed(e);
+                update_actionPerformed();
               }
             });
     deletepref = JvSwingUtils.makeButton(
@@ -306,7 +280,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                delete_actionPerformed(e);
+                delete_actionPerformed();
               }
             });
     createpref = JvSwingUtils.makeButton(
@@ -318,7 +292,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                create_actionPerformed(e);
+                create_actionPerformed();
               }
             });
     revertpref = JvSwingUtils.makeButton(
@@ -331,10 +305,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                revert_actionPerformed(e);
+                revert_actionPerformed();
               }
             });
-    startjob = JvSwingUtils.makeButton(
+
+    JButton startjob = JvSwingUtils.makeButton(
             MessageManager.getString("action.start_job"),
             MessageManager.getString("label.start_job_current_settings"),
             new ActionListener()
@@ -342,10 +317,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                startjob_actionPerformed(e);
+                startjob_actionPerformed();
               }
             });
-    canceljob = JvSwingUtils.makeButton(
+    JButton canceljob = JvSwingUtils.makeButton(
             MessageManager.getString("action.cancel_job"),
             MessageManager.getString("label.cancel_job_close_dialog"),
             new ActionListener()
@@ -353,10 +328,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                canceljob_actionPerformed(e);
+                canceljob_actionPerformed();
               }
             });
 
+    JPanel setDetails = new JPanel();
     setDetails.setBorder(
             new TitledBorder(MessageManager.getString("label.details")));
     setDetails.setLayout(new BorderLayout());
@@ -375,7 +351,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     setName.getEditor().addActionListener(this);
     JPanel setNameInfo = new JPanel(new FlowLayout(FlowLayout.LEFT));
     GridBagLayout gbl = new GridBagLayout();
-    SetNamePanel.setLayout(gbl);
+    setNamePanel.setLayout(gbl);
 
     JLabel setNameLabel = new JLabel(
             MessageManager.getString("label.current_parameter_set_name"));
@@ -390,9 +366,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     revertpref.setVisible(false);
     createpref.setVisible(false);
     JPanel setsavebuts = new JPanel();
-    setsavebuts.setLayout(new FlowLayout(FlowLayout.LEFT)); // GridLayout(1,2));
-    ((FlowLayout) setsavebuts.getLayout()).setHgap(10);
-    ((FlowLayout) setsavebuts.getLayout()).setVgap(0);
+    setsavebuts.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0)); // GridLayout(1,2));
     JPanel spacer = new JPanel();
     spacer.setPreferredSize(new Dimension(2, 30));
     setsavebuts.add(spacer);
@@ -403,11 +377,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
     // setsavebuts.setSize(new Dimension(150, 30));
     JPanel buttonArea = new JPanel(new GridLayout(1, 1));
     buttonArea.add(setsavebuts);
-    SetNamePanel.add(setNameInfo);
+    setNamePanel.add(setNameInfo);
     GridBagConstraints gbc = new GridBagConstraints();
     gbc.gridheight = 2;
     gbl.setConstraints(setNameInfo, gbc);
-    SetNamePanel.add(buttonArea);
+    setNamePanel.add(buttonArea);
     gbc = new GridBagConstraints();
     gbc.gridx = 0;
     gbc.gridy = 2;
@@ -417,36 +391,33 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
     // paramPane.setPreferredSize(new Dimension(360, 400));
     // paramPane.setPreferredSize(null);
-    jobOptions.setBorder(
+    optionsPanel.setBorder(
             new TitledBorder(MessageManager.getString("label.options")));
-    jobOptions.setOpaque(true);
-    paramList.setBorder(
+    optionsPanel.setOpaque(true);
+    paramsPanel.setBorder(
             new TitledBorder(MessageManager.getString("label.parameters")));
-    paramList.setOpaque(true);
-    JPanel bjo = new JPanel(new BorderLayout()),
-            bjp = new JPanel(new BorderLayout());
-    bjo.add(jobOptions, BorderLayout.CENTER);
-    bjp.add(paramList, BorderLayout.CENTER);
-    bjp.setOpaque(true);
-    bjo.setOpaque(true);
+    paramsPanel.setOpaque(true);
     // optsAndparams.setScrollableWidth(ScrollableSizeHint.FIT);
     // optsAndparams.setScrollableHeight(ScrollableSizeHint.NONE);
     // optsAndparams.setLayout(new BorderLayout());
+    JPanel optsAndparams = new JPanel();
     optsAndparams.setLayout(new BorderLayout());
-    optsAndparams.add(jobOptions, BorderLayout.NORTH);
-    optsAndparams.add(paramList, BorderLayout.CENTER);
+    optsAndparams.add(optionsPanel, BorderLayout.NORTH);
+    optsAndparams.add(paramsPanel, BorderLayout.CENTER);
     JPanel jp = new JPanel(new BorderLayout());
     jp.add(optsAndparams, BorderLayout.CENTER);
     paramPane.getViewport().setView(jp);
     paramPane.setBorder(null);
     setLayout(new BorderLayout());
+
+    JPanel jobPanel = new JPanel();
     jobPanel.setPreferredSize(null);
     jobPanel.setLayout(new BorderLayout());
     jobPanel.add(setDetails, BorderLayout.NORTH);
     jobPanel.add(paramPane, BorderLayout.CENTER);
     // jobPanel.setOrientation(JSplitPane.VERTICAL_SPLIT);
 
-    add(SetNamePanel, BorderLayout.NORTH);
+    add(setNamePanel, BorderLayout.NORTH);
     add(jobPanel, BorderLayout.CENTER);
 
     JPanel dialogpanel = new JPanel();
@@ -454,20 +425,20 @@ public class WsJobParameters extends JPanel implements ItemListener,
     dialogpanel.add(canceljob);
     // JAL-1580: setMaximumSize() doesn't work, so just size for the worst case:
     // check for null is for JUnit usage
-    final int windowHeight = Desktop.instance == null ? 540
+    final int windowHeight = Desktop.instance == null ? DEFAULT_HEIGHT
             : Desktop.instance.getHeight();
-    setPreferredSize(new Dimension(540, windowHeight));
+    // setPreferredSize(new Dimension(PREFERRED_WIDTH, windowHeight));
     add(dialogpanel, BorderLayout.SOUTH);
     validate();
   }
 
-  protected void revert_actionPerformed(ActionEvent e)
+  protected void revert_actionPerformed()
   {
     reInitDialog(lastParmSet);
     updateWebServiceMenus();
   }
 
-  protected void update_actionPerformed(ActionEvent e)
+  protected void update_actionPerformed()
   {
     if (isUserPreset)
     {
@@ -485,7 +456,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     paramStore.deletePreset(lastParmSet2);
   }
 
-  protected void delete_actionPerformed(ActionEvent e)
+  protected void delete_actionPerformed()
   {
     if (isUserPreset)
     {
@@ -496,7 +467,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     updateWebServiceMenus();
   }
 
-  protected void create_actionPerformed(ActionEvent e)
+  protected void create_actionPerformed()
   {
     String curname = ((String) setName.getSelectedItem()).trim();
     if (curname.length() > 0)
@@ -515,38 +486,25 @@ public class WsJobParameters extends JPanel implements ItemListener,
     }
   }
 
-  protected void canceljob_actionPerformed(ActionEvent e)
+  protected void canceljob_actionPerformed()
   {
-    response = 0;
+    startJob = false;
     if (frame != null)
     {
       frame.setVisible(false);
     }
   }
 
-  protected void startjob_actionPerformed(ActionEvent e)
+  protected void startjob_actionPerformed()
   {
-    response = 1;
+    startJob = true;
     if (frame != null)
     {
       frame.setVisible(false);
     }
   }
 
-  Jws2Instance service;
-
-  /**
-   * list of service presets in the gui
-   */
-  Hashtable servicePresets = null;
-
-  /**
-   * set if dialog is being set - so handlers will avoid spurious events
-   */
-  boolean settingDialog = false;
-
-  void initForService(Jws2Instance service, WsParamSetI jabap,
-          List<Argument> jabajobArgset)
+  void initForService(WsParamSetI jabap, List<Argument> jabajobArgset)
   {
     WsParamSetI p = null;
     List<ArgumentI> jobArgset = null;
@@ -564,12 +522,12 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   void init(WsParamSetI p, List<ArgumentI> jobArgset)
   {
-    Hashtable exnames = new Hashtable();
+    Hashtable<String, String> exnames = new Hashtable<>();
     for (int i = 0, iSize = setName.getItemCount(); i < iSize; i++)
     {
       exnames.put(setName.getItemAt(i), setName.getItemAt(i));
     }
-    servicePresets = new Hashtable();
+    servicePresets = new Hashtable<>();
     // Add the default entry - if not present already.
     if (!exnames.contains(SVC_DEF))
     {
@@ -577,7 +535,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
       exnames.put(SVC_DEF, SVC_DEF);
       servicePresets.put(SVC_DEF, SVC_DEF);
     }
-    String curname = (p == null ? "" : p.getName());
+
+    // String curname = (p == null ? "" : p.getName());
     for (WsParamSetI pr : paramStore.getPresets())
     {
       if (!pr.isModifiable())
@@ -619,7 +578,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     settingDialog = false;
   }
 
-  @SuppressWarnings("unchecked")
   private void updateTable(WsParamSetI p, List<ArgumentI> jobArgset)
   {
     boolean setDefaultParams = false;
@@ -656,9 +614,9 @@ public class WsJobParameters extends JPanel implements ItemListener,
             OptionI opt = (OptionI) myarg;
             OptionBox ob = opanp.addOption(opt);
             ob.resetToDefault(setDefaultParams);
-            if (MAX_OPTWIDTH < ob.getPreferredSize().width)
+            if (maxOptWidth < ob.getPreferredSize().width)
             {
-              MAX_OPTWIDTH = ob.getPreferredSize().width;
+              maxOptWidth = ob.getPreferredSize().width;
             }
             ob.validate();
             cw += ob.getPreferredSize().width + 5;
@@ -727,8 +685,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     return modifiedElements.size() > 0;
   }
 
-  private Hashtable modifiedElements = new Hashtable();
-
   /**
    * reset gui and modification state settings
    */
@@ -793,7 +749,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     if (b && modifiedElements.size() > 0)
     {
       makeSetNameValid(!isUserPreset);
-      SetNamePanel.revalidate();
+      setNamePanel.revalidate();
     }
     updateButtonDisplay();
   }
@@ -840,7 +796,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     // sync the gui with the preset database
     for (int i = 0, iS = setName.getItemCount(); i < iS; i++)
     {
-      String snm = (String) setName.getItemAt(i);
+      String snm = setName.getItemAt(i);
       if (snm.equals(nm))
       {
         makeupdate = true;
@@ -860,96 +816,88 @@ public class WsJobParameters extends JPanel implements ItemListener,
     settingDialog = stn;
   }
 
+  /**
+   * Rebuilds the Options and Parameters panels
+   */
   @Override
   public void refreshParamLayout()
   {
-    // optsAndparams.setPreferredSize(null);
-    FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
-    int sep = fl.getVgap();
-    boolean fh = true;
-    int os = 0,
-            s = jobOptions.getBorder().getBorderInsets(jobOptions).bottom
-                    + jobOptions.getBorder().getBorderInsets(jobOptions).top
-                    + 2 * sep;
-    /**
-     * final height for viewport
-     */
-    int finalh = s;
-    int panewidth = paramPane.getViewport().getSize().width - 120
-            - jobOptions.getBorder().getBorderInsets(jobOptions).left
-            + jobOptions.getBorder().getBorderInsets(jobOptions).right;
-
-    int w = 2 * fl.getHgap()
-            + (MAX_OPTWIDTH > OptsAndParamsPage.PARAM_WIDTH ? MAX_OPTWIDTH
-                    : OptsAndParamsPage.PARAM_WIDTH);
-    int hgap = fl.getHgap(), cw = hgap;
+    final int rightMargin = 40;
+    final int availableWidth = paramPane.getViewport().getSize().width
+            - rightMargin
+            - optionsPanel.getBorder().getBorderInsets(optionsPanel).left
+            + optionsPanel.getBorder().getBorderInsets(optionsPanel).right;
 
     if (opanp.getOptSet().size() > 0)
     {
+      int hgap = 5;
+      int currentWidth = hgap;
 
-      jobOptions.setLayout(new MigLayout("", "", ""));
-      jobOptions.removeAll();
+      /*
+       * layout constraint 'nogrid' prevents vertical column alignment,
+       * allowing controls to flow without extra space inserted to align
+       */
+      optionsPanel.setLayout(new MigLayout("nogrid", "", ""));
+      optionsPanel.removeAll();
+      JPanel lastAdded = null;
 
+      /*
+       * add each control in turn; if adding would overflow the right margin,
+       * remove and re-add the previous parameter with "wrap" (after) 
+       * in order to start a new row
+       */
       for (OptionBox pbox : opanp.getOptSet().values())
       {
         pbox.validate();
-        cw += pbox.getSize().width + hgap;
-        if (cw + 120 > panewidth)
-        {
-          jobOptions.add(pbox, "wrap");
-          // System.out.println("Wrap on "+pbox.option.getName());
-          cw = hgap + pbox.getSize().width;
-          fh = true;
-        }
-        else
-        {
-          jobOptions.add(pbox);
-        }
-        if (fh)
+        int boxWidth = pbox.getSize().width;
+        currentWidth += boxWidth + hgap;
+        boolean wrapAfterLast = currentWidth > availableWidth
+                && lastAdded != null;
+        // System.out.println(String.format(
+        // "%s width=%d, paneWidth=%d, currentWidth=%d, wrapAfterLast=%s",
+        // pbox.toString(), boxWidth, panewidth, currentWidth,
+        // wrapAfterLast));
+        if (wrapAfterLast)
         {
-          finalh += pbox.getSize().height + fl.getVgap();
-          fh = false;
+          optionsPanel.remove(lastAdded);
+          optionsPanel.add(lastAdded, "wrap");
+          currentWidth = hgap + boxWidth;
         }
+        optionsPanel.add(pbox);
+        lastAdded = pbox;
       }
-      jobOptions.revalidate();
+      optionsPanel.revalidate();
     }
     else
     {
-      jobOptions.setVisible(false);
+      optionsPanel.setVisible(false);
     }
 
-    // Now layout the parameters assuming they occupy one column - to calculate
-    // total height of options+parameters
-    fl = new FlowLayout(FlowLayout.LEFT);
-    // helpful hint from
-    // http://stackoverflow.com/questions/2743177/top-alignment-for-flowlayout
-    fl.setAlignOnBaseline(true);
     if (opanp.getParamSet().size() > 0)
     {
-      paramList.removeAll();
-      paramList.setLayout(new MigLayout("", "", ""));
-      fh = true;
+      paramsPanel.removeAll();
+      paramsPanel.setLayout(new MigLayout("", "", ""));
+      int hgap = 5;
+      int currentWidth = hgap;
+
+      JPanel lastAdded = null;
       for (ParamBox pbox : opanp.getParamSet().values())
       {
         pbox.validate();
-        cw += pbox.getSize().width + hgap;
-        if (cw + 160 > panewidth)
-        {
-          paramList.add(pbox, "wrap");
-          cw = pbox.getSize().width + hgap;
-          fh = true;
-        }
-        else
+        int boxWidth = pbox.getSize().width;
+        currentWidth += boxWidth + hgap;
+        boolean wrapAfterLast = currentWidth > availableWidth
+                && lastAdded != null;
+        if (wrapAfterLast)
         {
-          paramList.add(pbox);
+          paramsPanel.remove(lastAdded);
+          paramsPanel.add(lastAdded, "wrap");
+          currentWidth = pbox.getSize().width + hgap;
         }
-        if (fh)
-        {
-          finalh += pbox.getSize().height + fl.getVgap();
-          fh = false;
-        }
-
+        paramsPanel.add(pbox);
+        lastAdded = pbox;
       }
+
       /*
        * s = 2 * sep; for (ParamBox pbox : opanp.getParamSet().values()) {
        * pbox.validate(); s += sep +
@@ -961,11 +909,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
        * .getBorder().getBorderInsets(paramList).bottom+paramList
        * .getBorder().getBorderInsets(paramList).top;
        */
-      paramList.revalidate();
+      paramsPanel.revalidate();
     }
     else
     {
-      paramList.setVisible(false);
+      paramsPanel.setVisible(false);
     }
     // TODO: waste some time trying to eliminate any unnecessary .validate calls
     // here
@@ -1130,8 +1078,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
                 e.printStackTrace();
               }
             }
-            WsJobParameters pgui = new WsJobParameters(lastserv,
-                    new JabaPreset(lastserv, pr));
+            WsJobParameters pgui = new WsJobParameters(null, lastserv,
+                    new JabaPreset(lastserv, pr), null);
             JFrame jf = new JFrame(MessageManager
                     .formatMessage("label.ws_parameters_for", new String[]
                     { lastserv.getActionText() }));
@@ -1225,8 +1173,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     return opanp.getCurrentSettings();
   }
 
-  String lastParmSet = null;
-
   /*
    * Hashtable<String, Object[]> editedParams = new Hashtable<String,
    * Object[]>();
@@ -1266,10 +1212,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
     int n = 0;
     // remove any set names in the drop down menu that aren't either a reserved
     // setting, or a user defined or service preset.
-    Vector items = new Vector();
+    Vector<String> items = new Vector<>();
     while (n < setName.getItemCount())
     {
-      String item = (String) setName.getItemAt(n);
+      String item = setName.getItemAt(n);
       if (!item.equals(SVC_DEF) && !paramStore.presetExists(item))
       {
         setName.removeItemAt(n);
@@ -1337,7 +1283,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     initArgSetModified();
     syncSetNamesWithStore();
     setName.setSelectedItem(lastParmSet);
-    SetNamePanel.validate();
+    setNamePanel.validate();
     validate();
     settingDialog = false;
   }
@@ -1359,7 +1305,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
   @Override
   public void itemStateChanged(ItemEvent e)
   {
-    if (e.getSource() == setName && e.getStateChange() == e.SELECTED)
+    if (e.getSource() == setName
+            && e.getStateChange() == ItemEvent.SELECTED)
     {
       final String setname = (String) setName.getSelectedItem();
       // System.out.println("Item state changed for " + setname
index 44828aa..b5f047e 100644 (file)
@@ -14,6 +14,7 @@ import jalview.gui.JvOptionPane;
 import jalview.gui.SplitFrame;
 import jalview.io.DataSourceType;
 import jalview.io.StockholmFile;
+import jalview.util.FileUtils;
 import jalview.util.MessageManager;
 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
 import jalview.ws.params.ArgumentI;
@@ -63,12 +64,7 @@ public class HMMAlign extends HmmerCommand
   @Override
   public void run()
   {
-    HiddenMarkovModel hmm = af.getSelectedHMM();
-    if (hmm == null)
-    {
-      System.err.println("Can't run hmmalign as no HMM profile selected");
-      return;
-    }
+    HiddenMarkovModel hmm = getHmmProfile();
 
     long msgId = System.currentTimeMillis();
     af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
@@ -86,9 +82,9 @@ public class HMMAlign extends HmmerCommand
       Hashtable sequencesHash = stashSequences(seqs);
       try
       {
-        File modelFile = createTempFile("hmm", ".hmm");
-        File alignmentFile = createTempFile("output", ".sto");
-        File resultFile = createTempFile("input", ".sto");
+        File modelFile = FileUtils.createTempFile("hmm", ".hmm");
+        File alignmentFile = FileUtils.createTempFile("output", ".sto");
+        File resultFile = FileUtils.createTempFile("input", ".sto");
 
         exportStockholm(seqs, alignmentFile.getAbsoluteFile(), null);
         exportHmm(hmm, modelFile.getAbsoluteFile());
@@ -96,8 +92,8 @@ public class HMMAlign extends HmmerCommand
         boolean ran = runCommand(modelFile, alignmentFile, resultFile);
         if (!ran)
         {
-          JvOptionPane.showInternalMessageDialog(af,
-                  MessageManager.getString("warn.hmmalign_failed"));
+          JvOptionPane.showInternalMessageDialog(af, MessageManager
+                  .formatMessage("warn.command_failed", "hmmalign"));
           return;
         }
 
@@ -156,9 +152,9 @@ public class HMMAlign extends HmmerCommand
       }
     }
     args.add("-o");
-    args.add(resultFile.getAbsolutePath());
-    args.add(modelFile.getAbsolutePath());
-    args.add(alignmentFile.getAbsolutePath());
+    args.add(getFilePath(resultFile));
+    args.add(getFilePath(modelFile));
+    args.add(getFilePath(alignmentFile));
     
     return runCommand(args);
   }
@@ -176,7 +172,7 @@ public class HMMAlign extends HmmerCommand
   private SequenceI[] importData(File resultFile,
           List<AlignmentOrder> allOrders) throws IOException
   {
-    StockholmFile file = new StockholmFile(resultFile.getAbsolutePath(),
+    StockholmFile file = new StockholmFile(getFilePath(resultFile),
             DataSourceType.FILE);
     SequenceI[] result = file.getSeqsAsArray();
     AlignmentOrder msaorder = new AlignmentOrder(result);
@@ -211,14 +207,6 @@ public class HMMAlign extends HmmerCommand
       al.setDataset(dataset);
     }
 
-    /*
-     * hack to ensure hmm set on alignment
-     */
-    if (al.getSequenceAt(0).isHMMConsensusSequence())
-    {
-      al.setHmmConsensus(al.getSequenceAt(0));
-    }
-
     displayInNewFrame(al, allOrders, hidden, title);
   }
 
index d95be48..3c3bd40 100644 (file)
@@ -12,6 +12,7 @@ import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
 import jalview.io.FileParse;
 import jalview.io.HMMFile;
+import jalview.util.FileUtils;
 import jalview.util.MessageManager;
 import jalview.ws.params.ArgumentI;
 
@@ -147,8 +148,8 @@ public class HMMBuild extends HmmerCommand
     File alignmentFile = null;
     try
     {
-      hmmFile = createTempFile("hmm", ".hmm");
-      alignmentFile = createTempFile("output", ".sto");
+      hmmFile = FileUtils.createTempFile("hmm", ".hmm");
+      alignmentFile = FileUtils.createTempFile("output", ".sto");
 
       if (ac instanceof Alignment)
       {
@@ -187,6 +188,8 @@ public class HMMBuild extends HmmerCommand
       boolean ran = runCommand(alignmentFile, hmmFile, ac);
       if (!ran)
       {
+        JvOptionPane.showInternalMessageDialog(af, MessageManager
+                .formatMessage("warn.command_failed", "hmmbuild"));
         return;
       }
       importData(hmmFile, ac);
@@ -214,8 +217,8 @@ public class HMMBuild extends HmmerCommand
    */
   void deleteHmmSequences(AnnotatedCollectionI ac)
   {
-    SequenceI hmmSeq = ac.getHmmConsensus();
-    if (hmmSeq != null)
+    List<SequenceI> hmmSeqs = ac.getHmmSequences();
+    for (SequenceI hmmSeq : hmmSeqs)
     {
       if (ac instanceof SequenceGroup)
       {
@@ -311,8 +314,8 @@ public class HMMBuild extends HmmerCommand
       args.add(ARG_DNA);
     }
 
-    args.add(hmmFile.getAbsolutePath());
-    args.add(sequencesFile.getAbsolutePath());
+    args.add(getFilePath(hmmFile));
+    args.add(getFilePath(sequencesFile));
 
     return runCommand(args);
   }
@@ -330,10 +333,22 @@ public class HMMBuild extends HmmerCommand
   private void importData(File hmmFile, AnnotatedCollectionI ac)
           throws IOException
   {
+    if (hmmFile.length() == 0L)
+    {
+      Cache.log.error("Error: hmmbuild produced empty hmm file");
+      return;
+    }
+
     HMMFile file = new HMMFile(
             new FileParse(hmmFile.getAbsolutePath(), DataSourceType.FILE));
     SequenceI hmmSeq = file.getHMM().getConsensusSequence();
 
+    if (hmmSeq == null)
+    {
+      // hmmbuild failure not detected earlier
+      return;
+    }
+
     if (ac instanceof SequenceGroup)
     {
       SequenceGroup grp = (SequenceGroup) ac;
@@ -346,17 +361,10 @@ public class HMMBuild extends HmmerCommand
       alignment.insertSequenceAt(topIndex, hmmSeq);
       ac.setSeqrep(hmmSeq);
       grp.addSequence(hmmSeq, false);
-      grp.setHmmConsensus(hmmSeq);
     }
     else
     {
       alignment.insertSequenceAt(0, hmmSeq);
-      alignment.setHmmConsensus(hmmSeq);
-    }
-
-    if (af.getSelectedHMM() == null)
-    {
-      af.setSelectedHMMSequence(hmmSeq);
     }
   }
 }
index c668481..6f1f51f 100644 (file)
@@ -1,8 +1,10 @@
 package jalview.hmmer;
 
 import jalview.bin.Cache;
+import jalview.datamodel.SequenceI;
 import jalview.gui.Preferences;
 import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.ParamDatastoreI;
 import jalview.ws.params.WsParamSetI;
@@ -26,28 +28,31 @@ public final class HMMERParamStore implements ParamDatastoreI
 
   private static final String HMMSEARCH = "hmmsearch";
 
-  String name;
+  private String name;
 
-  List<WsParamSetI> presets = new ArrayList<>();
+  private List<WsParamSetI> presets = new ArrayList<>();
 
-  private HMMERParamStore(String nam)
+  private AlignmentViewport viewport;
+
+  private HMMERParamStore(String nam, AlignmentViewport av)
   {
+    this.viewport = av;
     this.name = nam;
   }
 
-  public static HMMERParamStore forBuild()
+  public static HMMERParamStore forBuild(AlignmentViewport viewport)
   {
-    return new HMMERParamStore(HMMBUILD);
+    return new HMMERParamStore(HMMBUILD, viewport);
   }
 
-  public static HMMERParamStore forAlign()
+  public static HMMERParamStore forAlign(AlignmentViewport viewport)
   {
-    return new HMMERParamStore(HMMALIGN);
+    return new HMMERParamStore(HMMALIGN, viewport);
   }
 
-  public static HMMERParamStore forSearch()
+  public static HMMERParamStore forSearch(AlignmentViewport viewport)
   {
-    return new HMMERParamStore(HMMSEARCH);
+    return new HMMERParamStore(HMMSEARCH, viewport);
   }
 
   @Override
@@ -83,8 +88,16 @@ public final class HMMERParamStore implements ParamDatastoreI
     return args;
   }
 
+  /**
+   * Answers default parameters for hmmsearch, taking into account any
+   * configured as user preferences
+   * 
+   * @param args
+   */
   private void getHMMSearchParams(List<ArgumentI> args)
   {
+    addChoiceOfHmm(args);
+
     args.add(new IntegerParameter(
             MessageManager.getString("label.number_of_results"),
             MessageManager.getString("label.number_of_results_desc"), true,
@@ -92,7 +105,7 @@ public final class HMMERParamStore implements ParamDatastoreI
     String names = Cache.getProperty(Preferences.HMMSEARCH_DBS);
     if (names != null && !names.isEmpty())
     {
-      Collection<String> databases = new ArrayList<>();
+      List<String> databases = new ArrayList<>();
       databases.add(MessageManager.getString("label.this_alignment"));
       Scanner nameScanner = new Scanner(names);
 
@@ -133,8 +146,8 @@ public final class HMMERParamStore implements ParamDatastoreI
             false, true, null));
     args.add(new LogarithmicParameter(
             MessageManager.getString("label.seq_e_value"),
-            MessageManager.getString("label.seq_e_value_desc"), false, -3d,
-            -37.92977945, 1d, 10d));
+            MessageManager.getString("label.seq_e_value_desc"), false, 1D,
+            1E-38, 10D, 10D));
     /*
     args.add(new DoubleParameter(
             MessageManager.getString("label.seq_score"),
@@ -142,9 +155,9 @@ public final class HMMERParamStore implements ParamDatastoreI
             0d, 0d, 10000d));
        */
     args.add(new LogarithmicParameter(
-            MessageManager.getString("label.dom_e_value_desc"),
-            MessageManager.getString("label.dom_e_value_desc"), false, -3d,
-            -37.92977945, 1d, 10d));
+            MessageManager.getString("label.dom_e_value"),
+            MessageManager.getString("label.dom_e_value_desc"), false, 1D,
+            1E-38, 10D, 10D));
     /*
     args.add(new DoubleParameter(
             MessageManager.getString("label.dom_score"),
@@ -154,30 +167,84 @@ public final class HMMERParamStore implements ParamDatastoreI
             */
   }
 
+  /**
+   * Answers default parameters for hmmalign, taking into account any configured
+   * as user preferences
+   * 
+   * @param args
+   */
   private void getHMMAlignParams(List<ArgumentI> args)
   {
+    addChoiceOfHmm(args);
+
+    boolean def = Cache.getDefault(Preferences.HMMALIGN_TRIM_TERMINI,
+            false);
     args.add(new BooleanOption(
             MessageManager.getString("label.trim_termini"),
             MessageManager.getString("label.trim_termini_desc"),
-            false, false, true, null));
+            false, false, def, null));
+  }
+
+  /**
+   * Adds an argument representing the choice of HMM sequences (profiles)
+   * against which to perform align or search, provided more than one is found
+   * 
+   * @param args
+   */
+  protected void addChoiceOfHmm(List<ArgumentI> args)
+  {
+    List<SequenceI> hmms = viewport.getAlignment().getHmmSequences();
+    if (!hmms.isEmpty())
+    {
+      List<String> options = new ArrayList<>();
+      for (SequenceI hmmSeq : hmms)
+      {
+        options.add(hmmSeq.getName());
+      }
+      String defseq = options.get(0);
+      Option option = new Option(MessageManager.getString("label.use_hmm"),
+              "", true, defseq, defseq, options, null);
+      args.add(option);
+    }
   }
 
+  /**
+   * Answers default parameters for hmmbuild, taking into account any configured
+   * as user preferences
+   * 
+   * @param args
+   */
   private void getHMMBuildParams(List<ArgumentI> args)
   {
-    args.add(new StringParameter(MessageManager.getString("label.hmm_name"),
-            MessageManager.getString("label.hmm_name_desc"), true, ""));
-    // todo only enable Use Reference Annotation if RF is present
-    args.add(new BooleanOption(
-            MessageManager.getString("label.use_reference"),
-            MessageManager.getString("label.use_reference_desc"), true,
-            true, true, null));
+    /*
+     * name to give the computed alignment HMM consensus sequence
+     * (Jalview constructs group HMM consensus sequence names)
+     */
+    String defValue = "Alignment_HMM";
+    StringParameter nameParam = new StringParameter(MessageManager.getString("label.hmm_name"),
+            MessageManager.getString("label.hmm_name_desc"), true, defValue,
+            defValue);
+    args.add(nameParam);
 
+    /*
+     * only enable Use Reference Annotation if RF is present
+     */
+    if (viewport.hasReferenceAnnotation())
+    {
+      args.add(new BooleanOption(
+              MessageManager.getString("label.use_reference"),
+              MessageManager.getString("label.use_reference_desc"), true,
+              true, true, null));
+    }
+
+    /*
+     * choice of whether to compute HMM for alignment and/or group(s)
+     */
     Collection<String> options = new ArrayList<>();
     options.add(MessageManager.getString("label.alignment"));
     options.add(MessageManager.getString("label.groups_and_alignment"));
     options.add(MessageManager.getString("label.groups"));
     options.add(MessageManager.getString("label.selected_group"));
-
     args.add(new Option(MessageManager.getString("label.hmmbuild_for"),
             MessageManager.getString("label.hmmbuild_for_desc"), true,
             MessageManager.getString("label.alignment"),
index 30299e9..d4c9656 100644 (file)
@@ -1,5 +1,6 @@
 package jalview.hmmer;
 
+import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
@@ -11,15 +12,18 @@ import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
 import jalview.io.FileParse;
 import jalview.io.StockholmFile;
+import jalview.util.FileUtils;
 import jalview.util.MessageManager;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.simple.BooleanOption;
+import jalview.ws.params.simple.Option;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Scanner;
 
@@ -27,6 +31,8 @@ import javax.swing.JOptionPane;
 
 public class HMMSearch extends HmmerCommand
 {
+  private static final String PARAMNAME_NO_OF_RESULTS = MessageManager.getString("label.number_of_results");
+
   static final String HMMSEARCH = "hmmsearch";
 
   boolean realign = false;
@@ -56,32 +62,34 @@ public class HMMSearch extends HmmerCommand
   @Override
   public void run()
   {
-    HiddenMarkovModel hmm = af.getSelectedHMM();
+    HiddenMarkovModel hmm = getHmmProfile();
     if (hmm == null)
     {
-      JOptionPane.showMessageDialog(af,
-              MessageManager.getString("warn.no_selected_hmm"));
+      // shouldn't happen if we got this far
+      Cache.log.error("Error: no hmm for hmmsearch");
       return;
     }
 
-    SequenceI hmmSeq = af.getSelectedHMMSequence();
+    SequenceI hmmSeq = hmm.getConsensusSequence();// af.getSelectedHMMSequence();
     long msgId = System.currentTimeMillis();
     af.setProgressBar(MessageManager.getString("status.running_hmmsearch"),
             msgId);
 
     try
     {
-      File hmmFile = createTempFile("hmm", ".hmm");
-      File hitsAlignmentFile = createTempFile("hitAlignment", ".sto");
-      File searchOutputFile = createTempFile("searchOutput", ".sto");
+      File hmmFile = FileUtils.createTempFile("hmm", ".hmm");
+      File hitsAlignmentFile = FileUtils.createTempFile("hitAlignment",
+              ".sto");
+      File searchOutputFile = FileUtils.createTempFile("searchOutput",
+              ".sto");
 
       exportHmm(hmm, hmmFile.getAbsoluteFile());
 
       boolean ran = runCommand(searchOutputFile, hitsAlignmentFile, hmmFile);
       if (!ran)
       {
-        JvOptionPane.showInternalMessageDialog(af,
-                MessageManager.getString("warn.hmmsearch_failed"));
+        JvOptionPane.showInternalMessageDialog(af, MessageManager
+                .formatMessage("warn.command_failed", "hmmsearch"));
         return;
       }
 
@@ -122,9 +130,9 @@ public class HMMSearch extends HmmerCommand
     List<String> args = new ArrayList<>();
     args.add(command);
     args.add("-o");
-    args.add(searchOutputFile.getAbsolutePath());
+    args.add(getFilePath(searchOutputFile));
     args.add("-A");
-    args.add(hitsAlignmentFile.getAbsolutePath());
+    args.add(getFilePath(hitsAlignmentFile));
 
     boolean dbFound = false;
     String dbPath = "";
@@ -152,7 +160,7 @@ public class HMMSearch extends HmmerCommand
         }
         else if (MessageManager.getString("label.seq_e_value").equals(name))
         {
-          args.add("--incE");
+          args.add("-E");
           args.add(arg.getValue());
         }
         else if (MessageManager.getString("label.seq_score").equals(name))
@@ -160,10 +168,10 @@ public class HMMSearch extends HmmerCommand
           args.add("-incT");
           args.add(arg.getValue());
         }
-        else if (MessageManager.getString("label.dom_e_value_desc")
+        else if (MessageManager.getString("label.dom_e_value")
                 .equals(name))
         {
-          args.add("--incdomE");
+          args.add("--domE");
           args.add(arg.getValue());
         }
         else if (MessageManager.getString("label.dom_score").equals(name))
@@ -194,15 +202,16 @@ public class HMMSearch extends HmmerCommand
     {
       /*
        * no external database specified for search, so
-       * export current alignment as 'database' to search
+       * export current alignment as 'database' to search,
+       * excluding any HMM consensus sequences it contains
        */
-      databaseFile = createTempFile("database", ".sto");
+      databaseFile = FileUtils.createTempFile("database", ".sto");
       AlignmentI al = af.getViewport().getAlignment();
       AlignmentI copy = new Alignment(al);
-      SequenceI hmms = copy.getHmmConsensus();
-      if (hmms != null)
+      List<SequenceI> hmms = copy.getHmmSequences();
+      for (SequenceI hmmSeq : hmms)
       {
-        copy.deleteSequence(hmms);
+        copy.deleteSequence(hmmSeq);
       }
       exportStockholm(copy.getSequencesArray(), databaseFile, null);
       // StockholmFile stoFile = new StockholmFile(copy);
@@ -213,8 +222,8 @@ public class HMMSearch extends HmmerCommand
       // writer.close();
     }
 
-    args.add(hmmFile.getAbsolutePath());
-    args.add(databaseFile.getAbsolutePath());
+    args.add(getFilePath(hmmFile));
+    args.add(getFilePath(databaseFile));
 
     return runCommand(args);
   }
@@ -250,10 +259,17 @@ public class HMMSearch extends HmmerCommand
       hmmAndSeqs[0] = hmmSeq;
       System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqCount);
 
-      AlignmentI alignment = new Alignment(hmmAndSeqs);
-      AlignFrame frame = new AlignFrame(alignment, 1, 1);
-      frame.setSelectedHMMSequence(hmmSeq);
+      /*
+       * and align the search results to the HMM profile
+       */
+      AlignmentI al = new Alignment(hmmAndSeqs);
+      AlignFrame frame = new AlignFrame(al, 1, 1);
       List<ArgumentI> alignArgs = new ArrayList<>();
+      String defSeq = hmmSeq.getName();
+      List<String> options = Collections.singletonList(defSeq);
+      Option option = new Option(MessageManager.getString("label.use_hmm"),
+              "", true, defSeq, defSeq, options, null);
+      alignArgs.add(option);
       if (trim)
       {
         alignArgs.add(new BooleanOption(
@@ -261,7 +277,7 @@ public class HMMSearch extends HmmerCommand
                 MessageManager.getString("label.trim_termini_desc"), true,
                 true, true, null));
       }
-      HMMAlign hmmalign = new HMMAlign(frame, alignArgs);
+      HmmerCommand hmmalign = new HMMAlign(frame, alignArgs);
       hmmalign.run();
       frame = null;
       hmmTemp.delete();
index fe6c0f9..f8f2cde 100644 (file)
@@ -14,7 +14,9 @@ import jalview.gui.JvOptionPane;
 import jalview.gui.Preferences;
 import jalview.io.HMMFile;
 import jalview.io.StockholmFile;
+import jalview.util.FileUtils;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 import jalview.ws.params.ArgumentI;
 
 import java.io.BufferedReader;
@@ -22,6 +24,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
 
@@ -63,7 +66,8 @@ public abstract class HmmerCommand implements Runnable
    */
   public static boolean isHmmerAvailable()
   {
-    File exec = getExecutable(HMMBUILD, Cache.getProperty(Preferences.HMMER_PATH));
+    File exec = FileUtils.getExecutable(HMMBUILD,
+            Cache.getProperty(Preferences.HMMER_PATH));
     return exec != null;
   }
 
@@ -93,16 +97,19 @@ public abstract class HmmerCommand implements Runnable
    * Runs a command as a separate process and waits for it to complete. Answers
    * true if the process return status is zero, else false.
    * 
-   * @param command
+   * @param commands
    *          the executable command and any arguments to it
    * @throws IOException
    */
-  public boolean runCommand(List<String> command)
+  public boolean runCommand(List<String> commands)
           throws IOException
   {
+    List<String> args = Platform.isWindows() ? wrapWithCygwin(commands)
+            : commands;
+
     try
     {
-      ProcessBuilder pb = new ProcessBuilder(command);
+      ProcessBuilder pb = new ProcessBuilder(args);
       pb.redirectErrorStream(true); // merge syserr to sysout
       final Process p = pb.start();
       new Thread(new Runnable()
@@ -128,7 +135,13 @@ public abstract class HmmerCommand implements Runnable
       }).start();
 
       p.waitFor();
-      return p.exitValue() == 0; // 0 is success, by convention
+      int exitValue = p.exitValue();
+      if (exitValue != 0)
+      {
+        Cache.log.error("Command failed, return code = " + exitValue);
+        Cache.log.error("Command/args were: " + args.toString());
+      }
+      return exitValue == 0; // 0 is success, by convention
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -137,6 +150,40 @@ public abstract class HmmerCommand implements Runnable
   }
 
   /**
+   * Converts the given command to a Cygwin "bash" command wrapper. The hmmer
+   * command and any arguments to it are converted into a single parameter to the
+   * bash command.
+   * 
+   * @param commands
+   */
+  protected List<String> wrapWithCygwin(List<String> commands)
+  {
+    File bash = FileUtils.getExecutable("bash",
+            Cache.getProperty(Preferences.CYGWIN_PATH));
+    if (bash == null)
+    {
+      Cache.log.error("Cygwin shell not found");
+      return commands;
+    }
+
+    List<String> wrapped = new ArrayList<>();
+    wrapped.add(bash.getAbsolutePath());
+    wrapped.add("-c");
+
+    /*
+     * combine hmmbuild/search/align and arguments to a single string
+     */
+    StringBuilder sb = new StringBuilder();
+    for (String cmd : commands)
+    {
+      sb.append(" ").append(cmd);
+    }
+    wrapped.add(sb.toString());
+
+    return wrapped;
+  }
+
+  /**
    * Exports an alignment, and reference (RF) annotation if present, to the
    * specified file, in Stockholm format
    * 
@@ -204,77 +251,84 @@ public abstract class HmmerCommand implements Runnable
   protected String getCommandPath(String cmd)
   {
     String binariesFolder = Cache.getProperty(Preferences.HMMER_PATH);
-    File file = getExecutable(cmd, binariesFolder);
+    File file = FileUtils.getExecutable(cmd, binariesFolder);
     if (file == null && af != null)
     {
-        JvOptionPane.showInternalMessageDialog(af,
-                MessageManager.getString("warn.hmm_command_failed"));
+      JvOptionPane.showInternalMessageDialog(af, MessageManager
+              .formatMessage("label.executable_not_found", cmd));
     }
 
-    return file == null ? null : file.getAbsolutePath();
+    return file == null ? null : getFilePath(file);
   }
 
   /**
-   * Answers the executable file for the given hmmer command, or null if not
-   * found or not executable. The path to the executable is the command name
-   * prefixed by the hmmer binaries folder path, optionally with .exe appended.
+   * Exports an HMM to the specified file
    * 
-   * @param cmd
-   *          hmmer command short name, for example hmmbuild
-   * @param binaryPath
-   *          parent folder containing hmmer executables
-   * @return
+   * @param hmm
+   * @param hmmFile
+   * @throws IOException
    */
-  public static File getExecutable(String cmd, String binaryPath)
+  public void exportHmm(HiddenMarkovModel hmm, File hmmFile)
+          throws IOException
   {
-    File file = new File(binaryPath, cmd);
-    if (!file.canExecute())
+    if (hmm != null)
     {
-      file = new File(binaryPath, cmd + ".exe");
-      {
-        if (!file.canExecute())
-        {
-          file = null;
-        }
-      }
+      HMMFile file = new HMMFile(hmm);
+      PrintWriter writer = new PrintWriter(hmmFile);
+      writer.print(file.print());
+      writer.close();
     }
-    return file;
   }
 
   /**
-   * A convenience method to create a temporary file that is deleted on exit of
-   * the JVM
+   * Answers the HMM profile for the profile sequence the user selected (default
+   * is just the first HMM sequence in the alignment)
    * 
-   * @param prefix
-   * @param suffix
    * @return
-   * @throws IOException
    */
-  protected File createTempFile(String prefix, String suffix)
-          throws IOException
+  protected HiddenMarkovModel getHmmProfile()
   {
-    File f = File.createTempFile(prefix, suffix);
-    f.deleteOnExit();
-    return f;
-
+    String alignToParamName = MessageManager.getString("label.use_hmm");
+    for (ArgumentI arg : params)
+    {
+      String name = arg.getName();
+      if (name.equals(alignToParamName))
+      {
+        String seqName = arg.getValue();
+        SequenceI hmmSeq = alignment.findName(seqName);
+        if (hmmSeq.hasHMMProfile())
+        {
+          return hmmSeq.getHMM();
+        }
+      }
+    }
+    return null;
   }
 
   /**
-   * Exports an HMM to the specified file
+   * Answers an absolute path to the given file, in a format suitable for
+   * processing by a hmmer command. On a Windows platform, the native Windows file
+   * path is converted to Cygwin format, by replacing '\'with '/' and drive letter
+   * X with /cygdrive/x.
    * 
-   * @param hmm
-   * @param hmmFile
-   * @throws IOException
+   * @param resultFile
+   * @return
    */
-  public void exportHmm(HiddenMarkovModel hmm, File hmmFile)
-          throws IOException
+  protected String getFilePath(File resultFile)
   {
-    if (hmm != null)
+    String path = resultFile.getAbsolutePath();
+    if (Platform.isWindows())
     {
-      HMMFile file = new HMMFile(hmm);
-      PrintWriter writer = new PrintWriter(hmmFile);
-      writer.print(file.print());
-      writer.close();
+      // the first backslash escapes '\' for the regular expression argument
+      path = path.replaceAll("\\" + File.separator, "/");
+      int colon = path.indexOf(':');
+      if (colon > 0)
+      {
+        String drive = path.substring(0, colon);
+        path = path.replaceAll(drive + ":", "/cygdrive/" + drive);
+      }
     }
+
+    return path;
   }
 }
index 2d753c1..798875f 100755 (executable)
@@ -425,14 +425,13 @@ public class FileLoader implements Runnable
               AlignmentI alignment = viewport.getAlignment();
               SequenceI seq = alignment
                       .getSequenceAt(alignment.getAbsoluteHeight() - 1);
-              if (seq.isHMMConsensusSequence())
+              if (seq.hasHMMProfile())
               {
                 /* 
                  * fudge: move HMM consensus sequence from last to first
                  */
                 alignment.deleteSequence(alignment.getAbsoluteHeight() - 1);
                 alignment.insertSequenceAt(0, seq);
-                alignment.setHmmConsensus(seq);
               }
               viewport.getAlignPanel().adjustAnnotationHeight();
               viewport.updateSequenceIdColours();
index 358298d..380db74 100755 (executable)
@@ -26,6 +26,7 @@ import jalview.fts.service.pdb.PDBFTSRestClient;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -47,11 +48,13 @@ import java.awt.event.MouseEvent;
 import javax.swing.AbstractButton;
 import javax.swing.AbstractCellEditor;
 import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
 import javax.swing.ButtonGroup;
 import javax.swing.DefaultListCellRenderer;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
+import javax.swing.JComponent;
 import javax.swing.JFileChooser;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
@@ -71,6 +74,8 @@ import javax.swing.event.ChangeListener;
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 
+import net.miginfocom.swing.MigLayout;
+
 /**
  * Base class for the Preferences panel.
  * 
@@ -272,17 +277,19 @@ public class GPreferences extends JPanel
   /*
    * hmmer tab and components
    */
-  protected JPanel hmmerTab = new JPanel();
+  protected JPanel hmmerTab;
+
+  protected JCheckBox hmmrTrimTermini;
 
-  protected JCheckBox hmmrTrimTermini = new JCheckBox();
+  protected AbstractButton hmmerBackgroundUniprot;
 
-  protected AbstractButton hmmerBackgroundUniprot = new JCheckBox();
+  protected AbstractButton hmmerBackgroundAlignment;
 
-  protected AbstractButton hmmerBackgroundAlignment = new JCheckBox();
+  protected JTextField hmmerSequenceCount;
 
-  protected JTextField hmmerSequenceCount = new JTextField();
+  protected JTextField hmmerPath;
 
-  protected JTextField hmmerPath = new JTextField();
+  protected JTextField cygwinPath;
 
   /*
    * DAS Settings tab
@@ -423,13 +430,23 @@ public class GPreferences extends JPanel
    */
   private JPanel initHMMERTab()
   {
-    hmmerTab.setLayout(null);
+    hmmerTab = new JPanel();
+    hmmerTab.setLayout(new BoxLayout(hmmerTab, BoxLayout.Y_AXIS));
+    hmmerTab.setLayout(new MigLayout("flowy"));
 
-    JLabel installationLocation = new JLabel(
+    /*
+     * path to hmmer binaries folder
+     */
+    JPanel installationPanel = new JPanel(new MigLayout("flowy"));
+    // new FlowLayout(FlowLayout.LEFT));
+    JvSwingUtils.createTitledBorder(installationPanel,
+            MessageManager.getString("label.installation"), true);
+    hmmerTab.add(installationPanel);
+    JLabel hmmerLocation = new JLabel(
             MessageManager.getString("label.hmmer_location"));
-    installationLocation.setFont(LABEL_FONT);
-    installationLocation.setBounds(new Rectangle(22, 10, 250, 23));
-    hmmerPath.setBounds(new Rectangle(22, 30, 300, 23));
+    hmmerLocation.setFont(LABEL_FONT);
+    final int pathFieldLength = 40;
+    hmmerPath = new JTextField(pathFieldLength);
     hmmerPath.addMouseListener(new MouseAdapter()
     {
       @Override
@@ -441,54 +458,95 @@ public class GPreferences extends JPanel
           if (chosen != null)
           {
             hmmerPath.setText(chosen);
+            validateHmmerPath();
           }
         }
       }
     });
+    installationPanel.add(hmmerLocation);
+    installationPanel.add(hmmerPath);
 
-    JLabel hmmalign = new JLabel(
-            MessageManager.getString("label.hmmalign_label"));
-    hmmalign.setFont(LABEL_FONT);
-    hmmalign.setBounds(new Rectangle(22, 50, 200, 23));
+    /*
+     * path to Cygwin binaries folder (for Windows)
+     */
+    if (Platform.isWindows())
+    {
+      JLabel cygwinLocation = new JLabel(
+              MessageManager.getString("label.cygwin_location"));
+      cygwinLocation.setFont(LABEL_FONT);
+      cygwinPath = new JTextField(pathFieldLength);
+      cygwinPath.addMouseListener(new MouseAdapter()
+      {
+        @Override
+        public void mouseClicked(MouseEvent e)
+        {
+          if (e.getClickCount() == 2)
+          {
+            String chosen = openFileChooser(true);
+            if (chosen != null)
+            {
+              cygwinPath.setText(chosen);
+              validateCygwinPath();
+            }
+          }
+        }
+      });
+      installationPanel.add(cygwinLocation);
+      installationPanel.add(cygwinPath);
+    }
 
+    /*
+     * preferences for hmmalign
+     */
+    JPanel alignOptionsPanel = new JPanel(new MigLayout());
+    // new FlowLayout(FlowLayout.LEFT));
+    JvSwingUtils.createTitledBorder(alignOptionsPanel,
+            MessageManager.getString("label.hmmalign_options"), true);
+    hmmerTab.add(alignOptionsPanel);
+    hmmrTrimTermini = new JCheckBox();
     hmmrTrimTermini.setFont(LABEL_FONT);
     hmmrTrimTermini.setText(MessageManager.getString("label.trim_termini"));
-    hmmrTrimTermini.setBounds(new Rectangle(22, 70, 200, 23));
-
-    JLabel hmmsearch = new JLabel(
-            MessageManager.getString("label.hmmsearch_label"));
-    hmmsearch.setFont(LABEL_FONT);
-    hmmsearch.setBounds(new Rectangle(22, 90, 200, 23));
+    alignOptionsPanel.add(hmmrTrimTermini);
 
+    /*
+     * preferences for hmmsearch
+     */
+    JPanel searchOptions = new JPanel(new MigLayout());
+    // FlowLayout(FlowLayout.LEFT));
+    JvSwingUtils.createTitledBorder(searchOptions,
+            MessageManager.getString("label.hmmsearch_options"), true);
+    hmmerTab.add(searchOptions);
     JLabel sequencesToKeep = new JLabel(
             MessageManager.getString("label.no_of_sequences"));
     sequencesToKeep.setFont(LABEL_FONT);
-    sequencesToKeep.setBounds(new Rectangle(22, 110, 125, 23));
-    hmmerSequenceCount.setBounds(new Rectangle(150, 110, 40, 23));
-
-    ButtonGroup backgroundFreqSource = new ButtonGroup();
-    backgroundFreqSource.add(hmmerBackgroundUniprot);
-    backgroundFreqSource.add(hmmerBackgroundAlignment);
-    backgroundFreqSource.setSelected(hmmerBackgroundUniprot.getModel(), true);
+    searchOptions.add(sequencesToKeep);
+    hmmerSequenceCount = new JTextField(5);
+    searchOptions.add(hmmerSequenceCount);
 
-    hmmerBackgroundUniprot.setText(MessageManager.getString("label.freq_uniprot"));
+    /*
+     * preferences for Information Content annotation
+     */
+    // JPanel dummy = new JPanel(new FlowLayout(FlowLayout.LEFT));
+    JPanel annotationOptions = new JPanel(new MigLayout("left"));
+    JvSwingUtils.createTitledBorder(annotationOptions,
+            MessageManager.getString("label.information_annotation"), true);
+    // dummy.add(annotationOptions);
+    hmmerTab.add(annotationOptions);
+    ButtonGroup backgroundOptions = new ButtonGroup();
+    hmmerBackgroundUniprot = new JRadioButton(
+            MessageManager.getString("label.freq_uniprot"));
     hmmerBackgroundUniprot.setFont(LABEL_FONT);
-    hmmerBackgroundUniprot.setBounds(new Rectangle(22, 130, 255, 23));
-
-    hmmerBackgroundAlignment.setText(MessageManager.getString("label.freq_alignment"));
+    hmmerBackgroundAlignment = new JRadioButton(
+            MessageManager.getString("label.freq_alignment"));
     hmmerBackgroundAlignment.setFont(LABEL_FONT);
-    hmmerBackgroundAlignment.setBounds(new Rectangle(22, 150, 300, 23));
-
-    hmmerTab.add(hmmerBackgroundUniprot);
-    hmmerTab.add(hmmerBackgroundAlignment);
-    hmmerTab.add(hmmalign);
-    hmmerTab.add(hmmsearch);
-    hmmerTab.add(installationLocation);
-    hmmerTab.add(hmmerPath);
-    hmmerTab.add(hmmrTrimTermini);
-    hmmerTab.add(sequencesToKeep);
-    hmmerTab.add(sequencesToKeep);
-    hmmerTab.add(hmmerSequenceCount);
+    backgroundOptions.add(hmmerBackgroundUniprot);
+    backgroundOptions.add(hmmerBackgroundAlignment);
+    backgroundOptions.setSelected(hmmerBackgroundUniprot.getModel(), true);
+    // disable buttons for now as annotation only uses Uniprot background
+    hmmerBackgroundAlignment.setEnabled(false);
+    hmmerBackgroundUniprot.setEnabled(false);
+    annotationOptions.add(hmmerBackgroundUniprot, "wrap");
+    annotationOptions.add(hmmerBackgroundAlignment);
 
     return hmmerTab;
   }
@@ -1046,7 +1104,7 @@ public class GPreferences extends JPanel
     protColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
     protColourLabel.setText(
             MessageManager.getString("label.prot_alignment_colour") + " ");
-    JvSwingUtils.addtoLayout(coloursTab,
+    GPreferences.addtoLayout(coloursTab,
             MessageManager
                     .getString("label.default_colour_scheme_for_alignment"),
             protColourLabel, protColour);
@@ -1058,7 +1116,7 @@ public class GPreferences extends JPanel
     nucColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
     nucColourLabel.setText(
             MessageManager.getString("label.nuc_alignment_colour") + " ");
-    JvSwingUtils.addtoLayout(coloursTab,
+    GPreferences.addtoLayout(coloursTab,
             MessageManager
                     .getString("label.default_colour_scheme_for_alignment"),
             nucColourLabel, nucColour);
@@ -1067,11 +1125,11 @@ public class GPreferences extends JPanel
     annotationShding.setBorder(new TitledBorder(
             MessageManager.getString("label.annotation_shading_default")));
     annotationShding.setLayout(new GridLayout(1, 2));
-    JvSwingUtils.addtoLayout(annotationShding,
+    GPreferences.addtoLayout(annotationShding,
             MessageManager.getString(
                     "label.default_minimum_colour_annotation_shading"),
             mincolourLabel, minColour);
-    JvSwingUtils.addtoLayout(annotationShding,
+    GPreferences.addtoLayout(annotationShding,
             MessageManager.getString(
                     "label.default_maximum_colour_annotation_shading"),
             maxcolourLabel, maxColour);
@@ -1406,11 +1464,6 @@ public class GPreferences extends JPanel
     return false;
   }
 
-  protected boolean validateHMMERPath(boolean showWarning)
-  {
-    return false;
-  }
-
   /**
    * Initialises the Visual tabbed panel.
    * 
@@ -1915,8 +1968,39 @@ public class GPreferences extends JPanel
 
   }
 
-  public void hmmerPath_actionPerformed(ActionEvent e)
+  protected void validateHmmerPath()
   {
+  }
+
+  protected void validateCygwinPath()
+  {
+  }
 
+  /**
+   * A helper method to add a panel containing a label and a component to a
+   * panel
+   * 
+   * @param panel
+   * @param tooltip
+   * @param label
+   * @param valBox
+   */
+  protected static void addtoLayout(JPanel panel, String tooltip,
+          JComponent label, JComponent valBox)
+  {
+    JPanel laypanel = new JPanel(new GridLayout(1, 2));
+    JPanel labPanel = new JPanel(new BorderLayout());
+    JPanel valPanel = new JPanel();
+    labPanel.setBounds(new Rectangle(7, 7, 158, 23));
+    valPanel.setBounds(new Rectangle(172, 7, 270, 23));
+    labPanel.add(label, BorderLayout.WEST);
+    valPanel.add(valBox);
+    laypanel.add(labPanel);
+    laypanel.add(valPanel);
+    valPanel.setToolTipText(tooltip);
+    labPanel.setToolTipText(tooltip);
+    valBox.setToolTipText(tooltip);
+    panel.add(laypanel);
+    panel.validate();
   }
 }
index 5170a6c..14ebbc0 100644 (file)
@@ -103,7 +103,7 @@ public class GRestInputParamEditDialog
     optionsPanel = new JPanel(new MigLayout("", "[fill]", "[fill]"));
     JScrollPane optionView = new JScrollPane();
     optionView.setViewportView(options);
-    JvSwingUtils.mgAddtoLayout(dpane,
+    JvSwingUtils.addtoLayout(dpane,
             MessageManager.getString("label.input_parameter_name"),
             new JLabel(MessageManager.getString("label.name")), tok,
             "grow,spanx 3,wrap");
index a4dca4b..db68757 100644 (file)
@@ -109,20 +109,20 @@ public class GRestServiceEditorPane extends JPanel
     cpanel = details;
     name = new JTextArea(1, 12);
 
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager
                     .getString("label.short_descriptive_name_for_service"),
             new JLabel(MessageManager.getString("label.name")), name,
             "wrap");
     action = new JComboBox();
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.function_service_performs"),
             new JLabel(MessageManager.getString("label.service_action")),
             action, "wrap");
     descr = new JTextArea(4, 60);
     descrVp = new JScrollPane();
     descrVp.setViewportView(descr);
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.brief_description_service"),
             new JLabel(MessageManager.getString("label.description")),
             descrVp, "wrap");
@@ -130,7 +130,7 @@ public class GRestServiceEditorPane extends JPanel
     url = new JTextArea(2, 60);
     urlVp = new JScrollPane();
     urlVp.setViewportView(url);
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.url_post_data_service"),
             new JLabel(MessageManager.getString("label.post_url")), urlVp,
             "wrap");
@@ -138,7 +138,7 @@ public class GRestServiceEditorPane extends JPanel
     urlsuff = new JTextArea();
     urlsuff.setColumns(60);
 
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.optional_suffix"),
             new JLabel(MessageManager.getString("label.url_suffix")),
             urlsuff, "wrap");
@@ -175,7 +175,7 @@ public class GRestServiceEditorPane extends JPanel
       }
     });
     gapChar = new JComboBox();
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.preferred_gap_character"),
             new JLabel(
                     MessageManager.getString("label.gap_character") + ":"),
index 1c50aab..e9b4de4 100644 (file)
@@ -44,8 +44,6 @@ public class OverviewRenderer
   // transparency of hidden cols/seqs overlay
   private final float TRANSPARENCY = 0.5f;
 
-  private final Color HIDDEN_COLOUR = Color.DARK_GRAY.darker();
-
   public static final String UPDATE = "OverviewUpdate";
 
   private static final int MAX_PROGRESS = 100;
@@ -152,7 +150,7 @@ public class OverviewRenderer
         if (pixelCol <= endCol)
         {
           rgbcolor = getColumnColourFromSequence(allGroups, seq,
-                  alignmentCol, finder);
+                  alignmentCol);
     
           // fill in the appropriate number of pixels
           for (int row = pixelRow; row <= endRow; ++row)
@@ -216,27 +214,23 @@ public class OverviewRenderer
   }
 
   /*
-   * Find the colour of a sequence at a specified column position
+   * Find the RGB value of the colour of a sequence at a specified column position
    * 
    * @param seq
    *          sequence to get colour for
    * @param lastcol
    *          column position to get colour for
-   * @param fcfinder
-   *          FeatureColourFinder to use
    * @return colour of sequence at this position, as RGB
    */
-  private int getColumnColourFromSequence(SequenceGroup[] allGroups,
-          jalview.datamodel.SequenceI seq,
-          int lastcol, FeatureColourFinder fcfinder)
+  int getColumnColourFromSequence(SequenceGroup[] allGroups,
+          SequenceI seq, int lastcol)
   {
-    Color color = Color.white;
+    Color color = resColFinder.GAP_COLOUR;
 
     if ((seq != null) && (seq.getLength() > lastcol))
     {
       color = resColFinder.getResidueColour(true, shader, allGroups, seq,
-              lastcol,
-              fcfinder);
+              lastcol, finder);
     }
 
     return color.getRGB();
@@ -359,15 +353,13 @@ public class OverviewRenderer
    *          the graphics object to draw on
    * @param anno
    *          alignment annotation information
-   * @param charWidth
-   *          alignment character width value
    * @param y
    *          y-position for the annotation graph
    * @param cols
    *          the collection of columns used in the overview panel
    */
-  public void drawGraph(Graphics g, AlignmentAnnotation anno, int charWidth,
-          int y, AlignmentColsCollectionI cols)
+  public void drawGraph(Graphics g, AlignmentAnnotation anno, int y,
+          AlignmentColsCollectionI cols)
   {
     Annotation[] annotations = anno.annotations;
     g.setColor(Color.white);
index 9ea468d..0f81ec1 100644 (file)
@@ -8,6 +8,7 @@ import jalview.util.ColorUtils;
 import jalview.util.Comparison;
 
 import java.awt.Color;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -45,15 +46,15 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
   private Map<Character, Float> frequencies;
 
   /**
-   * Constructor given a Hidden Markov Model consensus sequence. This provides
-   * the HMM profile from which we can read the emission probabilities that
-   * determine the colour.
+   * Constructor given a list of Hidden Markov Model consensus sequences. The
+   * first sequence provides the HMM profile from which we can read the emission
+   * probabilities that determine the colour.
    * 
-   * @param consensusSeq
+   * @param hmmSeqs
    */
-  public HmmerColourScheme(SequenceI consensusSeq)
+  public HmmerColourScheme(List<SequenceI> hmmSeqs)
   {
-    hmmSeq = consensusSeq;
+    hmmSeq = hmmSeqs.isEmpty() ? null : hmmSeqs.get(0);
     hmm = hmmSeq == null ? null : hmmSeq.getHMM();
   }
 
@@ -171,7 +172,7 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
   @Override
   public boolean isApplicableTo(AnnotatedCollectionI ac)
   {
-    return ac.getHmmConsensus() != null;
+    return !ac.getHmmSequences().isEmpty();
   }
 
   protected Map<Character, Float> getFrequencies()
index d5508f1..31bcadf 100644 (file)
@@ -1,6 +1,7 @@
 package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
 
 /**
  * An HMM colour scheme that uses global ('Uniprot') background frequencies for
@@ -18,13 +19,13 @@ public class HmmerGlobalBackground extends HmmerColourScheme
   private static final float MAX_LOG_RATIO = 4.519f;
 
   /**
-   * Constructor given a Hidden Markov Model
+   * Constructor given a sequence collection
    * 
-   * @param markov
+   * @param ac
    */
-  public HmmerGlobalBackground(AnnotatedCollectionI ac)
+  public HmmerGlobalBackground(SequenceCollectionI ac)
   {
-    super(ac.getHmmConsensus());
+    super(ac.getHmmSequences());
     String alphabetType = getHmm() == null
             ? ResidueProperties.ALPHABET_AMINO
             : getHmm().getAlphabetType();
index d7a5e65..2fe775c 100644 (file)
@@ -2,6 +2,7 @@ package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.ResidueCount;
+import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 
 import java.util.HashMap;
@@ -19,15 +20,13 @@ public class HmmerLocalBackground extends HmmerColourScheme
   float logTotalCount;
 
   /**
-   * Constructor given a Hidden Markov Model
+   * Constructor given a sequence collection
    * 
-   * @param sg
-   * 
-   * @param markov
+   * @param ac
    */
   public HmmerLocalBackground(AnnotatedCollectionI ac)
   {
-    super(ac.getHmmConsensus());
+    super(ac.getHmmSequences());
     countFrequencies(ac);
   }
 
@@ -48,9 +47,9 @@ public class HmmerLocalBackground extends HmmerColourScheme
    * Counts and stores the relative frequency of every residue in the alignment
    * (apart from any HMM consensus sequences)
    * 
-   * @param sg
+   * @param sc
    */
-  public void countFrequencies(AnnotatedCollectionI sg)
+  public void countFrequencies(SequenceCollectionI sc)
   {
     // TODO or total counts in Consensus Profile (how do we get at it?)?
     Map<Character, Float> freqs = new HashMap<>();
@@ -59,10 +58,10 @@ public class HmmerLocalBackground extends HmmerColourScheme
      * count symbols, excluding any HMM consensus sequences
      */
     ResidueCount counts = new ResidueCount();
-    List<SequenceI> seqs = sg.getSequences();
+    List<SequenceI> seqs = sc.getSequences();
     for (SequenceI seq : seqs)
     {
-      if (!seq.isHMMConsensusSequence())
+      if (!seq.hasHMMProfile())
       {
         for (char c : seq.getSequence())
         {
diff --git a/src/jalview/util/FileUtils.java b/src/jalview/util/FileUtils.java
new file mode 100644 (file)
index 0000000..1684763
--- /dev/null
@@ -0,0 +1,78 @@
+package jalview.util;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Miscellaneous file-related functions
+ */
+public final class FileUtils
+{
+
+  /**
+   * Answers the executable file for the given command, or null if not found or
+   * not executable. The path to the executable is the command name prefixed by
+   * the given folder path, optionally with .exe appended.
+   * 
+   * @param cmd
+   *          command short name, for example hmmbuild
+   * @param binaryPath
+   *          parent folder for the executable
+   * @return
+   */
+  public static File getExecutable(String cmd, String binaryPath)
+  {
+    File file = new File(binaryPath, cmd);
+    if (!file.canExecute())
+    {
+      file = new File(binaryPath, cmd + ".exe");
+      {
+        if (!file.canExecute())
+        {
+          file = null;
+        }
+      }
+    }
+    return file;
+  }
+
+  /**
+   * Answers the path to the folder containing the given executable file, by
+   * searching the PATH environment variable. Answers null if no such executable
+   * can be found.
+   * 
+   * @param cmd
+   * @return
+   */
+  public static String getPathTo(String cmd)
+  {
+    String paths = System.getenv("PATH");
+    // backslash is to escape regular expression argument
+    for (String path : paths.split("\\" + File.pathSeparator))
+    {
+      if (getExecutable(cmd, path) != null)
+      {
+        return path;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * A convenience method to create a temporary file that is deleted on exit of
+   * the JVM
+   * 
+   * @param prefix
+   * @param suffix
+   * @return
+   * @throws IOException
+   */
+  public static File createTempFile(String prefix, String suffix)
+          throws IOException
+  {
+    File f = File.createTempFile(prefix, suffix);
+    f.deleteOnExit();
+    return f;
+  }
+
+}
index 2c74609..7c0e15d 100644 (file)
@@ -51,7 +51,7 @@ public class Platform
   }
 
   /**
-   * Check if we are on a Microsoft plaform...
+   * Check if we are on a Microsoft platform...
    * 
    * @return true if we have to cope with another platform variation
    */
index e4d9d88..553f813 100644 (file)
@@ -1032,16 +1032,24 @@ public abstract class FeatureRendererModel
    * Removes from the list of features any that duplicate the location of a
    * feature of the same type. Should be used only for features of the same,
    * simple, feature colour (which normally implies the same feature type). Does
-   * not check visibility settings for feature type or feature group.
+   * not check visibility settings for feature type or feature group. No
+   * filtering is done if transparency, or any feature filters, are in force.
    * 
    * @param features
    */
   public void filterFeaturesForDisplay(List<SequenceFeature> features)
   {
-    if (features.isEmpty())
+    /*
+     * don't remove 'redundant' features if 
+     * - transparency is applied (feature count affects depth of feature colour)
+     * - filters are applied (not all features may be displayable)
+     */
+    if (features.isEmpty() || transparency != 1f
+            || !featureFilters.isEmpty())
     {
       return;
     }
+
     SequenceFeatures.sortFeatures(features, true);
     SequenceFeature lastFeature = null;
 
index d42598c..cf42425 100644 (file)
@@ -129,10 +129,10 @@ public class InformationThread extends AlignCalcWorker
     /*
      * alignment HMM profile
      */
-    SequenceI seq = alignment.getHmmConsensus();
-    if (seq != null)
+    List<SequenceI> seqs = alignment.getHmmSequences();
+    if (!seqs.isEmpty())
     {
-      HiddenMarkovModel hmm = seq.getHMM();
+      HiddenMarkovModel hmm = seqs.get(0).getHMM();
       ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
               0, width, alignViewport.isIgnoreBelowBackground(),
               alignViewport.isInfoLetterHeight());
@@ -145,10 +145,10 @@ public class InformationThread extends AlignCalcWorker
     List<SequenceGroup> groups = alignment.getGroups();
     for (SequenceGroup group : groups)
     {
-      seq = group.getHmmConsensus();
-      if (seq != null)
+      seqs = group.getHmmSequences();
+      if (!seqs.isEmpty())
       {
-        HiddenMarkovModel hmm = seq.getHMM();
+        HiddenMarkovModel hmm = seqs.get(0).getHMM();
         ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
                 0, width, group.isIgnoreBelowBackground(),
                 group.isUseInfoLetterHeight());
@@ -193,19 +193,24 @@ public class InformationThread extends AlignCalcWorker
     /*
      * annotation for alignment HMM consensus if present
      */
-    SequenceI hmmSeq = alignment.getHmmConsensus();
-    ProfilesI profile = alignViewport.getHmmProfiles();
-    float m = updateInformationAnnotation(hmmSeq, profile, null, infos);
-    maxInformation = Math.max(maxInformation, m);
+    List<SequenceI> hmmSeqs = alignment.getHmmSequences();
+    if (!hmmSeqs.isEmpty())
+    {
+      ProfilesI profile = alignViewport.getHmmProfiles();
+      float m = updateInformationAnnotation(hmmSeqs.get(0), profile, null,
+              infos);
+      maxInformation = Math.max(maxInformation, m);
+    }
 
     /*
      * annotation for group HMM consensus if present
      */
     for (SequenceGroup group : alignment.getGroups())
     {
-      hmmSeq = group.getHmmConsensus();
+      hmmSeqs = group.getHmmSequences();
       ProfilesI profiles = group.getHmmProfiles();
-      m = updateInformationAnnotation(hmmSeq, profiles, group, infos);
+      float m = updateInformationAnnotation(hmmSeqs.get(0), profiles, group,
+              infos);
       maxInformation = Math.max(maxInformation, m);
     }
 
index 0f1a25e..7d661a4 100644 (file)
@@ -31,6 +31,7 @@ import jalview.util.MessageManager;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.dm.JabaWsParamSet;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ParamDatastoreI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -108,8 +109,12 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       }
       WsJobParameters jobParams = (preset == null && paramset != null
               && paramset.size() > 0)
-                      ? new WsJobParameters(null, sh, null, paramset)
-                      : new WsJobParameters(sh, preset);
+                      ? new WsJobParameters((ParamDatastoreI) null, sh,
+                              (WsParamSetI) null,
+                              paramset)
+                      : new WsJobParameters((ParamDatastoreI) null, sh,
+                              preset,
+                              (List<Argument>) null);
       if (adjustingExisting)
       {
         jobParams.setName(MessageManager
@@ -117,8 +122,9 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       }
       if (!jobParams.showRunDialog())
       {
-        return false;
+        return false; // dialog cancelled
       }
+
       WsParamSetI prset = jobParams.getPreset();
       if (prset == null)
       {
index f80ff77..05abc3a 100644 (file)
  */
 package jalview.ws.params.simple;
 
-import jalview.ws.params.OptionI;
-
 import java.net.URL;
 import java.util.Arrays;
 
-public class BooleanOption extends Option implements OptionI
+public class BooleanOption extends Option
 {
 
   public BooleanOption(String name, String descr, boolean required,
           boolean defVal, boolean val, URL link)
   {
-
-    super(name, descr, required, (defVal ? name : ""), (val ? name : ""),
-            Arrays.asList(new String[]
-            { name }), link);
+    super(name, descr, required, (defVal ? name : null),
+            (val ? name : null),
+            Arrays.asList(name), link);
   }
 
 }
index d6ccf46..6b76170 100644 (file)
@@ -10,16 +10,17 @@ import jalview.ws.params.ValueConstrainI;
  */
 public class DoubleParameter extends Option implements ParameterI
 {
-  Double defval;
+  double defval;
 
-  Double min, max;
+  double min;
+
+  double max;
 
   @Override
   public ValueConstrainI getValidValue()
   {
     return new ValueConstrainI()
     {
-
       @Override
       public ValueType getType()
       {
@@ -29,27 +30,13 @@ public class DoubleParameter extends Option implements ParameterI
       @Override
       public Number getMin()
       {
-        if (min < max)
-        {
-          return min;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? min : null;
       }
 
       @Override
       public Number getMax()
       {
-        if (min < max)
-        {
-          return max;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? max : null;
       }
     };
   }
@@ -62,7 +49,7 @@ public class DoubleParameter extends Option implements ParameterI
   }
 
   public DoubleParameter(String name, String description, boolean required,
-          Double defValue, Double min, Double max)
+          Double defValue, double min, double max)
   {
     super(name, description, required, String.valueOf(defValue), null, null,
             null);
@@ -72,7 +59,7 @@ public class DoubleParameter extends Option implements ParameterI
   }
 
   public DoubleParameter(String name, String description, boolean required,
-          Double defValue, Double value, Double min, Double max)
+          Double defValue, Double value, double min, double max)
   {
     super(name, description, required, String.valueOf(defValue),
             String.valueOf(value), null, null);
index fb34e89..b3a01b2 100644 (file)
@@ -31,8 +31,11 @@ public class IntegerParameter extends Option implements ParameterI
 {
   int defval;
 
-  int min, max;
+  int min;
 
+  int max;
+
+  @Override
   public ValueConstrainI getValidValue()
   {
     return new ValueConstrainI()
@@ -47,27 +50,13 @@ public class IntegerParameter extends Option implements ParameterI
       @Override
       public Number getMin()
       {
-        if (min < max)
-        {
-          return min;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? min : null;
       }
 
       @Override
       public Number getMax()
       {
-        if (min < max)
-        {
-          return max;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? max : null;
       }
     };
   }
index 91ed03a..01744e7 100644 (file)
@@ -4,17 +4,20 @@ import jalview.ws.params.ParameterI;
 import jalview.ws.params.ValueConstrainI;
 
 /**
+ * A model for a numeric-valued parameter which should be displayed using a
+ * logarithmic scale
  * 
  * @author TZVanaalten
- *
  */
 public class LogarithmicParameter extends Option implements ParameterI
 {
-  Double defval;
+  final double defval;
 
-  Double min, max;
+  final double min;
 
-  Double base;
+  final double max;
+
+  final double base; // todo is this even needed?
 
   @Override
   public ValueConstrainI getValidValue()
@@ -31,27 +34,13 @@ public class LogarithmicParameter extends Option implements ParameterI
       @Override
       public Number getMin()
       {
-        if (min < max)
-        {
-          return min;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? min : null;
       }
 
       @Override
       public Number getMax()
       {
-        if (min < max)
-        {
-          return max;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? max : null;
       }
     };
   }
@@ -61,30 +50,31 @@ public class LogarithmicParameter extends Option implements ParameterI
     super(parm);
     max = parm.max;
     min = parm.min;
+    defval = 0D;
     base = parm.base;
   }
 
   public LogarithmicParameter(String name, String description,
-          boolean required, Double defValue, Double min, Double max,
-          Double base)
+          boolean required, Double defValue, double min, double max,
+          double base)
   {
     super(name, description, required, String.valueOf(defValue), null, null,
             null);
     defval = defValue;
-    this.min = min * 1000000;
-    this.max = max * 1000000;
+    this.min = min;
+    this.max = max;
     this.base = base;
   }
 
   public LogarithmicParameter(String name, String description,
-          boolean required, Double defValue, Double value, Double min,
-          Double max, Double base)
+          boolean required, Double defValue, double value, double min,
+          double max, double base)
   {
     super(name, description, required, String.valueOf(defValue),
             String.valueOf(value), null, null);
     defval = defValue;
-    this.min = min * 1000000;
-    this.max = max * 1000000;
+    this.min = min;
+    this.max = max;
     this.base = base;
   }
 
@@ -94,7 +84,7 @@ public class LogarithmicParameter extends Option implements ParameterI
     return new LogarithmicParameter(this);
   }
 
-  public Double getBase()
+  public double getBase()
   {
     return base;
   }
index 653359f..f0126df 100644 (file)
@@ -29,10 +29,21 @@ import java.util.List;
 
 public class Option implements OptionI
 {
+  String name;
 
-  String name, value, defvalue, description;
+  /*
+   * current value in string format, or "null" if undefined
+   */
+  String value;
 
-  ArrayList<String> possibleVals = new ArrayList<String>();
+  /*
+   * default value in string format, or "null" if undefined
+   */
+  String defvalue;
+
+  String description;
+
+  ArrayList<String> possibleVals = new ArrayList<>();
 
   boolean required;
 
@@ -84,11 +95,17 @@ public class Option implements OptionI
   {
     name = new String(opt.name);
     if (opt.value != null)
+    {
       value = new String(opt.value);
+    }
     if (opt.defvalue != null)
+    {
       defvalue = new String(opt.defvalue);
+    }
     if (opt.description != null)
+    {
       description = new String(opt.description);
+    }
     if (opt.possibleVals != null)
     {
       possibleVals = (ArrayList<String>) opt.possibleVals.clone();
@@ -113,7 +130,7 @@ public class Option implements OptionI
     this.defvalue = defValue;
     if (possibleVals != null)
     {
-      this.possibleVals = new ArrayList<String>();
+      this.possibleVals = new ArrayList<>();
       this.possibleVals.addAll(possibleVals);
     }
     this.fdetails = fdetails;
@@ -125,4 +142,13 @@ public class Option implements OptionI
     Option opt = new Option(this);
     return opt;
   }
+
+  /**
+   * toString method to help identify options in the debugger only
+   */
+  @Override
+  public String toString()
+  {
+    return this.getClass().getName() + ":" + name;
+  }
 }
index 8f96d04..e3b7067 100644 (file)
@@ -1,6 +1,7 @@
 package jalview.hmmer;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
@@ -19,6 +20,7 @@ import jalview.ws.params.simple.Option;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.util.ArrayList;
+import java.util.List;
 
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
@@ -60,15 +62,15 @@ public class HMMERTest {
           throws MalformedURLException, IOException
   {
     /*
-     * run hmmbuild - note the side-effect of selecting the HMM
-     * sequence that gets added to the alignment
+     * run hmmbuild
      */
     testHMMBuild();
-    HiddenMarkovModel hmm = frame.getSelectedHMM();
-    assertNotNull(hmm);
+    List<SequenceI> hmms = frame.getViewport().getAlignment()
+            .getHmmSequences();
+    assertFalse(hmms.isEmpty());
 
     /*
-     * now run hmmalign - with respect to the select HMM profile
+     * now run hmmalign - by default with respect to the added HMM profile
      */
     testHMMAlign();
   }
@@ -100,7 +102,7 @@ public class HMMERTest {
 
   public void testHMMAlign()
   {
-    HMMAlign thread = new HMMAlign(frame,
+    HmmerCommand thread = new HMMAlign(frame,
             new ArrayList<ArgumentI>());
     thread.run();
 
@@ -118,8 +120,8 @@ public class HMMERTest {
     assertNotNull(original);
     AlignmentI realigned = alignFrames[1].getViewport().getAlignment();
     assertNotNull(realigned);
-    assertNotNull(original.getHmmConsensus());
-    assertNotNull(realigned.getHmmConsensus());
+    assertFalse(original.getHmmSequences().isEmpty());
+    assertFalse(realigned.getHmmSequences().isEmpty());
 
     SequenceI ferCapan = original.findName("FER_CAPAN");
     assertTrue(ferCapan.getSequenceAsString().startsWith("MA------SVSAT"));
diff --git a/test/jalview/renderer/OverviewRendererTest.java b/test/jalview/renderer/OverviewRendererTest.java
new file mode 100644 (file)
index 0000000..bc9c2e4
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.renderer;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.renderer.seqfeatures.FeatureRenderer;
+import jalview.schemes.FeatureColour;
+import jalview.schemes.ZappoColourScheme;
+import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.OverviewDimensions;
+import jalview.viewmodel.OverviewDimensionsShowHidden;
+import jalview.viewmodel.ViewportRanges;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+public class OverviewRendererTest
+{
+
+  @Test
+  public void testGetColumnColourFromSequence()
+  {
+    OverviewResColourFinder cf = new OverviewResColourFinder(false,
+            Color.PINK, Color.green); // gapColour, hiddenColour
+    Sequence seq1 = new Sequence("seq1", "PQ-RL-");
+    Sequence seq2 = new Sequence("seq2", "FVE");
+    AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
+    AlignmentViewport av = new AlignViewport(al);
+    OverviewDimensions od = new OverviewDimensionsShowHidden(new ViewportRanges(al), false);
+    ResidueShaderI rs = new ResidueShader(new ZappoColourScheme());
+    FeatureRenderer fr = new FeatureRenderer(av);
+    OverviewRenderer or = new OverviewRenderer(fr, od, al, rs, cf);
+
+    // P is magenta (see ResidueProperties.zappo)
+    assertEquals(or.getColumnColourFromSequence(null, seq1, 0), Color.magenta.getRGB());
+    // Q is green
+    assertEquals(or.getColumnColourFromSequence(null, seq1, 1),
+            Color.green.getRGB());
+    // gap is pink (specified in OverviewResColourFinder constructor above)
+    assertEquals(or.getColumnColourFromSequence(null, seq1, 2),
+            Color.pink.getRGB());
+    // F is orange
+    assertEquals(or.getColumnColourFromSequence(null, seq2, 0),
+            Color.orange.getRGB());
+    // E is red
+    assertEquals(or.getColumnColourFromSequence(null, seq2, 2),
+            Color.red.getRGB());
+    // past end of sequence colour as gap (JAL-2929)
+    assertEquals(or.getColumnColourFromSequence(null, seq2, 3),
+            Color.pink.getRGB());
+
+    /*
+     * now add a feature on seq1
+     */
+    seq1.addSequenceFeature(
+            new SequenceFeature("Pfam", "desc", 1, 4, null));
+    fr.findAllFeatures(true);
+    av.setShowSequenceFeatures(true);
+    fr.setColour("Pfam", new FeatureColour(Color.yellow));
+    assertEquals(or.getColumnColourFromSequence(null, seq1, 0),
+            Color.yellow.getRGB());
+
+    // don't show sequence features
+    av.setShowSequenceFeatures(false);
+    assertEquals(or.getColumnColourFromSequence(null, seq1, 0),
+            Color.magenta.getRGB());
+  }
+}
index cebef11..da7cada 100644 (file)
@@ -357,6 +357,14 @@ public class FeatureRendererTest
     assertTrue(features.contains(sf2) || features.contains(sf3));
     assertFalse(features.contains(sf2) && features.contains(sf3));
     assertTrue(features.contains(sf5));
+
+    /*
+     * no filtering if transparency is applied
+     */
+    fr.setTransparency(0.5f);
+    features = seq.getSequenceFeatures();
+    fr.filterFeaturesForDisplay(features);
+    assertEquals(features.size(), 5);
   }
 
   @Test(groups = "Functional")
index 13bf47b..1cdee91 100644 (file)
@@ -24,7 +24,6 @@ public class HmmerGlobalBackgroundTest {
 
     SequenceI hmmSeq = file.getSeqsAsArray()[0];
     AlignmentI al = new Alignment(new SequenceI[] { hmmSeq });
-    al.setHmmConsensus(hmmSeq);
     ColourSchemeI scheme = new HmmerGlobalBackground(al);
 
     /*
index 7467ab2..5f2bb8f 100644 (file)
@@ -37,7 +37,6 @@ public class HmmerLocalBackgroundTest {
     AnnotatedCollectionI ac = new Alignment(
             new SequenceI[]
             { hmmSeq, seq1, seq2 });
-    ac.setHmmConsensus(hmmSeq);
     ColourSchemeI scheme = new HmmerLocalBackground(ac);
 
     /*
index 80b48c3..134fbd1 100644 (file)
@@ -28,6 +28,7 @@ import jalview.ws.jabaws.JalviewJabawsTestUtils;
 import jalview.ws.jws2.JabaPreset;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ParamDatastoreI;
 
 import java.awt.BorderLayout;
 import java.awt.event.WindowAdapter;
@@ -42,6 +43,7 @@ import javax.swing.JPanel;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import compbio.metadata.Argument;
 import compbio.metadata.Preset;
 import compbio.metadata.PresetManager;
 
@@ -58,12 +60,12 @@ public class Jws2ParamView
   /**
    * which services to test
    */
-  public static List<String> serviceTests = new ArrayList<String>();
+  public static List<String> serviceTests = new ArrayList<>();
 
   /**
    * which presets to test for services
    */
-  public static List<String> presetTests = new ArrayList<String>();
+  public static List<String> presetTests = new ArrayList<>();
   static
   {
     serviceTests.add("AAConWS".toLowerCase());
@@ -127,11 +129,12 @@ public class Jws2ParamView
             }
             pr = en.next();
           }
-          WsJobParameters pgui = new WsJobParameters(service,
-                  new JabaPreset(service, pr));
-          JFrame jf = new JFrame(MessageManager.formatMessage(
-                  "label.ws_parameters_for",
-                  new String[] { service.getActionText() }));
+          WsJobParameters pgui = new WsJobParameters((ParamDatastoreI) null,
+                  service, new JabaPreset(service, pr),
+                  (List<Argument>) null);
+          JFrame jf = new JFrame(MessageManager
+                  .formatMessage("label.ws_parameters_for", new String[]
+                  { service.getActionText() }));
           jf.setSize(700, 800);
           JPanel cont = new JPanel(new BorderLayout());
           pgui.validate();
index 01973d2..ab53613 100755 (executable)
@@ -36,7 +36,7 @@
                <param name="file2" value="${file2}" />
        </antcall>
        <echo message=" "/>
-       <echo message="Missing message labels in Messages.properties compare to ${file2}"/>
+       <echo message="Missing message labels in Messages.properties compared to ${file2}"/>
        <antcall target="compareProperties">
                <param name="file2" value="resources/lang/Messages.properties"/>
                <param name="file1" value="${file2}" />