--- /dev/null
+<html>
+<!--
+ * 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 <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ -->
+<head>
+<title>Split Frame Views</title>
+</head>
+<body>
+<p><strong>Split Frame Views</strong></p>
+<p/></p>Coding DNA (cDNA) and its protein product can be displayed in a split view, with cDNA above and protein below. The two alignments are
+linked, with these features supported:
+<ul>
+<li>mouseover or scrolling of either alignment is followed by the other (unless you turn off <strong><a href="../menus/alwview.html">"View | Automatic Scrolling"</a></strong>)</li>
+<li>on selecting rows, columns or regions in one alignment, the corresponding selection is made in the other</li>
+<li>sequence ordering in one alignment (using the cursor, or <strong><a href="../calculate/sorting.html">"Calculate | Sort")</a></strong> is also applied to the other</li>
+<li>editing (gap insertion / deletion) in the protein alignment is reflected in the cDNA (but not vice versa)</li>
+<li>on <strong><a href="../calculations/tree.html">"Calculate Tree"</a></strong> in either alignment, grouping, colouring and sorting by tree are applied to both</li>
+<li>the <strong><a href="../menus/alwformat.html">"Format | Font"</a></strong> menu option has an option 'Scale protein residues to codons'; select this option to make each protein residue
+the same width as a DNA codon (so the alignments 'line up' vertically)</li>
+</ul>
+<p>An alignment annotation row on the protein alignment shows the <strong><a href="../calculations/consensus.html">cDNA consensus</a></strong> for each peptide column.<br/>
+This consensus may reveal variation in nucleotides coding for conserved protein residues.</p>
+
+<p><strong>Opening a Split Frame View</strong></p>
+<p>A Split Frame View can be opened in one of the following ways:</p>
+<p><strong><em>Add Sequences</em></strong></p>
+<p>If you add (coding) DNA sequences to an open peptide alignment, or vice versa, <em>and</em> at least one DNA sequence translates to one of the
+peptide sequences, then the option to open in a split window is offered. The DNA may include start and/or stop codons, but no non-coding (intron)
+sequence.</p>
+
+<p>This option is available in Jalview Desktop (when adding sequences by any supported method), and Jalview applet (adding from textbox).
+The additional options below apply to Jalview Desktop only.</p>
+
+<p><strong><em>Translate as cDNA</em></strong></p>
+<p>Menu option <strong><a href="../menus/alwcalculate.html">"Calculate | Translate as cDNA"</a></strong> is available for a nucleotide alignment. Selecting this option shows the DNA and its
+calculated protein product in a Split Frame view.</p>
+
+<p><strong><em>Get Cross-References</em></strong></p>
+<p>Menu option <strong><a href="../menus/alwcalculate.html">"Calculate | Get Cross-References"</a></strong> is available for fetched sequences which have cross-references to other databases.
+On selecting protein cross-references (for a cDNA alignment), or DNA xrefs (for peptide), a Split Frame view is opened showing cDNA and peptide.</p>
+
+<p><strong><em>Realign Split View</em></strong></p>
+<p>If you invoke a web service to realign either half of a Split Frame, then the resulting realignment is displayed in a new
+Split Frame.</p>
+<ul>
+<li>the alignment you chose to realign (for example, peptide) is displayed as aligned by the external web service</li>
+<li>Jalview 'aligns' its complement (in this case, cDNA) similarly, by inserting corresponding gaps
+ <ul>
+ <li>NB this is <em>not</em> the same as aligning the complement using the external service, which may give different results</li>
+ </ul>
+</li>
+</ul>
+
+
+<p><em>Split Frame Views were introduced in Jalview 2.?.?</em></p>
+</body>
+</html>
When selected, these numbers are parsed into sequence associated
annotation which can then be used to sort the alignment via the Sort
by→Score menu.</em> <br></li>
-
+ <li><strong>Translate as cDNA</strong> (not applet)<br><em>This option is visible for nucleotide alignments.
+ Selecting this option shows the DNA's calculated protein product in a new window. Note that the
+ translation is not frame- or intron-aware; it simply translates all codons in each sequence, using the
+ standard <a href="../misc/geneticCode.html">genetic code</a> (any incomplete final codon is discarded).
+ You can perform this action on the whole alignment,
+ or selected rows, columns, or regions.</em> <br></li>
+ <li><strong>Get Cross-References</strong> (not applet)<br><em>This option is visible where sequences have cross-references to
+ other standard databases; for example, an EMBL entry may have cross-references to one or more UNIPROT entries.
+ Select the database to view all cross-referenced sequences in a new window.</em> <br></li>
<li><strong>Autocalculate Consensus</strong><br> <em>For
large alignments it can be useful to deselect "Autocalculate
Consensus" when editing. This prevents the sometimes lengthy
label.show_histogram = Show Histogram
label.show_logo = Show Logo
label.normalise_logo = Normalise Logo
-label.no_colour_selection_in_scheme = Please, make a colour selection before to apply colour scheme
+label.no_colour_selection_in_scheme = Please make a colour selection before applying colour scheme
label.no_colour_selection_warn = Error saving colour scheme
label.open_split_window? = Would you like to open as a split window, with cDNA and protein linked?
label.open_split_window = Open split window
label.configure_displayed_columns = Configure Displayed Columns
label.start_jalview = Start Jalview
label.biojs_html_export = BioJS
-action.back = Back
-label.hide_insertions = Hide Insertions
-label.mark_as_representative = Mark as representative
-label.open_jabaws_web_page = Open JABAWS web page
-label.opens_the_jabaws_server_homepage = Opens the JABAWS server's homepage in web browser
-label.pdb_sequence_getcher = PDB Sequence Fetcher
-label.result = result
-label.results = results
-label.structure_chooser = Structure Chooser
-label.select = Select :
-label.invert = Invert
-label.select_pdb_file = Select PDB File
-info.select_filter_option = Select Filter Option/Manual Entry
-info.associate_wit_sequence = Associate with Sequence
-label.search_result = Search Result
-label.found_structures_summary = Found Structures Summary
-label.configure_displayed_columns = Configure Displayed Columns
-label.scale_as_cdna = Scale protein residues to width of codons
+label.scale_as_cdna = Scale protein residues to codons
label.scale_protein_to_cdna = Scale Protein to cDNA
label.scale_protein_to_cdna_tip = Make protein residues same width as codons in split frame views
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import jalview.datamodel.Mapping;
import jalview.datamodel.SearchResults;
import jalview.datamodel.Sequence;
-import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.schemes.ResidueProperties;
public static AlignmentI makeExonAlignment(SequenceI[] dna,
Set<AlignedCodonFrame> mappings)
{
- Set<AlignedCodonFrame> newMappings = new HashSet<AlignedCodonFrame>();
+ Set<AlignedCodonFrame> newMappings = new LinkedHashSet<AlignedCodonFrame>();
List<SequenceI> exonSequences = new ArrayList<SequenceI>();
for (SequenceI dnaSeq : dna)
final SequenceI ds = dnaSeq.getDatasetSequence();
List<AlignedCodonFrame> seqMappings = MappingUtils
.findMappingsForSequence(ds, mappings);
- if (!seqMappings.isEmpty())
+ for (AlignedCodonFrame acf : seqMappings)
{
- /*
- * We assume here that only one protein mapping is expected per dna
- * sequence. Mapping to multiple protein sequences is conceivable but
- * undefined. Splitting a mapping to one protein sequence across
- * multiple mappings is possible but pathological. Need closer
- * constraints on the contents of AlignedCodonFrame.
- */
AlignedCodonFrame newMapping = new AlignedCodonFrame();
- final SequenceI exonSequence = makeExonSequence(ds,
- seqMappings.get(0), newMapping);
- exonSequences.add(exonSequence);
- newMappings.add(newMapping);
+ final List<SequenceI> mappedExons = makeExonSequences(ds, acf,
+ newMapping);
+ if (!mappedExons.isEmpty())
+ {
+ exonSequences.addAll(mappedExons);
+ newMappings.add(newMapping);
+ }
}
}
AlignmentI al = new Alignment(
}
/**
- * Helper method to make an exon-only sequence and populate its mapping to
- * protein
+ * Helper method to make exon-only sequences and populate their mappings to
+ * protein products
* <p>
* For example, if ggCCaTTcGAg has mappings [3, 4, 6, 7, 9, 10] to protein
* then generate a sequence CCTTGA with mapping [1, 6] to the same protein
* residues
+ * <p>
+ * Typically eukaryotic dna will include exons encoding for a single peptide
+ * sequence i.e. return a single result. Bacterial dna may have overlapping
+ * exon mappings coding for multiple peptides so return multiple results
+ * (example EMBL KF591215).
*
* @param dnaSeq
* a dna dataset sequence
* @param mapping
- * the current mapping of the sequence to protein
+ * containing one or more mappings of the sequence to protein
* @param newMapping
- * the new mapping to populate, from the exon-only sequence
+ * the new mapping to populate, from the exon-only sequences to their
+ * mapped protein sequences
* @return
*/
- protected static SequenceI makeExonSequence(SequenceI dnaSeq,
- AlignedCodonFrame acf, AlignedCodonFrame newMapping)
+ protected static List<SequenceI> makeExonSequences(SequenceI dnaSeq,
+ AlignedCodonFrame mapping, AlignedCodonFrame newMapping)
{
- Mapping mapping = acf.getMappingForSequence(dnaSeq);
+ List<SequenceI> exonSequences = new ArrayList<SequenceI>();
+ List<Mapping> seqMappings = mapping.getMappingsForSequence(dnaSeq);
final char[] dna = dnaSeq.getSequence();
- StringBuilder newSequence = new StringBuilder(dnaSeq.getLength());
-
- /*
- * Get the codon regions as { [2, 5], [7, 12], [14, 14] etc }
- */
- List<int[]> exonRanges = mapping.getMap().getFromRanges();
- for (int[] range : exonRanges)
+ for (Mapping seqMapping : seqMappings)
{
- for (int pos = range[0]; pos <= range[1]; pos++)
+ StringBuilder newSequence = new StringBuilder(dnaSeq.getLength());
+
+ /*
+ * Get the codon regions as { [2, 5], [7, 12], [14, 14] etc }
+ */
+ final List<int[]> dnaExonRanges = seqMapping.getMap().getFromRanges();
+ for (int[] range : dnaExonRanges)
{
- newSequence.append(dna[pos - 1]);
+ for (int pos = range[0]; pos <= range[1]; pos++)
+ {
+ newSequence.append(dna[pos - 1]);
+ }
}
- }
- SequenceI exon = new Sequence(dnaSeq.getName(), newSequence.toString());
+ SequenceI exon = new Sequence(dnaSeq.getName(),
+ newSequence.toString());
- /*
- * Locate any xrefs to CDS database on the protein product and attach to the
- * CDS sequence. Also add as a sub-token of the sequence name.
- */
- // default to "CDS" if we can't locate an actual gene id
- String cdsAccId = FeatureProperties.getCodingFeature(DBRefSource.EMBL);
- DBRefEntry[] cdsRefs = DBRefUtils.selectRefs(
- mapping.getTo().getDBRef(), DBRefSource.CODINGDBS);
- if (cdsRefs != null)
- {
- for (DBRefEntry cdsRef : cdsRefs)
+ /*
+ * Locate any xrefs to CDS database on the protein product and attach to
+ * the CDS sequence. Also add as a sub-token of the sequence name.
+ */
+ // default to "CDS" if we can't locate an actual gene id
+ String cdsAccId = FeatureProperties
+ .getCodingFeature(DBRefSource.EMBL);
+ DBRefEntry[] cdsRefs = DBRefUtils.selectRefs(seqMapping.getTo()
+ .getDBRef(), DBRefSource.CODINGDBS);
+ if (cdsRefs != null)
{
- exon.addDBRef(new DBRefEntry(cdsRef));
- cdsAccId = cdsRef.getAccessionId();
+ for (DBRefEntry cdsRef : cdsRefs)
+ {
+ exon.addDBRef(new DBRefEntry(cdsRef));
+ cdsAccId = cdsRef.getAccessionId();
+ }
}
- }
- exon.setName(exon.getName() + "|" + cdsAccId);
- exon.createDatasetSequence();
+ exon.setName(exon.getName() + "|" + cdsAccId);
+ exon.createDatasetSequence();
- /*
- * Build new mappings - from the same protein regions, but now to contiguous
- * exons
- */
- List<int[]> exonRange = new ArrayList<int[]>();
- exonRange.add(new int[]
- { 1, newSequence.length() });
- MapList map = new MapList(exonRange, mapping.getMap().getToRanges(), 3, 1);
- newMapping.addMap(exon.getDatasetSequence(), mapping.getTo(), map);
+ /*
+ * Build new mappings - from the same protein regions, but now to
+ * contiguous exons
+ */
+ List<int[]> exonRange = new ArrayList<int[]>();
+ exonRange.add(new int[]
+ { 1, newSequence.length() });
+ MapList map = new MapList(exonRange, seqMapping.getMap()
+ .getToRanges(),
+ 3, 1);
+ newMapping.addMap(exon.getDatasetSequence(), seqMapping.getTo(), map);
+ MapList cdsToDnaMap = new MapList(dnaExonRanges, exonRange, 1, 1);
+ newMapping.addMap(dnaSeq, exon.getDatasetSequence(), cdsToDnaMap);
- return exon;
+ exonSequences.add(exon);
+ }
+ return exonSequences;
}
}
*/
package jalview.datamodel;
+import java.util.ArrayList;
+import java.util.List;
+
import jalview.util.MapList;
import jalview.util.MappingUtils;
{ dnaSeq[codonPos[0] - 1], dnaSeq[codonPos[1] - 1],
dnaSeq[codonPos[2] - 1] };
}
+
+ /**
+ * Returns any mappings found which are to (or from) the given sequence, and
+ * to distinct sequences.
+ *
+ * @param seq
+ * @return
+ */
+ public List<Mapping> getMappingsForSequence(SequenceI seq)
+ {
+ List<Mapping> result = new ArrayList<Mapping>();
+ if (dnaSeqs == null)
+ {
+ return result;
+ }
+ List<SequenceI> related = new ArrayList<SequenceI>();
+ SequenceI seqDs = seq.getDatasetSequence();
+ seqDs = seqDs != null ? seqDs : seq;
+
+ for (int ds = 0; ds < dnaSeqs.length; ds++)
+ {
+ final Mapping mapping = dnaToProt[ds];
+ if (dnaSeqs[ds] == seqDs || mapping.to == seqDs)
+ {
+ if (!related.contains(mapping.to))
+ {
+ result.add(mapping);
+ related.add(mapping.to);
+ }
+ }
+ }
+ return result;
+ }
}
*/
AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
AlignFrame newTopFrame = new AlignFrame(topPanel);
+ newTopFrame.setSize(new Dimension(AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT));
newTopFrame.setVisible(true);
AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
+ newBottomFrame.setSize(new Dimension(AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT));
newBottomFrame.setVisible(true);
topPanel.av.setGatherViewsHere(false);
bottomPanel.av.setGatherViewsHere(false);
* Enable 'scale protein as cDNA' in a SplitFrame view. The selection is
* stored in the ViewStyle of both dna and protein Viewport
*/
+ scaleAsCdna.setEnabled(false);
if (ap.av.getCodingComplement() != null)
{
+ scaleAsCdna.setEnabled(true);
scaleAsCdna.setVisible(true);
scaleAsCdna.setSelected(ap.av.isScaleProteinAsCdna());
}
.getStringBounds("I", getGraphics()).getWidth();
if (mw < 1 || iw < 1)
{
- fontName.setSelectedItem(lastSelected.getName());
- fontStyle.setSelectedIndex(lastSelStyle);
- fontSize.setSelectedItem(lastSelSize);
- monospaced.setSelected(lastSelMono);
JOptionPane
.showInternalMessageDialog(
this,
MessageManager.getString("label.font_doesnt_have_letters_defined"),
MessageManager.getString("label.invalid_font"), JOptionPane.WARNING_MESSAGE);
+ /*
+ * Restore previous values - size first to avoid recursive calls to this
+ * point!
+ */
+ fontSize.setSelectedItem(lastSelSize);
+ fontName.setSelectedItem(lastSelected.getName());
+ fontStyle.setSelectedIndex(lastSelStyle);
+ monospaced.setSelected(lastSelMono);
return;
}
if (tp != null)
import jalview.datamodel.SequenceI;
import jalview.jbgui.GStructureChooser;
import jalview.jbgui.PDBDocFieldPreferences;
+import jalview.structure.StructureSelectionManager;
import jalview.util.MessageManager;
import jalview.ws.dbsources.PDBRestClient;
import jalview.ws.dbsources.PDBRestClient.PDBDocField;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Vector;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
+import javax.swing.table.DefaultTableModel;
+
/**
* Provides the behaviors for the Structure chooser Panel
private boolean isValidPBDEntry;
+ private static Hashtable<String, PDBEntry> cachedEntryMap;
+
public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
AlignmentPanel ap)
{
long startTime = System.currentTimeMillis();
String msg = MessageManager.getString("status.fetching_db_refs");
updateProgressIndicator(msg, startTime);
+ loadLocalCachedPDBEntries();
fetchStructuresMetaData();
populateFilterComboBox();
updateProgressIndicator(null, startTime);
+ " Found (" + totalTime + ")");
}
+ public void loadLocalCachedPDBEntries()
+ {
+ DefaultTableModel tableModel = new DefaultTableModel();
+ tableModel.addColumn("Sequence");
+ tableModel.addColumn("PDB Id");
+ tableModel.addColumn("Type");
+ tableModel.addColumn("File");
+ cachedEntryMap = new Hashtable<String, PDBEntry>();
+ for (SequenceI seq : selectedSequences)
+ {
+ if (seq.getDatasetSequence() != null
+ && seq.getDatasetSequence().getPDBId() != null)
+ {
+ for (PDBEntry pdbEntry : seq.getDatasetSequence().getPDBId())
+ {
+ String[] pdbEntryRowData = new String[]
+ { seq.getDisplayId(false), pdbEntry.getId(), pdbEntry.getType(),
+ pdbEntry.getFile() };
+ tableModel.addRow(pdbEntryRowData);
+ cachedEntryMap.put(seq.getDisplayId(false) + pdbEntry.getId(),
+ pdbEntry);
+ }
+ }
+ }
+ tbl_local_pdb.setModel(tableModel);
+ }
+
/**
* Update the DBRef entry for a given sequence with values retrieved from
* PDBResponseSummary
* the sequences to build a query for
* @return the built query string
*/
- @SuppressWarnings("unchecked")
+
public static String buildQuery(SequenceI seq)
{
String query = seq.getName();
if (seq.getPDBId() != null)
{
- for (PDBEntry entry : (Vector<PDBEntry>) seq.getPDBId())
+ for (PDBEntry entry : seq.getPDBId())
{
queryBuilder.append("text:").append(entry.getId()).append(" OR ");
}
VIEWS_ENTER_ID));
cmb_filterOption.addItem(new FilterOption("From File", "-",
VIEWS_FROM_FILE));
+ cmb_filterOption.addItem(new FilterOption("Cached PDB Entries", "-",
+ VIEWS_LOCAL_PDB));
}
/**
chk_invertFilter.setVisible(true);
filterResultSet(selectedFilterOpt.getValue());
}
- else
+ else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
+ || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
{
idInputAssSeqPanel.loadCmbAssSeq();
fileChooserAssSeqPanel.loadCmbAssSeq();
btn_view.setEnabled(true);
}
}
+ else if (currentView == VIEWS_LOCAL_PDB)
+ {
+ if (tbl_local_pdb.getSelectedRows().length > 0)
+ {
+ btn_view.setEnabled(true);
+ }
+ }
else if (currentView == VIEWS_ENTER_ID)
{
validateAssociationEnterPdb();
pdbEntry.setType("PDB");
pdbEntriesToView[count++] = pdbEntry;
}
- new StructureViewer(ap.getStructureSelectionManager())
- .viewStructures(ap, pdbEntriesToView,
- ap.av.collateForPDB(pdbEntriesToView));
+
+ launchStructureViewer(ap.getStructureSelectionManager(),
+ pdbEntriesToView, ap, selectedSequences);
+ }
+ else if(currentView == VIEWS_LOCAL_PDB){
+ int[] selectedRows = tbl_local_pdb.getSelectedRows();
+ PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
+ int count = 0;
+ for (int row : selectedRows)
+ {
+ String entryKey = tbl_local_pdb.getValueAt(row, 0).toString() + tbl_local_pdb.getValueAt(row, 1).toString();
+ pdbEntriesToView[count++] = cachedEntryMap.get(entryKey);
+ }
+ launchStructureViewer(ap.getStructureSelectionManager(),
+ pdbEntriesToView, ap, selectedSequences);
}
else if (currentView == VIEWS_ENTER_ID)
{
- selectedSequence = ((AssociateSeqOptions) idInputAssSeqPanel
+ SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
.getCmb_assSeq().getSelectedItem()).getSequence();
+ if (userSelectedSeq != null)
+ {
+ selectedSequence = userSelectedSeq;
+ }
PDBEntry pdbEntry = new PDBEntry();
pdbEntry.setId(txt_search.getText());
pdbEntry.setType("PDB");
selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
PDBEntry[] pdbEntriesToView = new PDBEntry[]
{ pdbEntry };
- new StructureViewer(ap.getStructureSelectionManager())
- .viewStructures(ap, pdbEntriesToView,
- ap.av.collateForPDB(pdbEntriesToView));
+ launchStructureViewer(ap.getStructureSelectionManager(),
+ pdbEntriesToView, ap, new SequenceI[]
+ { selectedSequence });
}
else if (currentView == VIEWS_FROM_FILE)
{
- selectedSequence = ((AssociateSeqOptions) fileChooserAssSeqPanel
+ SequenceI userSelectedSeq = ((AssociateSeqOptions) fileChooserAssSeqPanel
.getCmb_assSeq().getSelectedItem()).getSequence();
- new AssociatePdbFileWithSeq().associatePdbWithSeq(
+ if (userSelectedSeq != null)
+ {
+ selectedSequence = userSelectedSeq;
+ }
+ PDBEntry fileEntry = new AssociatePdbFileWithSeq()
+ .associatePdbWithSeq(
selectedPdbFileName, jalview.io.AppletFormatAdapter.FILE,
selectedSequence, true, Desktop.instance);
+
+ launchStructureViewer(ap.getStructureSelectionManager(),
+ new PDBEntry[]
+ { fileEntry }, ap, new SequenceI[]
+ { selectedSequence });
}
mainFrame.dispose();
}
+ private void launchStructureViewer(StructureSelectionManager ssm,
+ PDBEntry[] pdbEntriesToView, AlignmentPanel alignPanel,
+ SequenceI[] selectedSequences)
+ {
+ StructureViewer sViewer = new StructureViewer(ssm);
+ if (pdbEntriesToView.length > 1)
+ {
+ sViewer.viewStructures(alignPanel, pdbEntriesToView,
+ alignPanel.av.collateForPDB(pdbEntriesToView));
+ }
+ else
+ {
+ sViewer.viewStructures(pdbEntriesToView[0], selectedSequences, null,
+ alignPanel);
+ }
+ }
+
/**
* Populates the combo-box used in associating manually fetched structures to
* a unique sequence when more than one sequence selection is made.
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JButton;
private JPanel pnl_actions = new JPanel();
- private JPanel pnl_filter = new JPanel();
+ private JPanel pnl_main = new JPanel();
private JPanel pnl_idInput = new JPanel(new FlowLayout());
private JPanel pnl_fileChooserBL = new JPanel(new BorderLayout());
+ private JPanel pnl_locPDB = new JPanel(new BorderLayout());
+
protected JPanel pnl_switchableViews = new JPanel(new CardLayout());
protected CardLayout layout_switchableViews = (CardLayout) (pnl_switchableViews
protected static final String VIEWS_ENTER_ID = "VIEWS_ENTER_ID";
+ protected static final String VIEWS_LOCAL_PDB = "VIEWS_LOCAL_PDB";
+
protected JTable tbl_summary = new JTable();
protected JScrollPane scrl_foundStructures = new JScrollPane(
tbl_summary);
- private JTabbedPane tabbedPane = new JTabbedPane();
+ protected JTable tbl_local_pdb = new JTable();
+
+ protected JScrollPane scrl_localPDB = new JScrollPane(tbl_local_pdb);
+
+ private JTabbedPane pnl_filter = new JTabbedPane();
private PDBDocFieldPreferences pdbDocFieldPrefs = new PDBDocFieldPreferences(
PreferenceSource.STRUCTURE_CHOOSER);
private void jbInit() throws Exception
{
tbl_summary.setAutoCreateRowSorter(true);
+ tbl_local_pdb.setAutoCreateRowSorter(true);
+ tbl_local_pdb.addMouseListener(new MouseAdapter()
+ {
+ public void mouseClicked(MouseEvent e)
+ {
+ updateCurrentView();
+ }
+ });
+
btn_view.setFont(new java.awt.Font("Verdana", 0, 12));
btn_view.setText(MessageManager.getString("action.view"));
btn_view.addActionListener(new java.awt.event.ActionListener()
scrl_foundStructures
.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ scrl_localPDB.setPreferredSize(new Dimension(500, 300));
+ scrl_localPDB
+ .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+
cmb_filterOption.setFont(new java.awt.Font("Verdana", 0, 12));
chk_invertFilter.setFont(new java.awt.Font("Verdana", 0, 12));
chk_rememberSettings.setFont(new java.awt.Font("Verdana", 0, 12));
pnl_actions.add(btn_cancel);
// pnl_filter.add(lbl_result);
- pnl_filter.add(cmb_filterOption);
- pnl_filter.add(lbl_loading);
- pnl_filter.add(chk_invertFilter);
+ pnl_main.add(cmb_filterOption);
+ pnl_main.add(lbl_loading);
+ pnl_main.add(chk_invertFilter);
lbl_loading.setVisible(false);
- pnl_idInput.add(txt_search);
- pnl_idInput.add(lbl_pdbManualFetchStatus);
pnl_fileChooser.add(btn_pdbFromFile);
pnl_fileChooser.add(lbl_fromFileStatus);
-
pnl_fileChooserBL.add(fileChooserAssSeqPanel, BorderLayout.NORTH);
pnl_fileChooserBL.add(pnl_fileChooser, BorderLayout.CENTER);
+ pnl_idInput.add(txt_search);
+ pnl_idInput.add(lbl_pdbManualFetchStatus);
pnl_idInputBL.add(idInputAssSeqPanel, BorderLayout.NORTH);
pnl_idInputBL.add(pnl_idInput, BorderLayout.CENTER);
}
}
};
- tabbedPane.addChangeListener(changeListener);
- tabbedPane.setPreferredSize(new Dimension(500, 300));
- tabbedPane.add(foundStructureSummary, scrl_foundStructures);
- tabbedPane.add(
+ pnl_filter.addChangeListener(changeListener);
+ pnl_filter.setPreferredSize(new Dimension(500, 300));
+ pnl_filter.add(foundStructureSummary, scrl_foundStructures);
+ pnl_filter.add(
MessageManager.getString("label.configure_displayed_columns"),
pdbDocFieldPrefs);
+ pnl_locPDB.add(scrl_localPDB);
pnl_switchableViews.add(pnl_fileChooserBL, VIEWS_FROM_FILE);
pnl_switchableViews.add(pnl_idInputBL, VIEWS_ENTER_ID);
- pnl_switchableViews.add(tabbedPane, VIEWS_FILTER);
+ pnl_switchableViews.add(pnl_filter, VIEWS_FILTER);
+ pnl_switchableViews.add(pnl_locPDB, VIEWS_LOCAL_PDB);
this.setLayout(mainLayout);
- this.add(pnl_filter, java.awt.BorderLayout.NORTH);
+ this.add(pnl_main, java.awt.BorderLayout.NORTH);
this.add(pnl_switchableViews, java.awt.BorderLayout.CENTER);
this.add(pnl_actions, java.awt.BorderLayout.SOUTH);
*/
public class PDBRestClient
{
- private static String PDB_SEARCH_ENDPOINT = "http://wwwdev.ebi.ac.uk/pdbe/search/pdb/select?";
+ private static String PDB_SEARCH_ENDPOINT = "http://www.ebi.ac.uk/pdbe/search/pdb/select?";
private static int DEFAULT_RESPONSE_SIZE = 200;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
* x-ref to the EMBLCDS record.
*/
@Test
- public void testMakeExonSequence()
+ public void testMakeExonSequences()
{
SequenceI dna1 = new Sequence("dna1", "aaaGGGcccTTTaaa");
SequenceI pep1 = new Sequence("pep1", "GF");
mappings.add(acf);
AlignedCodonFrame newMapping = new AlignedCodonFrame();
- SequenceI exon = AlignmentUtils.makeExonSequence(dna1, acf, newMapping);
+ List<SequenceI> exons = AlignmentUtils.makeExonSequences(dna1, acf,
+ newMapping);
+ assertEquals(1, exons.size());
+ SequenceI exon = exons.get(0);
assertEquals("GGGTTT", exon.getSequenceAsString());
assertEquals("dna1|A12345", exon.getName());
assertEquals("EMBLCDS", cdsRef.getSource());
assertEquals("2", cdsRef.getVersion());
assertEquals("A12345", cdsRef.getAccessionId());
+ }
+
+ /**
+ * Test the method that makes an exon-only alignment from a DNA sequence and
+ * its product mappings, for the case where there are multiple exon mappings
+ * to different protein products.
+ */
+ @Test
+ public void testMakeExonAlignment_multipleProteins()
+ {
+ SequenceI dna1 = new Sequence("dna1", "aaaGGGcccTTTaaa");
+ SequenceI pep1 = new Sequence("pep1", "GF"); // GGGTTT
+ SequenceI pep2 = new Sequence("pep2", "KP"); // aaaccc
+ SequenceI pep3 = new Sequence("pep3", "KF"); // aaaTTT
+ dna1.createDatasetSequence();
+ pep1.createDatasetSequence();
+ pep2.createDatasetSequence();
+ pep3.createDatasetSequence();
+ pep1.getDatasetSequence().addDBRef(
+ new DBRefEntry("EMBLCDS", "2", "A12345"));
+ pep2.getDatasetSequence().addDBRef(
+ new DBRefEntry("EMBLCDS", "3", "A12346"));
+ pep3.getDatasetSequence().addDBRef(
+ new DBRefEntry("EMBLCDS", "4", "A12347"));
+ /*
+ * Make the mappings from dna to protein. Using LinkedHashset is a
+ * convenience so results are in the input order. There is no assertion that
+ * the generated exon sequences are in any particular order.
+ */
+ Set<AlignedCodonFrame> mappings = new LinkedHashSet<AlignedCodonFrame>();
+ // map ...GGG...TTT to GF
+ MapList map = new MapList(new int[]
+ { 4, 6, 10, 12 }, new int[]
+ { 1, 2 }, 3, 1);
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ acf.addMap(dna1.getDatasetSequence(), pep1.getDatasetSequence(), map);
+ mappings.add(acf);
+
+ // map aaa...ccc to KP
+ map = new MapList(new int[]
+ { 1, 3, 7, 9 }, new int[]
+ { 1, 2 }, 3, 1);
+ acf = new AlignedCodonFrame();
+ acf.addMap(dna1.getDatasetSequence(), pep2.getDatasetSequence(), map);
+ mappings.add(acf);
+
+ // map aaa......TTT to KF
+ map = new MapList(new int[]
+ { 1, 3, 10, 12 }, new int[]
+ { 1, 2 }, 3, 1);
+ acf = new AlignedCodonFrame();
+ acf.addMap(dna1.getDatasetSequence(), pep3.getDatasetSequence(), map);
+ mappings.add(acf);
+
+ /*
+ * Create the Exon alignment; also replaces the dna-to-protein mappings with
+ * exon-to-protein and exon-to-dna mappings
+ */
+ AlignmentI exal = AlignmentUtils.makeExonAlignment(new SequenceI[]
+ { dna1 }, mappings);
+
+ /*
+ * Verify we have 3 exon sequences, mapped to pep1/2/3 respectively
+ */
+ List<SequenceI> exons = exal.getSequences();
+ assertEquals(3, exons.size());
+
+ SequenceI exon = exons.get(0);
+ assertEquals("GGGTTT", exon.getSequenceAsString());
+ assertEquals("dna1|A12345", exon.getName());
+ assertEquals(1, exon.getDBRef().length);
+ DBRefEntry cdsRef = exon.getDBRef()[0];
+ assertEquals("EMBLCDS", cdsRef.getSource());
+ assertEquals("2", cdsRef.getVersion());
+ assertEquals("A12345", cdsRef.getAccessionId());
+
+ exon = exons.get(1);
+ assertEquals("aaaccc", exon.getSequenceAsString());
+ assertEquals("dna1|A12346", exon.getName());
+ assertEquals(1, exon.getDBRef().length);
+ cdsRef = exon.getDBRef()[0];
+ assertEquals("EMBLCDS", cdsRef.getSource());
+ assertEquals("3", cdsRef.getVersion());
+ assertEquals("A12346", cdsRef.getAccessionId());
+
+ exon = exons.get(2);
+ assertEquals("aaaTTT", exon.getSequenceAsString());
+ assertEquals("dna1|A12347", exon.getName());
+ assertEquals(1, exon.getDBRef().length);
+ cdsRef = exon.getDBRef()[0];
+ assertEquals("EMBLCDS", cdsRef.getSource());
+ assertEquals("4", cdsRef.getVersion());
+ assertEquals("A12347", cdsRef.getAccessionId());
+
+ /*
+ * Verify there are mappings from each exon sequence to its protein product
+ * and also to its dna source
+ */
+ Iterator<AlignedCodonFrame> newMappingsIterator = mappings.iterator();
+
+ // mappings for dna1 - exon1 - pep1
+ AlignedCodonFrame exonMapping = newMappingsIterator.next();
+ List<Mapping> dnaMappings = exonMapping.getMappingsForSequence(dna1);
+ assertEquals(1, dnaMappings.size());
+ assertSame(exons.get(0).getDatasetSequence(), dnaMappings.get(0)
+ .getTo());
+ assertEquals("G(1) in CDS should map to G(4) in DNA", 4, dnaMappings
+ .get(0).getMap().getToPosition(1));
+ List<Mapping> peptideMappings = exonMapping
+ .getMappingsForSequence(pep1);
+ assertEquals(1, peptideMappings.size());
+ assertSame(pep1.getDatasetSequence(), peptideMappings.get(0).getTo());
+
+ // mappings for dna1 - exon2 - pep2
+ exonMapping = newMappingsIterator.next();
+ dnaMappings = exonMapping.getMappingsForSequence(dna1);
+ assertEquals(1, dnaMappings.size());
+ assertSame(exons.get(1).getDatasetSequence(), dnaMappings.get(0)
+ .getTo());
+ assertEquals("c(4) in CDS should map to c(7) in DNA", 7, dnaMappings
+ .get(0).getMap().getToPosition(4));
+ peptideMappings = exonMapping.getMappingsForSequence(pep2);
+ assertEquals(1, peptideMappings.size());
+ assertSame(pep2.getDatasetSequence(), peptideMappings.get(0).getTo());
+
+ // mappings for dna1 - exon3 - pep3
+ exonMapping = newMappingsIterator.next();
+ dnaMappings = exonMapping.getMappingsForSequence(dna1);
+ assertEquals(1, dnaMappings.size());
+ assertSame(exons.get(2).getDatasetSequence(), dnaMappings.get(0)
+ .getTo());
+ assertEquals("T(4) in CDS should map to T(10) in DNA", 10, dnaMappings
+ .get(0).getMap().getToPosition(4));
+ peptideMappings = exonMapping.getMappingsForSequence(pep3);
+ assertEquals(1, peptideMappings.size());
+ assertSame(pep3.getDatasetSequence(), peptideMappings.get(0).getTo());
}
}
--- /dev/null
+package jalview.gui;
+
+import java.awt.Canvas;
+import java.awt.Font;
+import java.awt.FontMetrics;
+
+import org.junit.Test;
+
+public class FontChooserTest
+{
+
+ /**
+ * Not a real test as it runs no methods on FontChooser and makes no
+ * assertions, but this method writes to sysout the names of any (currently
+ * available, plain) fonts and point sizes that would be rejected by Jalview's
+ * FontChooser as having an I-width of less than 1.0.
+ */
+ @Test
+ public void dumpInvalidFonts()
+ {
+ String[] fonts = java.awt.GraphicsEnvironment
+ .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
+ for (int pointSize = 1;; pointSize++)
+ {
+ System.out.println(System.lineSeparator()
+ + "Fonts with insufficient width at " + pointSize + "pt:");
+ if (pointSize == 1)
+ {
+ System.out.println("All except:");
+ }
+ int badCount = 0;
+ for (String fontname : fonts)
+ {
+ Font newFont = new Font(fontname, Font.PLAIN, pointSize);
+ FontMetrics fontm = new Canvas().getFontMetrics(newFont);
+ double iw = fontm.getStringBounds("I", null).getWidth();
+ final boolean tooSmall = iw < 1d;
+ if (tooSmall)
+ {
+ badCount++;
+ }
+ if ((pointSize > 1 && tooSmall) || (pointSize == 1 && !tooSmall))
+ {
+ System.out.println(fontname);
+ }
+ }
+ if (badCount == 0)
+ {
+ break;
+ }
+ }
+ }
+
+}