import java.awt.event.*;
import java.awt.print.*;
import javax.swing.*;
+import javax.swing.event.MenuEvent;
import jalview.analysis.*;
import jalview.commands.*;
void init()
{
- this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
-
if (viewport.conservation == null)
{
BLOSUM62Colour.setEnabled(false);
if (Desktop.desktop != null)
{
+ this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
addServiceListeners();
setGUINucleotide(viewport.alignment.isNucleotide());
}
setMenusFromViewport(viewport);
-
+ buildSortByAnnotationScoresMenu();
if (viewport.wrapAlignment)
{
wrapMenuItem_actionPerformed(null);
&& Character.isDigit(evt.getKeyChar()))
alignPanel.seqPanel.numberPressed(evt.getKeyChar());
-
switch (evt.getKeyCode())
{
new AnnotationExporter().exportAnnotations(
alignPanel,
viewport.showAnnotation ? viewport.alignment.getAlignmentAnnotation() : null,
- viewport.alignment.getGroups()
+ viewport.alignment.getGroups(),
+ ((Alignment)viewport.alignment).alignmentProperties
);
}
{
return;
}
-
+ // TODO: preserve the ordering of displayed alignment annotation in any internal paste (particularly sequence associated annotation)
SequenceI [] seqs = viewport.getSelectionAsNewSequence();
String[] omitHidden = null;
*/
void paste(boolean newAlignment)
{
+ boolean externalPaste=true;
try
{
Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
}
SequenceI[] sequences;
-
+ boolean annotationAdded = false;
+ AlignmentI alignment = null;
if(Desktop.jalviewClipboard!=null)
{
// The clipboard was filled from within Jalview, we must use the sequences
// And dataset from the copied alignment
- sequences = (SequenceI[])Desktop.jalviewClipboard[0];
+ SequenceI[] newseq = (SequenceI[])Desktop.jalviewClipboard[0];
+ // be doubly sure that we create *new* sequence objects.
+ sequences = new SequenceI[newseq.length];
+ for (int i=0;i<newseq.length;i++) {
+ sequences[i] = new Sequence(newseq[i]);
+ }
+ alignment = new Alignment(sequences);
+ externalPaste = false;
}
else
{
- sequences = new FormatAdapter().readFile(str, "Paste", format).
- getSequencesArray();
+ // parse the clipboard as an alignment.
+ alignment = new FormatAdapter().readFile(str, "Paste", format);
+ sequences = alignment.getSequencesArray();
}
- AlignmentI alignment = null;
+ int alwidth=0;
- if (newAlignment)
- {
- alignment = new Alignment(sequences);
+ if (newAlignment)
+ {
- if (Desktop.jalviewClipboard != null)
- {
- alignment.setDataset( (Alignment) Desktop.jalviewClipboard[1]);
- }
- else
- {
- alignment.setDataset(null);
- }
- }
- else
- {
- alignment = viewport.getAlignment();
+ if (Desktop.jalviewClipboard != null)
+ {
+ // dataset is inherited
+ alignment.setDataset( (Alignment) Desktop.jalviewClipboard[1]);
+ }
+ else
+ {
+ // new dataset is constructed
+ alignment.setDataset(null);
+ }
+ alwidth = alignment.getWidth()+1;
+ }
+ else
+ {
+ AlignmentI pastedal = alignment; // preserve pasted alignment object
+ // Add pasted sequences and dataset into existing alignment.
+ alignment = viewport.getAlignment();
+ alwidth = alignment.getWidth()+1;
+ // decide if we need to import sequences from an existing dataset
+ boolean importDs = Desktop.jalviewClipboard != null
+ && Desktop.jalviewClipboard[1] != alignment.getDataset();
+ // importDs==true instructs us to copy over new dataset sequences from
+ // an existing alignment
+ Vector newDs = (importDs) ? new Vector() : null; // used to create
+ // minimum dataset set
- //!newAlignment
- SequenceI [] newseqs = new SequenceI[sequences.length];
for (int i = 0; i < sequences.length; i++)
{
- newseqs[i] = new Sequence(sequences[i].getName(),
- sequences[i].getSequence(),
- sequences[i].getStart(),
- sequences[i].getEnd());
-
- alignment.addSequence(newseqs[i]);
+ if (importDs)
+ {
+ newDs.addElement(null);
+ }
+ SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
+ // paste
+ if (importDs && ds != null)
+ {
+ if (!newDs.contains(ds))
+ {
+ newDs.setElementAt(ds, i);
+ ds = new Sequence(ds);
+ // update with new dataset sequence
+ sequences[i].setDatasetSequence(ds);
+ }
+ else
+ {
+ ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
+ }
+ }
+ else
+ {
+ // copy and derive new dataset sequence
+ sequences[i] = sequences[i].deriveSequence();
+ alignment.getDataset().addSequence(sequences[i].getDatasetSequence());
+ // TODO: avoid creation of duplicate dataset sequences with a
+ // 'contains' method using SequenceI.equals()/SequenceI.contains()
+ }
+ alignment.addSequence(sequences[i]); // merges dataset
}
-
- /*
- //ADD HISTORY ITEM
- */
- addHistoryItem(new EditCommand(
- "Add sequences",
- EditCommand.PASTE,
- newseqs,
- 0,
- alignment.getWidth(),
- alignment)
- );
-
-
- viewport.setEndSeq(alignment.getHeight());
- alignment.getWidth();
- viewport.firePropertyChange("alignment", null, alignment.getSequences());
- }
-
-
-
- // Add any annotations attached to sequences
- for (int i = 0; i < sequences.length; i++)
+ if (newDs != null)
+ {
+ newDs.clear(); // tidy up
+ }
+ if (pastedal.getAlignmentAnnotation()!=null) {
+ // Add any annotation attached to alignment.
+ AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
+ for (int i=0; i<alann.length; i++)
+ {
+ annotationAdded=true;
+ if (alann[i].sequenceRef==null && !alann[i].autoCalculated) {
+ AlignmentAnnotation newann = new AlignmentAnnotation(alann[i]);
+ newann.padAnnotation(alwidth);
+ alignment.addAnnotation(newann);
+ }
+ }
+ }
+ }
+ if (!newAlignment) {
+ ///////
+ // ADD HISTORY ITEM
+ //
+ addHistoryItem(new EditCommand(
+ "Add sequences",
+ EditCommand.PASTE,
+ sequences,
+ 0,
+ alignment.getWidth(),
+ alignment)
+ );
+ }
+ // Add any annotations attached to sequences
+ for (int i = 0; i < sequences.length; i++)
{
if (sequences[i].getAnnotation() != null)
{
for (int a = 0; a < sequences[i].getAnnotation().length; a++)
{
- AlignmentAnnotation newAnnot =
- new AlignmentAnnotation(
- sequences[i].getAnnotation()[a].label,
- sequences[i].getAnnotation()[a].description,
- sequences[i].getAnnotation()[a].annotations,
- sequences[i].getAnnotation()[a].graphMin,
- sequences[i].getAnnotation()[a].graphMax,
- sequences[i].getAnnotation()[a].graph);
-
- sequences[i].getAnnotation()[a] = newAnnot;
- newAnnot.sequenceMapping = sequences[i].getAnnotation()[a].
- sequenceMapping;
- newAnnot.sequenceRef = sequences[i];
- newAnnot.adjustForAlignment();
- alignment.addAnnotation(newAnnot);
- alignment.setAnnotationIndex(newAnnot, a);
+ annotationAdded=true;
+ sequences[i].getAnnotation()[a].adjustForAlignment();
+ sequences[i].getAnnotation()[a].padAnnotation(alwidth);
+ alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation was duplicated earlier
+ alignment.setAnnotationIndex(sequences[i].getAnnotation()[a], a);
}
- alignPanel.annotationPanel.adjustPanelHeight();
+
}
}
-
- if(newAlignment)
- {
+ if (!newAlignment) {
+ // propagate alignment changed.
+ viewport.setEndSeq(alignment.getHeight());
+ if (annotationAdded)
+ {
+ alignPanel.annotationPanel.adjustPanelHeight();
+ buildSortByAnnotationScoresMenu();
+ }
+ viewport.firePropertyChange("alignment", null, alignment.getSequences());
+ } else {
AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH, DEFAULT_HEIGHT);
String newtitle = new String("Copied sequences");
af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().transferSettings(
alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
-
- if (title.startsWith("Copied sequences"))
- {
- newtitle = title;
- }
- else
- {
- newtitle = newtitle.concat("- from " + title);
+ // TODO: maintain provenance of an alignment, rather than just make the title a concatenation of operations.
+ if (!externalPaste) {
+ if (title.startsWith("Copied sequences"))
+ {
+ newtitle = title;
+ }
+ else
+ {
+ newtitle = newtitle.concat("- from " + title);
+ }
+ } else {
+ newtitle = new String("Pasted sequences");
}
Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
}
+ public void alignmentProperties()
+ {
+ JEditorPane editPane = new JEditorPane("text/html","");
+ editPane.setEditable(false);
+ StringBuffer contents = new StringBuffer("<html>");
+
+ float avg = 0;
+ int min=Integer.MAX_VALUE, max=0;
+ for(int i=0; i<viewport.alignment.getHeight(); i++)
+ {
+ int size = viewport.alignment.getSequenceAt(i).getEnd()
+ -viewport.alignment.getSequenceAt(i).getStart();
+ avg += size;
+ if(size>max)
+ max = size;
+ if(size<min)
+ min = size;
+ }
+ avg = avg/(float)viewport.alignment.getHeight();
+
+ contents.append("<br>Sequences: "+ viewport.alignment.getHeight());
+ contents.append("<br>Minimum Sequence Length: "+min);
+ contents.append("<br>Maximum Sequence Length: "+max);
+ contents.append("<br>Average Length: "+(int)avg);
+
+ if (((Alignment)viewport.alignment).getProperties() != null)
+ {
+ Hashtable props = ((Alignment)viewport.alignment).getProperties();
+ Enumeration en = props.keys();
+ contents.append("<br><br><table border=\"1\">");
+ while(en.hasMoreElements())
+ {
+ String key = en.nextElement().toString();
+ StringBuffer val = new StringBuffer();
+ String vals = props.get(key).toString();
+ int pos=0, npos;
+ do {
+ npos = vals.indexOf("\n",pos);
+ if (npos==-1)
+ {
+ val.append(vals.substring(pos));
+ } else {
+ val.append(vals.substring(pos, npos));
+ val.append("<br>");
+ }
+ pos = npos+1;
+ } while (npos!=-1);
+ contents.append("<tr><td>"+key+"</td><td>"+val+"</td></tr>");
+ }
+ contents.append("</table>");
+ }
+ editPane.setText(contents.toString()+"</html>");
+ JInternalFrame frame = new JInternalFrame();
+ frame.getContentPane().add(new JScrollPane(editPane));
+
+ Desktop.instance.addInternalFrame(frame,"Alignment Properties: "+getTitle(),500,400);
+ }
+
+
/**
* DOCUMENT ME!
*
alignPanel.paintAlignment(true);
}
-
/**
* DOCUMENT ME!
*
}
});
}
+ /**
+ * Add a new sort by annotation score menu item
+ * @param sort the menu to add the option to
+ * @param scoreLabel the label used to retrieve scores for each sequence on the alignment
+ */
+ public void addSortByAnnotScoreMenuItem(JMenu sort, final String scoreLabel)
+ {
+ final JMenuItem item = new JMenuItem(scoreLabel);
+ sort.add(item);
+ item.addActionListener(new java.awt.event.ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
+ AlignmentSorter.sortByAnnotationScore(scoreLabel, viewport.getAlignment());
+ addHistoryItem(new OrderCommand("Sort by "+scoreLabel, oldOrder, viewport.alignment));
+ alignPanel.paintAlignment(true);
+ }
+ });
+ }
+ /**
+ * last hash for alignment's annotation array - used to minimise cost of rebuild.
+ */
+ protected int _annotationScoreVectorHash;
+ /**
+ * search the alignment and rebuild the sort by annotation score submenu
+ * the last alignment annotation vector hash is stored to minimize
+ * cost of rebuilding in subsequence calls.
+ *
+ */
+ public void buildSortByAnnotationScoresMenu()
+ {
+ if (viewport.alignment.getAlignmentAnnotation().hashCode()!=_annotationScoreVectorHash)
+ {
+ sortByAnnotScore.removeAll();
+ // almost certainly a quicker way to do this - but we keep it simple
+ Hashtable scoreSorts=new Hashtable();
+ AlignmentAnnotation aann[];
+ Enumeration sq = viewport.alignment.getSequences().elements();
+ while (sq.hasMoreElements())
+ {
+ aann = ((SequenceI) sq.nextElement()).getAnnotation();
+ for (int i=0;aann!=null && i<aann.length; i++)
+ {
+ if (aann[i].hasScore() && aann[i].sequenceRef!=null)
+ {
+ scoreSorts.put(aann[i].label, aann[i].label);
+ }
+ }
+ }
+ Enumeration labels = scoreSorts.keys();
+ while (labels.hasMoreElements())
+ {
+ addSortByAnnotScoreMenuItem(sortByAnnotScore, (String) labels.nextElement());
+ }
+ sortByAnnotScore.setVisible(scoreSorts.size()>0);
+ scoreSorts.clear();
+ }
+ }
/**
* Maintain the Order by->Displayed Tree menu.
}
wsmenu.add(secstrmenu);
}
- this.webService.removeAll();
+ resetWebServiceMenu();
for (int i = 0, j = wsmenu.size(); i < j; i++)
{
webService.add( (JMenu) wsmenu.get(i));
}
else
{
- this.webService.removeAll();
+ resetWebServiceMenu();
this.webService.add(this.webServiceNoServices);
}
// TODO: add in rediscovery function
// TODO: group services by location as well as function.
}
+
+ /**
+ * empty the web service menu and add any ad-hoc functions
+ * not dynamically discovered.
+ *
+ */
+ private void resetWebServiceMenu()
+ {
+ webService.removeAll();
+ // Temporary hack - DBRef Fetcher always top level ws entry.
+ JMenuItem rfetch = new JMenuItem("Fetch DB References");
+ rfetch.setToolTipText("Retrieve and parse uniprot records for the alignment or the currently selected sequences");
+ webService.add(rfetch);
+ rfetch.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e)
+ {
+ new jalview.io.DBRefFetcher(
+ alignPanel.av.getSequenceSelection(),
+ alignPanel.alignFrame).fetchDBRefs(false);
+ }
+
+ });
+ }
+
/* public void vamsasStore_actionPerformed(ActionEvent e)
{
JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
-
public void showTranslation_actionPerformed(ActionEvent e)
{
///////////////////////////////
// Collect Data to be translated/transferred
- SequenceI [] selection = viewport.getSelectionAsNewSequence();
+ SequenceI [] selection = viewport.getSequenceSelection();
String [] seqstring = viewport.getViewAsString(true);
AlignmentI al = null;
try {
{
// (isAnnotation)
alignPanel.adjustAnnotationHeight();
+ buildSortByAnnotationScoresMenu();
}
}
{
return viewport;
}
+
+
+ /**
+ * Open the dialog for regex description parsing.
+ */
+ protected void extractScores_actionPerformed(ActionEvent e)
+ {
+ ParseProperties pp = new jalview.analysis.ParseProperties(viewport.alignment);
+ if (pp.getScoresFromDescription("col", "score column ", "\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)")>0)
+ {
+ buildSortByAnnotationScoresMenu();
+ }
+ }
}
class PrintThread