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;
import javax.swing.JComboBox;
import javax.swing.JLabel;
-import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
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;
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;
{
private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
+ /**
+ * warn user if need to fetch more than this many uniprot records at once
+ */
+ private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
+
private SequenceI selectedSequence;
private SequenceI[] selectedSequences;
private String selectedPdbFileName;
+ private TFType localPdbTempfacType;
+
+ private String localPdbPaeMatrixFileName;
+
private boolean isValidPBDEntry;
private boolean cachedPDBExists;
List<SequenceI> 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();
this.selectedSequence = selectedSeq;
this.selectedSequences = selectedSeqs;
this.progressIndicator = (ap == null) ? null : ap.alignFrame;
+ this.showChooserGUI = showGUI;
init();
}
@Override
public void actionPerformed(ActionEvent e)
{
- promptForTDBFetch();
+ promptForTDBFetch(false);
}
});
Executors.defaultThreadFactory().newThread(new Runnable()
{
+ @Override
public void run()
{
populateSeqsWithoutSourceDBRef();
populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
discoverStructureViews();
updateProgressIndicator(null, startTime);
- mainFrame.setVisible(true);
+ mainFrame.setVisible(showChooserGUI);
updateCurrentView();
}
- private void promptForTDBFetch()
+ /**
+ * raises dialog for Uniprot fetch followed by 3D beacons search
+ *
+ * @param ignoreGui
+ * - when true, don't ask, just fetch
+ */
+ public void promptForTDBFetch(boolean ignoreGui)
{
final long progressId = System.currentTimeMillis();
{
mainFrame.setEnabled(false);
cmb_filterOption.setEnabled(false);
- progressBar.setProgressBar(MessageManager.getString("status.searching_3d_beacons"), progressId);
+ progressBar.setProgressBar(
+ MessageManager.getString("status.searching_3d_beacons"),
+ progressId);
+ btn_queryTDB.setEnabled(false);
// TODO: warn if no accessions discovered
populateSeqsWithoutSourceDBRef();
// redo initial discovery - this time with 3d beacons
// Executors.
- previousWantedFields=null;
+ previousWantedFields = null;
+ lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
+ cmb_filterOption.setSelectedItem(null);
+ cachedPDBExists = false; // reset to initial
initialStructureDiscovery();
if (!isStructuresDiscovered())
{
- progressBar.setProgressBar(MessageManager.getString("status.no_structures_discovered_from_3d_beacons"), progressId);
- btn_queryTDB.setToolTipText(MessageManager.getString("status.no_structures_discovered_from_3d_beacons"));
+ progressBar.setProgressBar(MessageManager.getString(
+ "status.no_structures_discovered_from_3d_beacons"),
+ progressId);
+ btn_queryTDB.setToolTipText(MessageManager.getString(
+ "status.no_structures_discovered_from_3d_beacons"));
btn_queryTDB.setEnabled(false);
- } else {
+ pnl_queryTDB.setVisible(false);
+ }
+ else
+ {
+ cmb_filterOption.setSelectedIndex(0); // select 'best'
btn_queryTDB.setVisible(false);
+ pnl_queryTDB.setVisible(false);
progressBar.setProgressBar(null, progressId);
}
mainFrame.setEnabled(true);
final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
{
-
+
@Override
public void finished()
{
notQueriedTDBYet = false;
// new thread to discover structures - via 3d beacons
Executors.defaultThreadFactory().newThread(strucDiscovery).start();
-
+
}
};
-
+
// 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() {
- public void run() {
- if (lastSelected!=null) {
- cmb_filterOption.setSelectedItem(lastSelected);
- }
- };
+ final Callable revertview = () -> {
+ if (lastSelected != null)
+ {
+ 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);
+ if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
+ {
+ Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
+ return;
+ }
// need cancel and no to result in the discoverPDB action - mocked is
- // 'cancel'
- JvOptionPane.newOptionDialog(this)
+ // 'cancel' TODO: mock should be OK
+
+ StructureChooser thisSC = this;
+ JvOptionPane.newOptionDialog(thisSC.getFrame())
.setResponseHandler(JvOptionPane.OK_OPTION,
discoverCanonicalDBrefs)
.setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
MessageManager.formatMessage(
"label.fetch_references_for_3dbeacons",
seqsWithoutSourceDBRef.size()),
- MessageManager
- .getString("label.3dbeacons"),
+ 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"));
+ MessageManager.getString("action.ok"), false);
}
/**
// TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
// StructureChooser
// works
- jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
- jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
- chooser.setFileView(new jalview.io.JalviewFileView());
+ JalviewFileChooser chooser = new JalviewFileChooser(
+ Cache.getProperty("LAST_DIRECTORY"));
+ chooser.setFileView(new JalviewFileView());
chooser.setDialogTitle(
MessageManager.formatMessage("label.select_pdb_file_for",
selectedSequence.getDisplayId(false)));
selectedSequence.getDisplayId(false)));
int value = chooser.showOpenDialog(null);
- if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
+ if (value == JalviewFileChooser.APPROVE_OPTION)
{
selectedPdbFileName = chooser.getSelectedFile().getPath();
- jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
+ 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
*/
if (canQueryTDB && notQueriedTDBYet)
{
btn_queryTDB.setVisible(true);
+ pnl_queryTDB.setVisible(true);
}
if (cachedPDBExist)
{
FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
.getSelectedItem());
-
+
if (lastSelected == selectedFilterOpt)
{
// don't need to do anything, probably
String filterTitle = mainFrame.getTitle();
mainFrame.setTitle(frameTitle);
chk_invertFilter.setVisible(false);
-
+
if (selectedFilterOpt.getView() == VIEWS_FILTER)
{
mainFrame.setTitle(filterTitle);
FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
.getSelectedItem());
String currentView = selectedFilterOpt.getView();
-
- if (currentView == VIEWS_FILTER && data instanceof ThreeDBStructureChooserQuerySource)
+
+ if (currentView == VIEWS_FILTER
+ && data instanceof ThreeDBStructureChooserQuerySource)
{
-
- TDB_FTSData row=((ThreeDBStructureChooserQuerySource)data).getFTSDataFor(getResultTable(), selectedRow, discoveredStructuresSet);
- String pageUrl = row.getModelViewUrl();
+
+ TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
+ .getFTSDataFor(getResultTable(), selectedRow,
+ discoveredStructuresSet);
+ String pageUrl = row.getModelViewUrl();
JPopupMenu popup = new JPopupMenu("3D Beacons");
JMenuItem viewUrl = new JMenuItem("View model web page");
- viewUrl.addActionListener(
- new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- Desktop.showUrl(pageUrl);
- }
- }
- );
+ viewUrl.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ Desktop.showUrl(pageUrl);
+ }
+ });
popup.add(viewUrl);
- SwingUtilities.invokeLater(new Runnable() {
- public void run() { popup.show(getResultTable(), x, y); }
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ popup.show(getResultTable(), x, y);
+ }
});
return true;
}
// event not handled by us
return false;
}
+
/**
* Validates inputs from the Manual PDB entry panel
*/
{
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-")))
{
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
{
validateSelections();
}
- private FilterOption lastSelected=null;
+
+ private FilterOption lastSelected = null;
+
/**
* Handles the state change event for the 'filter' combo-box and 'invert'
* check-box
if (pdbIdStr.split(":").length > 1)
{
pdbEntry.setId(pdbIdStr.split(":")[0]);
- pdbEntry.setChainCode(pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
+ pdbEntry.setChainCode(
+ pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
}
else
{
}
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 });
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());
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);
{
if (selectedSequences != null)
{
+ lbl_loading.setVisible(true);
Thread refreshThread = new Thread(new Runnable()
{
@Override
filterResultSet(
((FilterOption) cmb_filterOption.getSelectedItem())
.getValue());
+ lbl_loading.setVisible(false);
}
});
refreshThread.start();
@Override
public void setProgressBar(String message, long id)
{
- progressBar.setProgressBar(message, id);
+ if (!Platform.isHeadless())
+ progressBar.setProgressBar(message, id);
}
@Override
&& mainFrame.isVisible()
&& cmb_filterOption.getSelectedItem() != null;
}
+
/**
*
* @return true if the 3D-Beacons query button will/has been displayed
*/
- public boolean isCanQueryTDB() {
- return canQueryTDB;
+ public boolean isCanQueryTDB()
+ {
+ return canQueryTDB;
}
public boolean isNotQueriedTDBYet()
{
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();
+ }
}