From 9ce5bbd251a067e0c5b1969725121498bcfb28a0 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Fri, 20 Apr 2018 22:01:08 +0100 Subject: [PATCH] JAL-2629 update spikes/mungo to latest --- .ant-targets-build.xml | 29 - .classpath | 3 +- .../org/jalview/HiddenColsIteratorsBenchmark.java | 140 ++++ .../main/java/org/jalview/SeqWidthBenchmark.java | 96 +++ build.xml | 9 +- resources/lang/Messages.properties | 55 +- resources/lang/Messages_es.properties | 2 - src/jalview/analysis/SeqsetUtils.java | 7 +- src/jalview/appletgui/OverviewCanvas.java | 3 +- src/jalview/datamodel/Alignment.java | 29 +- src/jalview/datamodel/HiddenMarkovModel.java | 33 +- src/jalview/datamodel/Sequence.java | 24 +- src/jalview/datamodel/SequenceCollectionI.java | 10 +- src/jalview/datamodel/SequenceGroup.java | 33 +- src/jalview/datamodel/SequenceI.java | 15 +- src/jalview/gui/AlignFrame.java | 105 +-- src/jalview/gui/AquaInternalFrameManager.java | 3 +- src/jalview/gui/JvSwingUtils.java | 63 +- src/jalview/gui/OptsAndParamsPage.java | 671 ++++++++++---------- src/jalview/gui/OverviewCanvas.java | 3 +- src/jalview/gui/PopupMenu.java | 24 - src/jalview/gui/Preferences.java | 98 ++- src/jalview/gui/WsJobParameters.java | 373 +++++------ src/jalview/hmmer/HMMAlign.java | 34 +- src/jalview/hmmer/HMMBuild.java | 34 +- src/jalview/hmmer/HMMERParamStore.java | 115 +++- src/jalview/hmmer/HMMSearch.java | 66 +- src/jalview/hmmer/HmmerCommand.java | 154 +++-- src/jalview/io/FileLoader.java | 3 +- src/jalview/jbgui/GPreferences.java | 192 ++++-- src/jalview/jbgui/GRestInputParamEditDialog.java | 2 +- src/jalview/jbgui/GRestServiceEditorPane.java | 12 +- src/jalview/renderer/OverviewRenderer.java | 24 +- src/jalview/schemes/HmmerColourScheme.java | 15 +- src/jalview/schemes/HmmerGlobalBackground.java | 9 +- src/jalview/schemes/HmmerLocalBackground.java | 17 +- src/jalview/util/FileUtils.java | 78 +++ src/jalview/util/Platform.java | 2 +- .../seqfeatures/FeatureRendererModel.java | 12 +- src/jalview/workers/InformationThread.java | 29 +- src/jalview/ws/jws2/Jws2Client.java | 12 +- src/jalview/ws/params/simple/BooleanOption.java | 11 +- src/jalview/ws/params/simple/DoubleParameter.java | 29 +- src/jalview/ws/params/simple/IntegerParameter.java | 23 +- .../ws/params/simple/LogarithmicParameter.java | 48 +- src/jalview/ws/params/simple/Option.java | 32 +- test/jalview/hmmer/HMMERTest.java | 18 +- test/jalview/renderer/OverviewRendererTest.java | 73 +++ .../renderer/seqfeatures/FeatureRendererTest.java | 8 + .../jalview/schemes/HmmerGlobalBackgroundTest.java | 1 - test/jalview/schemes/HmmerLocalBackgroundTest.java | 1 - test/jalview/ws/gui/Jws2ParamView.java | 17 +- utils/i18nAnt.xml | 2 +- 53 files changed, 1695 insertions(+), 1206 deletions(-) create mode 100644 benchmarking/src/main/java/org/jalview/HiddenColsIteratorsBenchmark.java create mode 100644 benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java create mode 100644 src/jalview/util/FileUtils.java create mode 100644 test/jalview/renderer/OverviewRendererTest.java diff --git a/.ant-targets-build.xml b/.ant-targets-build.xml index 15432a1..7ef21f1 100644 --- a/.ant-targets-build.xml +++ b/.ant-targets-build.xml @@ -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 diff --git a/.classpath b/.classpath index 896611c..f4b8cf8 100644 --- a/.classpath +++ b/.classpath @@ -66,9 +66,8 @@ - - + diff --git a/benchmarking/src/main/java/org/jalview/HiddenColsIteratorsBenchmark.java b/benchmarking/src/main/java/org/jalview/HiddenColsIteratorsBenchmark.java new file mode 100644 index 0000000..477bfad --- /dev/null +++ b/benchmarking/src/main/java/org/jalview/HiddenColsIteratorsBenchmark.java @@ -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 . + * 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 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 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 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 index 0000000..a92d4f0 --- /dev/null +++ b/benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java @@ -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 . + * 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 - + @@ -182,17 +182,14 @@ - - - + - + diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 06c8b6b..609c6a8 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -822,8 +822,8 @@ label.fetch_retrieve_from_all_sources = Retrieve from all {0} sources in {1}
label.feature_settings_click_drag = Drag up or down to change render order.
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 = Click to show brief description
Right click for further information. -label.opt_and_params_show_brief_desc = Click to show brief description
+label.opt_and_params_show_brief_desc_image_link = Click to show brief description
Right click for further information. +label.opt_and_params_show_brief_desc = Click to show brief description
label.adjusts_width_generated_eps_png = Adjusts the width of the generated EPS or PNG file to ensure even the longest sequence ID or annotation label is displayed label.manually_specify_width_left_column = 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 label.job_created_when_checked = When checked, a job is created for every sequence in the current selection. @@ -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 diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index e42d6b8..6dfefa3 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -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 diff --git a/src/jalview/analysis/SeqsetUtils.java b/src/jalview/analysis/SeqsetUtils.java index 2c077b6..921ab2a 100755 --- a/src/jalview/analysis/SeqsetUtils.java +++ b/src/jalview/analysis/SeqsetUtils.java @@ -53,7 +53,7 @@ public class SeqsetUtils sqinfo.put("Description", seq.getDescription()); } - Vector sfeat = new Vector(); + Vector sfeat = new Vector<>(); List 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; } diff --git a/src/jalview/appletgui/OverviewCanvas.java b/src/jalview/appletgui/OverviewCanvas.java index ecc90b8..e99c021 100644 --- a/src/jalview/appletgui/OverviewCanvas.java +++ b/src/jalview/appletgui/OverviewCanvas.java @@ -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()); } diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index 6b100ea..e3b4c64 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -53,8 +53,6 @@ public class Alignment implements AlignmentI private List sequences; - private SequenceI hmmConsensus; - protected List 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 getHmmSequences() + { + List result = new ArrayList<>(); + for (int i = 0; i < sequences.size(); i++) + { + SequenceI seq = sequences.get(i); + if (seq.hasHMMProfile()) + { + result.add(seq); + } + } + return result; + } } diff --git a/src/jalview/datamodel/HiddenMarkovModel.java b/src/jalview/datamodel/HiddenMarkovModel.java index a4270cd..3c2c437 100644 --- a/src/jalview/datamodel/HiddenMarkovModel.java +++ b/src/jalview/datamodel/HiddenMarkovModel.java @@ -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 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; } } diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index 755abbb..9464c74 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -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; + } } diff --git a/src/jalview/datamodel/SequenceCollectionI.java b/src/jalview/datamodel/SequenceCollectionI.java index ee4b844..a280079 100644 --- a/src/jalview/datamodel/SequenceCollectionI.java +++ b/src/jalview/datamodel/SequenceCollectionI.java @@ -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 getHmmSequences(); } diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index aebcbb3..b558f40 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -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 getHmmSequences() + { + List result = new ArrayList<>(); + for (int i = 0; i < sequences.size(); i++) + { + SequenceI seq = sequences.get(i); + if (seq.hasHMMProfile()) + { + result.add(seq); + } + } + return result; + } + } diff --git a/src/jalview/datamodel/SequenceI.java b/src/jalview/datamodel/SequenceI.java index 5b3d782..6d34d07 100755 --- a/src/jalview/datamodel/SequenceI.java +++ b/src/jalview/datamodel/SequenceI.java @@ -499,10 +499,6 @@ public interface SequenceI extends ASequenceI */ public List 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 it); + String getSequenceStringFromIterator(Iterator 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 it); + int firstResidueOutsideIterator(Iterator it); + + /** + * Answers true if this sequence has an associated Hidden Markov Model + * + * @return + */ + boolean hasHMMProfile(); } diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 009d946..bcb8423 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -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 alignPanels = new ArrayList<>(); @@ -1031,21 +1024,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, { return; } - List 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 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 args = new ArrayList<>(); + + /* + * get default parameters, and optionally show a dialog + * to allow them to be modified + */ + ParamDatastoreI store = HMMERParamStore.forAlign(viewport); + List 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 args = new ArrayList<>(); + + /* + * get default parameters, and (if requested) show + * dialog to allow modification + */ + ParamDatastoreI store = HMMERParamStore.forSearch(viewport); + List 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) { diff --git a/src/jalview/gui/AquaInternalFrameManager.java b/src/jalview/gui/AquaInternalFrameManager.java index 829135b..537ec17 100644 --- a/src/jalview/gui/AquaInternalFrameManager.java +++ b/src/jalview/gui/AquaInternalFrameManager.java @@ -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 +} diff --git a/src/jalview/gui/JvSwingUtils.java b/src/jalview/gui/JvSwingUtils.java index 4658668..190eda1 100644 --- a/src/jalview/gui/JvSwingUtils.java +++ b/src/jalview/gui/JvSwingUtils.java @@ -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 diff --git a/src/jalview/gui/OptsAndParamsPage.java b/src/jalview/gui/OptsAndParamsPage.java index 1505df8..fcb293c 100644 --- a/src/jalview/gui/OptsAndParamsPage.java +++ b/src/jalview/gui/OptsAndParamsPage.java @@ -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 optSet = new LinkedHashMap<>(); + + Map 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 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 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 ? "
" @@ -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: + *
    + *
  • if a text input, returns the trimmed value
  • + *
  • if a choice list, returns the selected value
  • + *
  • 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.
  • + *
+ * 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 optSet = new java.util.LinkedHashMap<>(); - - Map paramSet = new java.util.LinkedHashMap<>(); - public Map 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; } - } diff --git a/src/jalview/gui/OverviewCanvas.java b/src/jalview/gui/OverviewCanvas.java index 7994bf2..cc361a5 100644 --- a/src/jalview/gui/OverviewCanvas.java +++ b/src/jalview/gui/OverviewCanvas.java @@ -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()); } diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index e3becf6..a3a2422 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -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 */ diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index df35b5e..5382f8d 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -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; diff --git a/src/jalview/gui/WsJobParameters.java b/src/jalview/gui/WsJobParameters.java index af52d43..8377a16 100644 --- a/src/jalview/gui/WsJobParameters.java +++ b/src/jalview/gui/WsJobParameters.java @@ -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 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 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 modifiedElements = new Hashtable<>(); + + String lastParmSet = null; + + public WsJobParameters(ParamDatastoreI store, WsParamSetI preset, List 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 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 jobArgset) + public WsJobParameters(ParamDatastoreI paramStorei, Jws2Instance service, + WsParamSetI preset, List 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 jabajobArgset) + void initForService(WsParamSetI jabap, List jabajobArgset) { WsParamSetI p = null; List jobArgset = null; @@ -564,12 +522,12 @@ public class WsJobParameters extends JPanel implements ItemListener, void init(WsParamSetI p, List jobArgset) { - Hashtable exnames = new Hashtable(); + Hashtable 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 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 editedParams = new Hashtable(); @@ -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 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 diff --git a/src/jalview/hmmer/HMMAlign.java b/src/jalview/hmmer/HMMAlign.java index 44828aa..b5f047e 100644 --- a/src/jalview/hmmer/HMMAlign.java +++ b/src/jalview/hmmer/HMMAlign.java @@ -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 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); } diff --git a/src/jalview/hmmer/HMMBuild.java b/src/jalview/hmmer/HMMBuild.java index d95be48..3c3bd40 100644 --- a/src/jalview/hmmer/HMMBuild.java +++ b/src/jalview/hmmer/HMMBuild.java @@ -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 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); } } } diff --git a/src/jalview/hmmer/HMMERParamStore.java b/src/jalview/hmmer/HMMERParamStore.java index c668481..6f1f51f 100644 --- a/src/jalview/hmmer/HMMERParamStore.java +++ b/src/jalview/hmmer/HMMERParamStore.java @@ -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 presets = new ArrayList<>(); + private List 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 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 databases = new ArrayList<>(); + List 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 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 args) + { + List hmms = viewport.getAlignment().getHmmSequences(); + if (!hmms.isEmpty()) + { + List 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 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 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"), diff --git a/src/jalview/hmmer/HMMSearch.java b/src/jalview/hmmer/HMMSearch.java index 30299e9..d4c9656 100644 --- a/src/jalview/hmmer/HMMSearch.java +++ b/src/jalview/hmmer/HMMSearch.java @@ -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 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 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 alignArgs = new ArrayList<>(); + String defSeq = hmmSeq.getName(); + List 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(); diff --git a/src/jalview/hmmer/HmmerCommand.java b/src/jalview/hmmer/HmmerCommand.java index fe6c0f9..f8f2cde 100644 --- a/src/jalview/hmmer/HmmerCommand.java +++ b/src/jalview/hmmer/HmmerCommand.java @@ -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 command) + public boolean runCommand(List commands) throws IOException { + List 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 wrapWithCygwin(List commands) + { + File bash = FileUtils.getExecutable("bash", + Cache.getProperty(Preferences.CYGWIN_PATH)); + if (bash == null) + { + Cache.log.error("Cygwin shell not found"); + return commands; + } + + List 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; } } diff --git a/src/jalview/io/FileLoader.java b/src/jalview/io/FileLoader.java index 2d753c1..798875f 100755 --- a/src/jalview/io/FileLoader.java +++ b/src/jalview/io/FileLoader.java @@ -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(); diff --git a/src/jalview/jbgui/GPreferences.java b/src/jalview/jbgui/GPreferences.java index 358298d..380db74 100755 --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@ -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(); } } diff --git a/src/jalview/jbgui/GRestInputParamEditDialog.java b/src/jalview/jbgui/GRestInputParamEditDialog.java index 5170a6c..14ebbc0 100644 --- a/src/jalview/jbgui/GRestInputParamEditDialog.java +++ b/src/jalview/jbgui/GRestInputParamEditDialog.java @@ -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"); diff --git a/src/jalview/jbgui/GRestServiceEditorPane.java b/src/jalview/jbgui/GRestServiceEditorPane.java index a4dca4b..db68757 100644 --- a/src/jalview/jbgui/GRestServiceEditorPane.java +++ b/src/jalview/jbgui/GRestServiceEditorPane.java @@ -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") + ":"), diff --git a/src/jalview/renderer/OverviewRenderer.java b/src/jalview/renderer/OverviewRenderer.java index 1c50aab..e9b4de4 100644 --- a/src/jalview/renderer/OverviewRenderer.java +++ b/src/jalview/renderer/OverviewRenderer.java @@ -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); diff --git a/src/jalview/schemes/HmmerColourScheme.java b/src/jalview/schemes/HmmerColourScheme.java index 9ea468d..0f81ec1 100644 --- a/src/jalview/schemes/HmmerColourScheme.java +++ b/src/jalview/schemes/HmmerColourScheme.java @@ -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 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 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 getFrequencies() diff --git a/src/jalview/schemes/HmmerGlobalBackground.java b/src/jalview/schemes/HmmerGlobalBackground.java index d5508f1..31bcadf 100644 --- a/src/jalview/schemes/HmmerGlobalBackground.java +++ b/src/jalview/schemes/HmmerGlobalBackground.java @@ -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(); diff --git a/src/jalview/schemes/HmmerLocalBackground.java b/src/jalview/schemes/HmmerLocalBackground.java index d7a5e65..2fe775c 100644 --- a/src/jalview/schemes/HmmerLocalBackground.java +++ b/src/jalview/schemes/HmmerLocalBackground.java @@ -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 freqs = new HashMap<>(); @@ -59,10 +58,10 @@ public class HmmerLocalBackground extends HmmerColourScheme * count symbols, excluding any HMM consensus sequences */ ResidueCount counts = new ResidueCount(); - List seqs = sg.getSequences(); + List 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 index 0000000..1684763 --- /dev/null +++ b/src/jalview/util/FileUtils.java @@ -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; + } + +} diff --git a/src/jalview/util/Platform.java b/src/jalview/util/Platform.java index 2c74609..7c0e15d 100644 --- a/src/jalview/util/Platform.java +++ b/src/jalview/util/Platform.java @@ -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 */ diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index e4d9d88..553f813 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -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 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; diff --git a/src/jalview/workers/InformationThread.java b/src/jalview/workers/InformationThread.java index d42598c..cf42425 100644 --- a/src/jalview/workers/InformationThread.java +++ b/src/jalview/workers/InformationThread.java @@ -129,10 +129,10 @@ public class InformationThread extends AlignCalcWorker /* * alignment HMM profile */ - SequenceI seq = alignment.getHmmConsensus(); - if (seq != null) + List 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 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 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); } diff --git a/src/jalview/ws/jws2/Jws2Client.java b/src/jalview/ws/jws2/Jws2Client.java index 0f1a25e..7d661a4 100644 --- a/src/jalview/ws/jws2/Jws2Client.java +++ b/src/jalview/ws/jws2/Jws2Client.java @@ -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) 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) { diff --git a/src/jalview/ws/params/simple/BooleanOption.java b/src/jalview/ws/params/simple/BooleanOption.java index f80ff77..05abc3a 100644 --- a/src/jalview/ws/params/simple/BooleanOption.java +++ b/src/jalview/ws/params/simple/BooleanOption.java @@ -20,21 +20,18 @@ */ 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); } } diff --git a/src/jalview/ws/params/simple/DoubleParameter.java b/src/jalview/ws/params/simple/DoubleParameter.java index d6ccf46..6b76170 100644 --- a/src/jalview/ws/params/simple/DoubleParameter.java +++ b/src/jalview/ws/params/simple/DoubleParameter.java @@ -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); diff --git a/src/jalview/ws/params/simple/IntegerParameter.java b/src/jalview/ws/params/simple/IntegerParameter.java index fb34e89..b3a01b2 100644 --- a/src/jalview/ws/params/simple/IntegerParameter.java +++ b/src/jalview/ws/params/simple/IntegerParameter.java @@ -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; } }; } diff --git a/src/jalview/ws/params/simple/LogarithmicParameter.java b/src/jalview/ws/params/simple/LogarithmicParameter.java index 91ed03a..01744e7 100644 --- a/src/jalview/ws/params/simple/LogarithmicParameter.java +++ b/src/jalview/ws/params/simple/LogarithmicParameter.java @@ -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; } diff --git a/src/jalview/ws/params/simple/Option.java b/src/jalview/ws/params/simple/Option.java index 653359f..f0126df 100644 --- a/src/jalview/ws/params/simple/Option.java +++ b/src/jalview/ws/params/simple/Option.java @@ -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 possibleVals = new ArrayList(); + /* + * default value in string format, or "null" if undefined + */ + String defvalue; + + String description; + + ArrayList 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) opt.possibleVals.clone(); @@ -113,7 +130,7 @@ public class Option implements OptionI this.defvalue = defValue; if (possibleVals != null) { - this.possibleVals = new ArrayList(); + 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; + } } diff --git a/test/jalview/hmmer/HMMERTest.java b/test/jalview/hmmer/HMMERTest.java index 8f96d04..e3b7067 100644 --- a/test/jalview/hmmer/HMMERTest.java +++ b/test/jalview/hmmer/HMMERTest.java @@ -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 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()); 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 index 0000000..bc9c2e4 --- /dev/null +++ b/test/jalview/renderer/OverviewRendererTest.java @@ -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()); + } +} diff --git a/test/jalview/renderer/seqfeatures/FeatureRendererTest.java b/test/jalview/renderer/seqfeatures/FeatureRendererTest.java index cebef11..da7cada 100644 --- a/test/jalview/renderer/seqfeatures/FeatureRendererTest.java +++ b/test/jalview/renderer/seqfeatures/FeatureRendererTest.java @@ -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") diff --git a/test/jalview/schemes/HmmerGlobalBackgroundTest.java b/test/jalview/schemes/HmmerGlobalBackgroundTest.java index 13bf47b..1cdee91 100644 --- a/test/jalview/schemes/HmmerGlobalBackgroundTest.java +++ b/test/jalview/schemes/HmmerGlobalBackgroundTest.java @@ -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); /* diff --git a/test/jalview/schemes/HmmerLocalBackgroundTest.java b/test/jalview/schemes/HmmerLocalBackgroundTest.java index 7467ab2..5f2bb8f 100644 --- a/test/jalview/schemes/HmmerLocalBackgroundTest.java +++ b/test/jalview/schemes/HmmerLocalBackgroundTest.java @@ -37,7 +37,6 @@ public class HmmerLocalBackgroundTest { AnnotatedCollectionI ac = new Alignment( new SequenceI[] { hmmSeq, seq1, seq2 }); - ac.setHmmConsensus(hmmSeq); ColourSchemeI scheme = new HmmerLocalBackground(ac); /* diff --git a/test/jalview/ws/gui/Jws2ParamView.java b/test/jalview/ws/gui/Jws2ParamView.java index 80b48c3..134fbd1 100644 --- a/test/jalview/ws/gui/Jws2ParamView.java +++ b/test/jalview/ws/gui/Jws2ParamView.java @@ -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 serviceTests = new ArrayList(); + public static List serviceTests = new ArrayList<>(); /** * which presets to test for services */ - public static List presetTests = new ArrayList(); + public static List 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) 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(); diff --git a/utils/i18nAnt.xml b/utils/i18nAnt.xml index 01973d2..ab53613 100755 --- a/utils/i18nAnt.xml +++ b/utils/i18nAnt.xml @@ -36,7 +36,7 @@ - + -- 1.7.10.2