X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAlignFrame.java;h=a429eceb3b1b850ea6550c5b5842979413722e56;hb=0d519ae0c45b0b9962b4589e84c262a71bb2f346;hp=a2336a0e1283da95811d6c3703be97bc7b193c76;hpb=7e82e1fed011077e5cd4cc40ac8ad3519d7c47a8;p=jalview.git diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index a2336a0..a429ece 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -24,6 +24,7 @@ import jalview.analysis.AlignmentSorter; import jalview.analysis.AlignmentUtils; import jalview.analysis.CrossRef; import jalview.analysis.Dna; +import jalview.analysis.GeneticCodeI; import jalview.analysis.ParseProperties; import jalview.analysis.SequenceIdMatcher; import jalview.api.AlignExportSettingI; @@ -62,8 +63,16 @@ import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.gui.ColourMenuHelper.ColourChangeListener; import jalview.gui.ViewSelectionMenu.ViewSetProvider; +import jalview.hmmer.HMMAlign; +import jalview.hmmer.HMMBuild; +import jalview.hmmer.HMMERParamStore; +import jalview.hmmer.HMMERPreset; +import jalview.hmmer.HMMSearch; +import jalview.hmmer.HmmerCommand; +import jalview.hmmer.JackHMMER; import jalview.io.AlignmentProperties; import jalview.io.AnnotationFile; +import jalview.io.BackupFiles; import jalview.io.BioJsHTMLOutput; import jalview.io.DataSourceType; import jalview.io.FileFormat; @@ -95,6 +104,9 @@ import jalview.ws.DBRefFetcher.FetchFinishedListenerI; import jalview.ws.jws1.Discoverer; import jalview.ws.jws2.Jws2Discoverer; import jalview.ws.jws2.jabaws2.Jws2Instance; +import jalview.ws.params.ArgumentI; +import jalview.ws.params.ParamDatastoreI; +import jalview.ws.params.WsParamSetI; import jalview.ws.seqfetcher.DbSourceProxy; import java.awt.BorderLayout; @@ -124,22 +136,26 @@ import java.awt.print.PrinterJob; import java.beans.PropertyChangeEvent; import java.io.File; import java.io.FileWriter; +import java.io.IOException; import java.io.PrintWriter; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Deque; -import java.util.Enumeration; -import java.util.Hashtable; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.Vector; +import javax.swing.ButtonGroup; import javax.swing.JCheckBoxMenuItem; import javax.swing.JEditorPane; +import javax.swing.JFileChooser; import javax.swing.JInternalFrame; import javax.swing.JLayeredPane; import javax.swing.JMenu; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; @@ -152,7 +168,6 @@ import javax.swing.SwingUtilities; public class AlignFrame extends GAlignFrame implements DropTargetListener, IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener { - public static final int DEFAULT_WIDTH = 700; public static final int DEFAULT_HEIGHT = 500; @@ -178,6 +193,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, */ String fileName = null; + /** * Creates a new AlignFrame object with specific width and height. * @@ -762,6 +778,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, ap.av.updateConservation(ap); ap.av.updateConsensus(ap); ap.av.updateStrucConsensus(ap); + ap.av.initInformationWorker(ap); } } @@ -904,6 +921,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, showConsensusHistogram.setSelected(av.isShowConsensusHistogram()); showSequenceLogo.setSelected(av.isShowSequenceLogo()); normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo()); + showInformationHistogram.setSelected(av.isShowInformationHistogram()); + showHMMSequenceLogo.setSelected(av.isShowHMMSequenceLogo()); + normaliseHMMSequenceLogo.setSelected(av.isNormaliseHMMSequenceLogo()); ColourMenuHelper.setColourSelected(colourMenu, av.getGlobalColourScheme()); @@ -963,10 +983,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, return progressBar.operationInProgress(); } + /** + * Sets the text of the status bar. Note that setting a null or empty value + * will cause the status bar to be hidden, with possibly undesirable flicker + * of the screen layout. + */ @Override public void setStatus(String text) { - statusBar.setText(text); + statusBar.setText(text == null || text.isEmpty() ? " " : text); } /* @@ -995,6 +1020,258 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } @Override + public void hmmBuild_actionPerformed(boolean withDefaults) + { + if (!alignmentIsSufficient(1)) + { + return; + } + + /* + * 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(); + WsJobParameters params = new WsJobParameters(store, set, args); + if (params.showRunDialog()) + { + args = params.getJobParams(); + } + else + { + return; // user cancelled + } + } + new Thread(new HMMBuild(this, args)).start(); + } + + @Override + public void hmmAlign_actionPerformed(boolean withDefaults) + { + if (!(checkForHMM() && alignmentIsSufficient(2))) + { + return; + } + + /* + * 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(); + WsJobParameters params = new WsJobParameters(store, set, args); + if (params.showRunDialog()) + { + args = params.getJobParams(); + } + else + { + return; // user cancelled + } + } + new Thread(new HMMAlign(this, args)).start(); + } + + @Override + public void hmmSearch_actionPerformed(boolean withDefaults) + { + if (!checkForHMM()) + { + return; + } + + /* + * 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(); + WsJobParameters params = new WsJobParameters(store, set, args); + if (params.showRunDialog()) + { + args = params.getJobParams(); + } + else + { + return; // user cancelled + } + } + new Thread(new HMMSearch(this, args)).start(); + alignPanel.repaint(); + } + + @Override + public void jackhmmer_actionPerformed(boolean withDefaults) + { + + /* + * get default parameters, and (if requested) show + * dialog to allow modification + */ + + ParamDatastoreI store = HMMERParamStore.forJackhmmer(viewport); + List args = store.getServiceParameters(); + + if (!withDefaults) + { + WsParamSetI set = new HMMERPreset(); + WsJobParameters params = new WsJobParameters(store, set, args); + if (params.showRunDialog()) + { + args = params.getJobParams(); + } + else + { + return; // user cancelled + } + } + new Thread(new JackHMMER(this, args)).start(); + alignPanel.repaint(); + + } + + /** + * 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 (viewport.getAlignment().getHmmSequences().isEmpty()) + { + JOptionPane.showMessageDialog(this, + MessageManager.getString("warn.no_hmm")); + return false; + } + return true; + } + + @Override + protected void filterByEValue_actionPerformed() + { + viewport.filterByEvalue(inputDouble("Enter E-Value Cutoff")); + } + + @Override + protected void filterByScore_actionPerformed() + { + viewport.filterByScore(inputDouble("Enter Bit Score Threshold")); + } + + private double inputDouble(String message) + { + String str = null; + Double d = null; + while(d == null || d <= 0) + { + str = JOptionPane.showInputDialog(this.alignPanel, message); + try + { + d = Double.valueOf(str); + } + catch (NumberFormatException e) + { + } + } + return d; + } + + /** + * Checks if the alignment contains the required number of sequences. + * + * @param required + * @return + */ + public boolean alignmentIsSufficient(int required) + { + if (getViewport().getSequenceSelection().length < required) + { + JOptionPane.showMessageDialog(this, + MessageManager.getString("label.not_enough_sequences")); + return false; + } + return true; + } + + /** + * Opens a file browser and adds the selected file, if in Fasta, Stockholm or + * Pfam format, to the list held under preference key "HMMSEARCH_DBS" (as a + * comma-separated list) + */ + @Override + public void addDatabase_actionPerformed() throws IOException + { + if (Cache.getProperty(Preferences.HMMSEARCH_DBS) == null) + { + Cache.setProperty(Preferences.HMMSEARCH_DBS, ""); + } + + String path = openFileChooser(false); + if (path != null && new File(path).exists()) + { + IdentifyFile identifier = new IdentifyFile(); + FileFormatI format = identifier.identify(path, DataSourceType.FILE); + if (format == FileFormat.Fasta || format == FileFormat.Stockholm + || format == FileFormat.Pfam) + { + String currentDbPaths = Cache + .getProperty(Preferences.HMMSEARCH_DBS); + currentDbPaths += Preferences.COMMA + path; + Cache.setProperty(Preferences.HMMSEARCH_DBS, currentDbPaths); + } + else + { + JOptionPane.showMessageDialog(this, + MessageManager.getString("warn.invalid_format")); + } + } + } + + /** + * Opens a file chooser, optionally restricted to selecting folders + * (directories) only. Answers the path to the selected file or folder, or + * null if none is chosen. + * + * @param + * @return + */ + protected String openFileChooser(boolean forFolder) + { + // TODO duplicates GPreferences method - relocate to JalviewFileChooser? + String choice = null; + JFileChooser chooser = new JFileChooser(); + if (forFolder) + { + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + } + chooser.setDialogTitle( + MessageManager.getString("label.open_local_file")); + chooser.setToolTipText(MessageManager.getString("action.open")); + + int value = chooser.showOpenDialog(this); + + if (value == JFileChooser.APPROVE_OPTION) + { + choice = chooser.getSelectedFile().getPath(); + } + return choice; + } + + @Override public void reload_actionPerformed(ActionEvent e) { if (fileName != null) @@ -1154,7 +1431,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, shortName.lastIndexOf(java.io.File.separatorChar) + 1); } - success = new Jalview2XML().saveAlignment(this, file, shortName); + success = new jalview.project.Jalview2XML().saveAlignment(this, file, + shortName); statusBar.setText(MessageManager.formatMessage( "label.successfully_saved_to_file_in_format", new Object[] @@ -1186,9 +1464,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } else { + // create backupfiles object and get new temp filename destination + BackupFiles backupfiles = new BackupFiles(file); + try { - PrintWriter out = new PrintWriter(new FileWriter(file)); + PrintWriter out = new PrintWriter( + new FileWriter(backupfiles.getTempFilePath())); out.print(output); out.close(); @@ -1201,6 +1483,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, success = false; ex.printStackTrace(); } + + backupfiles.setWriteSuccess(success); + // do the backup file roll and rename the temp file to actual file + success = backupfiles.rollBackupsAndRenameTempFile(); + } } @@ -1403,6 +1690,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, @Override public void associatedData_actionPerformed(ActionEvent e) + throws IOException, InterruptedException { // Pick the tree file JalviewFileChooser chooser = new JalviewFileChooser( @@ -1888,9 +2176,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * * @param e * DOCUMENT ME! + * @throws InterruptedException + * @throws IOException */ @Override protected void pasteNew_actionPerformed(ActionEvent e) + throws IOException, InterruptedException { paste(true); } @@ -1900,9 +2191,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * * @param e * DOCUMENT ME! + * @throws InterruptedException + * @throws IOException */ @Override protected void pasteThis_actionPerformed(ActionEvent e) + throws IOException, InterruptedException { paste(false); } @@ -1912,8 +2206,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * * @param newAlignment * true to paste to a new alignment, otherwise add to this. + * @throws InterruptedException + * @throws IOException */ - void paste(boolean newAlignment) + void paste(boolean newAlignment) throws IOException, InterruptedException { boolean externalPaste = true; try @@ -2074,7 +2370,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, newGraphGroups.add(q, null); } newGraphGroups.set(newann.graphGroup, - new Integer(++fgroup)); + Integer.valueOf(++fgroup)); } newann.graphGroup = newGraphGroups.get(newann.graphGroup) .intValue(); @@ -2121,7 +2417,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, newGraphGroups.add(q, null); } newGraphGroups.set(newann.graphGroup, - new Integer(++fgroup)); + Integer.valueOf(++fgroup)); } newann.graphGroup = newGraphGroups.get(newann.graphGroup) .intValue(); @@ -2241,7 +2537,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, System.out.println("Exception whilst pasting: " + ex); // could be anything being pasted in here } - } @Override @@ -2397,15 +2692,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, @Override public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e) { - SequenceGroup sg = new SequenceGroup(); - - for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++) - { - sg.addSequence(viewport.getAlignment().getSequenceAt(i), false); - } + SequenceGroup sg = new SequenceGroup( + viewport.getAlignment().getSequences()); sg.setEndRes(viewport.getAlignment().getWidth() - 1); viewport.setSelectionGroup(sg); + viewport.isSelectionGroupChanged(true); viewport.sendSelection(); // JAL-2034 - should delegate to // alignPanel to decide if overview needs @@ -2701,7 +2993,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, /* * Create a new AlignmentPanel (with its own, new Viewport) */ - AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel); + AlignmentPanel newap = new jalview.project.Jalview2XML() + .copyAlignPanel(alignPanel); if (!copyAnnotation) { /* @@ -2726,6 +3019,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, newap.av.setRedoList(viewport.getRedoList()); /* + * copy any visualisation settings that are not saved in the project + */ + newap.av.setColourAppliesToAllGroups( + viewport.getColourAppliesToAllGroups()); + + /* * Views share the same mappings; need to deregister any new mappings * created by copyAlignPanel, and register the new reference to the shared * mappings @@ -2888,7 +3187,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, viewport.setFollowHighlight(state); if (state) { - alignPanel.scrollToPosition(viewport.getSearchResults(), false); + alignPanel.scrollToPosition(viewport.getSearchResults()); } } @@ -3035,6 +3334,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, viewport.expandColSelection(sg, false); viewport.hideAllSelectedSeqs(); viewport.hideSelectedColumns(); + alignPanel.updateLayout(); alignPanel.paintAlignment(true, true); viewport.sendSelection(); } @@ -3059,6 +3359,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, public void hideSelColumns_actionPerformed(ActionEvent e) { viewport.hideSelectedColumns(); + alignPanel.updateLayout(); alignPanel.paintAlignment(true, true); viewport.sendSelection(); } @@ -3080,7 +3381,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, protected void scaleAbove_actionPerformed(ActionEvent e) { viewport.setScaleAboveWrapped(scaleAbove.isSelected()); - // TODO: do we actually need to update overview for scale above change ? + alignPanel.updateLayout(); alignPanel.paintAlignment(true, false); } @@ -3094,6 +3395,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, protected void scaleLeft_actionPerformed(ActionEvent e) { viewport.setScaleLeftWrapped(scaleLeft.isSelected()); + alignPanel.updateLayout(); alignPanel.paintAlignment(true, false); } @@ -3107,6 +3409,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, protected void scaleRight_actionPerformed(ActionEvent e) { viewport.setScaleRightWrapped(scaleRight.isSelected()); + alignPanel.updateLayout(); alignPanel.paintAlignment(true, false); } @@ -3328,6 +3631,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * otherwise set the chosen colour scheme (or null for 'None') */ ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name, + viewport, viewport.getAlignment(), viewport.getHiddenRepSequences()); changeColour(cs); } @@ -3691,35 +3995,33 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } if (viewport.getAlignment().getAlignmentAnnotation() - .hashCode() != _annotationScoreVectorHash) + .hashCode() == _annotationScoreVectorHash) + { + return; + } + + sortByAnnotScore.removeAll(); + Set scoreSorts = new HashSet<>(); + for (SequenceI sqa : viewport.getAlignment().getSequences()) { - sortByAnnotScore.removeAll(); - // almost certainly a quicker way to do this - but we keep it simple - Hashtable scoreSorts = new Hashtable(); - AlignmentAnnotation aann[]; - for (SequenceI sqa : viewport.getAlignment().getSequences()) + AlignmentAnnotation[] anns = sqa.getAnnotation(); + for (int i = 0; anns != null && i < anns.length; i++) { - aann = sqa.getAnnotation(); - for (int i = 0; aann != null && i < aann.length; i++) + AlignmentAnnotation aa = anns[i]; + if (aa != null && aa.hasScore() && aa.sequenceRef != null) { - if (aann[i].hasScore() && aann[i].sequenceRef != null) - { - scoreSorts.put(aann[i].label, aann[i].label); - } + scoreSorts.add(aa.label); } } - Enumeration labels = scoreSorts.keys(); - while (labels.hasMoreElements()) - { - addSortByAnnotScoreMenuItem(sortByAnnotScore, - (String) labels.nextElement()); - } - sortByAnnotScore.setVisible(scoreSorts.size() > 0); - scoreSorts.clear(); - - _annotationScoreVectorHash = viewport.getAlignment() - .getAlignmentAnnotation().hashCode(); } + for (String label : scoreSorts) + { + addSortByAnnotScoreMenuItem(sortByAnnotScore, label); + } + sortByAnnotScore.setVisible(!scoreSorts.isEmpty()); + + _annotationScoreVectorHash = viewport.getAlignment() + .getAlignmentAnnotation().hashCode(); } /** @@ -4260,14 +4562,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * frame's DNA sequences to their aligned protein (amino acid) equivalents. */ @Override - public void showTranslation_actionPerformed(ActionEvent e) + public void showTranslation_actionPerformed(GeneticCodeI codeTable) { AlignmentI al = null; try { Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true)); - al = dna.translateCdna(); + al = dna.translateCdna(codeTable); } catch (Exception ex) { jalview.bin.Cache.log.error( @@ -4296,7 +4598,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, af.setFileFormat(this.currentFileFormat); final String newTitle = MessageManager .formatMessage("label.translation_of_params", new Object[] - { this.getTitle() }); + { this.getTitle(), codeTable.getId() }); af.setTitle(newTitle); if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true)) { @@ -4464,7 +4766,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, int assocfiles = 0; if (filesmatched.size() > 0) { - boolean autoAssociate = Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false); + boolean autoAssociate = Cache + .getDefault("AUTOASSOCIATE_PDBANDSEQS", false); if (!autoAssociate) { String msg = MessageManager.formatMessage( @@ -4559,6 +4862,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * * @param file * either a filename or a URL string. + * @throws InterruptedException + * @throws IOException */ public void loadJalviewDataFile(String file, DataSourceType sourceType, FileFormatI format, SequenceI assocSeq) @@ -4665,7 +4970,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } if (isAnnotation) { - alignPanel.adjustAnnotationHeight(); viewport.updateSequenceIdColours(); buildSortByAnnotationScoresMenu(); @@ -5284,7 +5588,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, { PaintRefresher.Refresh(this, viewport.getSequenceSetId()); alignPanel.updateAnnotation(); - alignPanel.paintAlignment(true, true); + alignPanel.paintAlignment(true, + viewport.needToUpdateStructureViews()); } } @@ -5399,7 +5704,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, */ public List getAlignPanels() { - return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels; + // alignPanels is never null + // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels; + return alignPanels; } /** @@ -5568,15 +5875,16 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, colourMenu.add(textColour); colourMenu.addSeparator(); - ColourMenuHelper.addMenuItems(colourMenu, this, viewport.getAlignment(), - false); + ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this, + viewport.getAlignment(), false); + colourMenu.add(annotationColour); + bg.add(annotationColour); colourMenu.addSeparator(); colourMenu.add(conservationMenuItem); colourMenu.add(modifyConservation); colourMenu.add(abovePIDThreshold); colourMenu.add(modifyPID); - colourMenu.add(annotationColour); ColourSchemeI colourScheme = viewport.getGlobalColourScheme(); ColourMenuHelper.setColourSelected(colourMenu, colourScheme); @@ -5594,6 +5902,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } } + /** + * Sets the status of the HMMER menu + */ + public void updateHMMERStatus() + { + hmmerMenu.setEnabled(HmmerCommand.isHmmerAvailable()); + } + @Override protected void loadVcf_actionPerformed() {