X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FStructureChooser.java;h=2b16495d53a90b92ab16f5a8324ca5e621714516;hb=1d1edb58c9ee8baec12686a512eb18d97b9bdba1;hp=04cc94e044a1bad2001822a62ceac00e943dc870;hpb=b8f69c187f02cf7213b92b4882afe36c7c16a733;p=jalview.git diff --git a/src/jalview/gui/StructureChooser.java b/src/jalview/gui/StructureChooser.java index 04cc94e..2b16495 100644 --- a/src/jalview/gui/StructureChooser.java +++ b/src/jalview/gui/StructureChooser.java @@ -28,9 +28,11 @@ import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Executors; @@ -43,12 +45,20 @@ import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; +import com.stevesoft.pat.Regex; + +import jalview.analysis.AlignmentUtils; +import jalview.api.AlignmentViewPanel; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; import jalview.bin.Console; import jalview.bin.Jalview; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.ext.jmol.JmolParser; import jalview.fts.api.FTSData; import jalview.fts.api.FTSDataColumnI; import jalview.fts.api.FTSRestClientI; @@ -57,16 +67,21 @@ import jalview.fts.core.FTSRestRequest; import jalview.fts.core.FTSRestResponse; import jalview.fts.service.pdb.PDBFTSRestClient; import jalview.fts.service.threedbeacons.TDB_FTSData; +import jalview.gui.StructureViewer.ViewerType; import jalview.gui.structurechooser.PDBStructureChooserQuerySource; import jalview.gui.structurechooser.StructureChooserQuerySource; import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource; import jalview.io.DataSourceType; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; import jalview.jbgui.FilterOption; import jalview.jbgui.GStructureChooser; +import jalview.structure.StructureImportSettings.TFType; import jalview.structure.StructureMapping; import jalview.structure.StructureSelectionManager; import jalview.util.MessageManager; import jalview.util.Platform; +import jalview.util.StringUtils; import jalview.ws.DBRefFetcher; import jalview.ws.DBRefFetcher.FetchFinishedListenerI; import jalview.ws.seqfetcher.DbSourceProxy; @@ -107,6 +122,10 @@ public class StructureChooser extends GStructureChooser private String selectedPdbFileName; + private TFType localPdbTempfacType; + + private String localPdbPaeMatrixFileName; + private boolean isValidPBDEntry; private boolean cachedPDBExists; @@ -656,9 +675,9 @@ public class StructureChooser extends GStructureChooser // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and // StructureChooser // works - jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser( + JalviewFileChooser chooser = new JalviewFileChooser( Cache.getProperty("LAST_DIRECTORY")); - chooser.setFileView(new jalview.io.JalviewFileView()); + chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle( MessageManager.formatMessage("label.select_pdb_file_for", selectedSequence.getDisplayId(false))); @@ -667,15 +686,96 @@ public class StructureChooser extends GStructureChooser selectedSequence.getDisplayId(false))); int value = chooser.showOpenDialog(null); - if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION) + if (value == JalviewFileChooser.APPROVE_OPTION) { selectedPdbFileName = chooser.getSelectedFile().getPath(); Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName); + boolean guessTFType = localPdbPaeMatrixFileName == null; + localPdbPaeMatrixFileName = guessPAEFilename(); + guessTFType |= localPdbPaeMatrixFileName != null; + Regex alphaFold = JmolParser.getNewAlphafoldValidator(); + if (guessTFType + && alphaFold.search(new File(selectedPdbFileName).getName()) + && !tempFacAsChanged) + { + // localPdbPaeMatrixFileName was null and now isn't and filename could + // well be AlphaFold and user hasn't adjusted the tempFacType + combo_tempFacAs.setSelectedItem(TFType.PLDDT); + } validateSelections(); } } /** + * Handles action event for btn_pdbFromFile + */ + @Override + protected void paeMatrixFile_actionPerformed() + { + File pdbFile = new File(selectedPdbFileName); + String setFile = Cache.getProperty("LAST_DIRECTORY"); + if (localPdbPaeMatrixFileName != null) + { + File paeFile = new File(localPdbPaeMatrixFileName); + if (paeFile.exists()) + setFile = paeFile.getAbsolutePath(); + else if (paeFile.getParentFile().exists()) + setFile = paeFile.getParentFile().getAbsolutePath(); + } + else + { + String guess = guessPAEFilename(); + if (guess != null) + setFile = guess; + } + JalviewFileChooser chooser = new JalviewFileChooser(setFile); + chooser.setFileView(new JalviewFileView()); + chooser.setDialogTitle(MessageManager.formatMessage( + "label.select_pae_matrix_file_for", pdbFile.getName())); + chooser.setToolTipText(MessageManager.formatMessage( + "label.load_pae_matrix_file_associate_with_structure", + pdbFile.getName())); + + int value = chooser.showOpenDialog(null); + if (value == JalviewFileChooser.APPROVE_OPTION) + { + localPdbPaeMatrixFileName = chooser.getSelectedFile().getPath(); + Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName); + } + validateAssociationFromFile(); + } + + private String guessPAEFilename() + { + if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb") + || selectedPdbFileName.toLowerCase(Locale.ROOT) + .endsWith(".cif")) + { + String jsonExt = selectedPdbFileName.substring(0, + selectedPdbFileName.length() - 4) + ".json"; + // AlphaFold naming scheme + String guessFile1 = StringUtils.replaceLast(jsonExt, "model", + "predicted_aligned_error"); + // nf-core mode naming scheme + String guessFile2 = StringUtils.replaceLast(jsonExt, ".json", + "_scores.json"); + if (new File(guessFile1).exists()) + { + return guessFile1; + } + else if (new File(jsonExt).exists()) + { + return jsonExt; + } + else if (new File(guessFile2).exists()) + { + return guessFile2; + } + } + return null; + } + + /** * Populates the filter combo-box options dynamically depending on discovered * structures */ @@ -942,7 +1042,9 @@ public class StructureChooser extends GStructureChooser { AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel .getCmb_assSeq().getSelectedItem(); - lbl_fromFileStatus.setIcon(errorImage); + // lbl_fromFileStatus.setIcon(errorImage); + String pdbFileString = ""; + String pdbFileTooltip = ""; if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt .getName().equalsIgnoreCase("-Select Associated Seq-"))) { @@ -950,14 +1052,44 @@ public class StructureChooser extends GStructureChooser if (selectedPdbFileName != null && selectedPdbFileName.length() > 0) { btn_add.setEnabled(true); - lbl_fromFileStatus.setIcon(goodImage); + // lbl_fromFileStatus.setIcon(goodImage); + pdbFileString = new File(selectedPdbFileName).getName(); + pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath(); + setPdbOptionsEnabled(true); + } + else + { + pdbFileString = MessageManager.getString("label.none"); + pdbFileTooltip = MessageManager.getString("label.nothing_selected"); } } else { btn_pdbFromFile.setEnabled(false); - lbl_fromFileStatus.setIcon(errorImage); + // lbl_fromFileStatus.setIcon(errorImage); + pdbFileString = MessageManager.getString("label.none"); + pdbFileTooltip = MessageManager.getString("label.nothing_selected"); } + lbl_pdbFile.setText(pdbFileString); + lbl_pdbFile.setToolTipText(pdbFileTooltip); + + // PAE file choice + String paeFileString = ""; + String paeFileTooltip = ""; + if (localPdbPaeMatrixFileName != null + && localPdbPaeMatrixFileName.length() > 0) + { + paeFileString = new File(localPdbPaeMatrixFileName).getName(); + paeFileTooltip = new File(localPdbPaeMatrixFileName) + .getAbsolutePath(); + } + else + { + paeFileString = MessageManager.getString("label.none"); + paeFileTooltip = MessageManager.getString("label.nothing_selected"); + } + lbl_paeFile.setText(paeFileString); + lbl_paeFile.setToolTipText(paeFileTooltip); } @Override @@ -1142,20 +1274,19 @@ public class StructureChooser extends GStructureChooser } else if (currentView == VIEWS_FROM_FILE) { - SequenceI userSelectedSeq = ((AssociateSeqOptions) fileChooserAssSeqPanel - .getCmb_assSeq().getSelectedItem()).getSequence(); + StructureChooser sc = StructureChooser.this; + TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem(); + String paeFilename = sc.localPdbPaeMatrixFileName; + AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel + .getCmb_assSeq().getSelectedItem(); + SequenceI userSelectedSeq = assSeqOpt.getSequence(); if (userSelectedSeq != null) - { selectedSequence = userSelectedSeq; - } - PDBEntry fileEntry = new AssociatePdbFileWithSeq() - .associatePdbWithSeq(selectedPdbFileName, - DataSourceType.FILE, selectedSequence, true, - Desktop.instance); + String pdbFilename = selectedPdbFileName; - sViewer = launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, - ap, new SequenceI[] - { selectedSequence }); + StructureChooser.openStructureFileForSequence(ssm, sc, ap, + selectedSequence, true, pdbFilename, tft, paeFilename, + true); } SwingUtilities.invokeLater(new Runnable() { @@ -1214,6 +1345,15 @@ public class StructureChooser extends GStructureChooser StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView, final AlignmentPanel alignPanel, SequenceI[] sequences) { + return launchStructureViewer(ssm, pdbEntriesToView, alignPanel, + sequences, null); + } + + private StructureViewer launchStructureViewer( + StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView, + final AlignmentPanel alignPanel, SequenceI[] sequences, + ViewerType viewerType) + { long progressId = sequences.hashCode(); setProgressBar(MessageManager .getString("status.launching_3d_structure_viewer"), progressId); @@ -1278,14 +1418,17 @@ public class StructureChooser extends GStructureChooser MessageManager.getString( "status.fetching_3d_structures_for_selected_entries"), progressId); - theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel); + theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel, + viewerType); } else { setProgressBar(MessageManager.formatMessage( "status.fetching_3d_structures_for", pdbEntriesToView[0].getId()), progressId); - theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel); + // Can we pass a pre-computeMappinged pdbFile? + theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel, + viewerType); } setProgressBar(null, progressId); // remember the last viewer we used... @@ -1526,20 +1669,21 @@ public class StructureChooser extends GStructureChooser @Override public void setProgressBar(String message, long id) { - if (!Platform.isHeadless()) + if (!Platform.isHeadless() && progressBar != null) progressBar.setProgressBar(message, id); } @Override public void registerHandler(long id, IProgressIndicatorHandler handler) { - progressBar.registerHandler(id, handler); + if (progressBar != null) + progressBar.registerHandler(id, handler); } @Override public boolean operationInProgress() { - return progressBar.operationInProgress(); + return progressBar == null ? false : progressBar.operationInProgress(); } public JalviewStructureDisplayI getOpenedStructureViewer() @@ -1583,30 +1727,77 @@ public class StructureChooser extends GStructureChooser /** * Open a single structure file for a given sequence */ - public static void openStructureFileForSequence(AlignmentPanel ap, - SequenceI seq, File sFile) + public static void openStructureFileForSequence( + StructureSelectionManager ssm, StructureChooser sc, + AlignmentPanel ap, SequenceI seq, boolean prompt, + String sFilename, TFType tft, String paeFilename, + boolean doXferSettings) { - //Open the chooser headlessly. Not sure this is actually needed ? - StructureChooser sc = new StructureChooser(new SequenceI[] { seq }, seq, - ap, false); - StructureSelectionManager ssm = ap.getStructureSelectionManager(); - PDBEntry fileEntry = null; - try - { - fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq( - sFile.getAbsolutePath(), DataSourceType.FILE, seq, true, - Desktop.instance); - } catch (Exception e) - { - Console.error("Could not open structure file '" - + sFile.getAbsolutePath() + "'"); - return; + openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft, + paeFilename, false, true, doXferSettings, null); + } + + public static StructureViewer openStructureFileForSequence( + StructureSelectionManager ssm, StructureChooser sc, + AlignmentPanel ap, SequenceI seq, boolean prompt, + String sFilename, TFType tft, String paeFilename, + boolean forceHeadless, boolean showRefAnnotations, + boolean doXferSettings, ViewerType viewerType) + { + StructureViewer sv = null; + boolean headless = forceHeadless; + if (sc == null) + { + // headless = true; + prompt = false; + sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false); } + if (ssm == null) + { + ssm = ap.getStructureSelectionManager(); + } + + PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq( + sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance, + tft, paeFilename, doXferSettings); - StructureViewer sViewer = sc.launchStructureViewer(ssm, - new PDBEntry[] - { fileEntry }, ap, new SequenceI[] { seq }); + // if headless, "false" in the sc constructor above will avoid GUI behaviour + // in sc.launchStructureViewer() + if (!headless && !(viewerType == null)) + { + sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap, + new SequenceI[] + { seq }, viewerType); + } + + if (headless) + sc.mainFrame.dispose(); + + if (showRefAnnotations) + showReferenceAnnotationsForSequence(ap.alignFrame, seq); + + return sv; + } + + public static void showReferenceAnnotationsForSequence(AlignFrame af, + SequenceI sequence) + { + AlignViewport av = af.getCurrentView(); + AlignmentI al = av.getAlignment(); + + List forSequences = new ArrayList<>(); + forSequences.add(sequence); + final Map> candidates = new LinkedHashMap<>(); + AlignmentUtils.findAddableReferenceAnnotations(forSequences, null, + candidates, al); + final SequenceGroup selectionGroup = av.getSelectionGroup(); + AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup); + for (AlignmentViewPanel ap : af.getAlignPanels()) + { + // required to readjust the height and position of the PAE + // annotation + ap.adjustAnnotationHeight(); + } - sc.mainFrame.dispose(); } }