X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FStructureChooser.java;h=e2eaabdffb6a9d0f388a24bca7cc169679b972d4;hb=7e3a6674abdd31bf48e7e249a74eff50fd2ce589;hp=246d162cf0f0fbdb95a059c9a83fa6963622b00a;hpb=2123f8ad0cc51b9f58d5d2820fa54ed03a8f3b22;p=jalview.git diff --git a/src/jalview/gui/StructureChooser.java b/src/jalview/gui/StructureChooser.java index 246d162..e2eaabd 100644 --- a/src/jalview/gui/StructureChooser.java +++ b/src/jalview/gui/StructureChooser.java @@ -24,12 +24,14 @@ package jalview.gui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; +import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; +import java.util.concurrent.Callable; import java.util.concurrent.Executors; import javax.swing.JCheckBox; @@ -41,12 +43,15 @@ import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; +import com.stevesoft.pat.Regex; + import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; import jalview.bin.Console; import jalview.bin.Jalview; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; +import jalview.ext.jmol.JmolParser; import jalview.fts.api.FTSData; import jalview.fts.api.FTSDataColumnI; import jalview.fts.api.FTSRestClientI; @@ -59,11 +64,16 @@ 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; @@ -104,6 +114,10 @@ public class StructureChooser extends GStructureChooser private String selectedPdbFileName; + private TFType localPdbTempfacType; + + private String localPdbPaeMatrixFileName; + private boolean isValidPBDEntry; private boolean cachedPDBExists; @@ -116,11 +130,19 @@ public class StructureChooser extends GStructureChooser List seqsWithoutSourceDBRef = null; + private boolean showChooserGUI = true; + private static StructureViewer lastTargetedView = null; public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq, AlignmentPanel ap) { + this(selectedSeqs, selectedSeq, ap, true); + } + + public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq, + AlignmentPanel ap, boolean showGUI) + { // which FTS engine to use data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs); initDialog(); @@ -129,6 +151,7 @@ public class StructureChooser extends GStructureChooser this.selectedSequence = selectedSeq; this.selectedSequences = selectedSeqs; this.progressIndicator = (ap == null) ? null : ap.alignFrame; + this.showChooserGUI = showGUI; init(); } @@ -244,7 +267,7 @@ public class StructureChooser extends GStructureChooser populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists); discoverStructureViews(); updateProgressIndicator(null, startTime); - mainFrame.setVisible(true); + mainFrame.setVisible(showChooserGUI); updateCurrentView(); } @@ -316,74 +339,64 @@ public class StructureChooser extends GStructureChooser }; // fetch db refs if OK pressed - final Runnable discoverCanonicalDBrefs = new Runnable() - { - @Override - public void run() + final Callable discoverCanonicalDBrefs = () -> { + btn_queryTDB.setEnabled(false); + populateSeqsWithoutSourceDBRef(); + + final int y = seqsWithoutSourceDBRef.size(); + if (y > 0) { - populateSeqsWithoutSourceDBRef(); + final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef + .toArray(new SequenceI[y]); + DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef, + progressBar, new DbSourceProxy[] + { new jalview.ws.dbsources.Uniprot() }, null, false); + dbRefFetcher.addListener(afterDbRefFetch); + // ideally this would also gracefully run with callbacks - final int y = seqsWithoutSourceDBRef.size(); - if (y > 0) - { - final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef - .toArray(new SequenceI[y]); - DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef, - progressBar, new DbSourceProxy[] - { new jalview.ws.dbsources.Uniprot() }, null, false); - dbRefFetcher.addListener(afterDbRefFetch); - // ideally this would also gracefully run with callbacks - dbRefFetcher.fetchDBRefs(true); - } - else - { - // call finished action directly - afterDbRefFetch.finished(); - } + dbRefFetcher.fetchDBRefs(true); } - + else + { + // call finished action directly + afterDbRefFetch.finished(); + } + return null; }; - final Runnable revertview = new Runnable() - { - @Override - public void run() + final Callable revertview = () -> { + if (lastSelected != null) { - if (lastSelected != null) - { - cmb_filterOption.setSelectedItem(lastSelected); - } - }; + cmb_filterOption.setSelectedItem(lastSelected); + } + return null; }; int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD", THRESHOLD_WARN_UNIPROT_FETCH_NEEDED); Console.debug("Using Uniprot fetch threshold of " + threshold); - boolean runThread = false; if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold) { - runThread = true; + Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs); + return; } // need cancel and no to result in the discoverPDB action - mocked is // 'cancel' TODO: mock should be OK - if (!runThread) - { - int answer = JvOptionPane.showConfirmDialog(this, - MessageManager.formatMessage( - "label.fetch_references_for_3dbeacons", - seqsWithoutSourceDBRef.size()), - MessageManager.getString("label.3dbeacons"), - JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE); - runThread = (answer == JvOptionPane.OK_OPTION); - } - if (runThread) - { - Executors.defaultThreadFactory().newThread(discoverCanonicalDBrefs) - .start(); - return; - } - else - { - revertview.run(); - } + + StructureChooser thisSC = this; + JvOptionPane.newOptionDialog(thisSC.getFrame()) + .setResponseHandler(JvOptionPane.OK_OPTION, + discoverCanonicalDBrefs) + .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview) + .setResponseHandler(JvOptionPane.NO_OPTION, revertview) + .showDialog( + MessageManager.formatMessage( + "label.fetch_references_for_3dbeacons", + seqsWithoutSourceDBRef.size()), + MessageManager.getString("label.3dbeacons"), + JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE, + null, new Object[] + { MessageManager.getString("action.ok"), + MessageManager.getString("action.cancel") }, + MessageManager.getString("action.ok"), false); } /** @@ -654,9 +667,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))); @@ -665,15 +678,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 */ @@ -940,7 +1034,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-"))) { @@ -948,14 +1044,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 @@ -1140,17 +1266,44 @@ public class StructureChooser extends GStructureChooser } else if (currentView == VIEWS_FROM_FILE) { - SequenceI userSelectedSeq = ((AssociateSeqOptions) fileChooserAssSeqPanel - .getCmb_assSeq().getSelectedItem()).getSequence(); + TFType tft = (TFType) StructureChooser.this.combo_tempFacAs + .getSelectedItem(); + String paeFilename = StructureChooser.this.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; + PDBEntry fileEntry = new AssociatePdbFileWithSeq() + .associatePdbWithSeq(pdbFilename, DataSourceType.FILE, + selectedSequence, true, Desktop.instance, tft, + paeFilename); + + /* + SequenceI[] seqArray = new SequenceI[] { selectedSequence }; + + StructureFile sf = ssm.computeMapping(true, seqArray, null, + selectedPdbFileName, DataSourceType.FILE, null, tft, + paeFilename); + StructureMapping[] sm = ssm.getMapping(fileEntry.getFile()); + // DO SOMETHING WITH + File paeFile = paeFilename == null ? null : new File(paeFilename); + if (paeFilename != null && paeFile.exists()) + { + AlignmentI al = StructureChooser.this.ap.getAlignment(); + try + { + EBIAlfaFold.importPaeJSONAsContactMatrixToSequence(al, + paeFile, selectedSequence); + } catch (IOException | ParseException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + */ sViewer = launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap, new SequenceI[] { selectedSequence }); @@ -1236,6 +1389,10 @@ public class StructureChooser extends GStructureChooser for (SequenceI seq : sequences) { PDBEntry pdbe = pdbEntriesToView[p++]; + Console.debug( + "##### pdbe=" + pdbe == null ? null : pdbe.toString()); + Console.debug("##### pdbe.getFile()=" + pdbe == null ? null + : pdbe.getFile()); if (pdbe != null && pdbe.getFile() != null) { StructureMapping[] smm = ssm.getMapping(pdbe.getFile()); @@ -1283,6 +1440,7 @@ public class StructureChooser extends GStructureChooser setProgressBar(MessageManager.formatMessage( "status.fetching_3d_structures_for", pdbEntriesToView[0].getId()), progressId); + // Can we pass a pre-computeMappinged pdbFile? theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel); } setProgressBar(null, progressId); @@ -1391,6 +1549,7 @@ public class StructureChooser extends GStructureChooser { if (selectedSequences != null) { + lbl_loading.setVisible(true); Thread refreshThread = new Thread(new Runnable() { @Override @@ -1402,6 +1561,7 @@ public class StructureChooser extends GStructureChooser filterResultSet( ((FilterOption) cmb_filterOption.getSelectedItem()) .getValue()); + lbl_loading.setVisible(false); } }); refreshThread.start(); @@ -1522,7 +1682,8 @@ public class StructureChooser extends GStructureChooser @Override public void setProgressBar(String message, long id) { - progressBar.setProgressBar(message, id); + if (!Platform.isHeadless()) + progressBar.setProgressBar(message, id); } @Override @@ -1574,4 +1735,34 @@ public class StructureChooser extends GStructureChooser { return notQueriedTDBYet; } + + /** + * Open a single structure file for a given sequence + */ + public static void openStructureFileForSequence(AlignmentPanel ap, + SequenceI seq, File sFile) + { + // 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; + } + + StructureViewer sViewer = sc.launchStructureViewer(ssm, + new PDBEntry[] + { fileEntry }, ap, new SequenceI[] { seq }); + + sc.mainFrame.dispose(); + } }