--- /dev/null
+<html>
+<title>Adding Groovy Support to Jalview
+</title>
+<body>
+<h1>
+Adding Groovy Support to Jalview
+</h1>
+<p>
+There is currently no scripting language
+extension within Jalview, in part because a
+scripting API has not been developed.
+</p>
+<p>It is, however, really easy to embed scripting
+engines within Jalview. We haven't done it
+with the Bean Scripting Framework, but the
+code snippets below show you how to get going
+with groovy.
+</p>
+<h2>Modifications</h2>
+<p>
+For each class below, add the following objects and methods to their definitions.
+</p>
+<ul><li>
+jalview.jbgui.GDesktop
+<pre>
+..
+protected JMenuItem groovyShell = new JMenuItem();
+..
+jbInit() {
+..
+groovyShell.setText("Groovy Shell...");
+groovyShell.addActionListener(new ActionListener()
+{
+ public void actionPerformed(ActionEvent e) {
+ groovyShell_actionPerformed(e);
+ }
+});
+..
+}
+..
+protected void groovyShell_actionPerformed(ActionEvent e)
+{
+}
+..
+</pre></li>
+<li>jalview.gui.Desktop
+<pre>
+..
+/**
+ * Accessor method to quickly get all the AlignmentFrames
+ * loaded.
+ */
+protected AlignFrame[] getAlignframes() {
+ JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+ if (frames == null)
+ {
+ return null;
+ }
+ Vector avp=new Vector();
+ try
+ {
+ //REVERSE ORDER
+ for (int i = frames.length - 1; i > -1; i--)
+ {
+ if (frames[i] instanceof AlignFrame)
+ {
+ AlignFrame af = (AlignFrame) frames[i];
+ avp.addElement(af);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ if (avp.size()==0)
+ {
+ return null;
+ }
+ AlignFrame afs[] = new AlignFrame[avp.size()];
+ for (int i=0,j=avp.size(); i<j; i++) {
+ afs[i] = (AlignFrame) avp.elementAt(i);
+ }
+ avp.clear();
+ return afs;
+}
+
+/**
+ * Add Groovy Support to Jalview
+ */
+public void groovyShell_actionPerformed(ActionEvent e) {
+ Console gc = new Console();
+ gc.setVariable("Jalview", this);
+ gc.run();
+}
+..
+</pre>
+</li>
+</ul>
+<p>
+Finally, compile and run with the groovy-all-*.jar (get the jar
+from the <em>embedded</em> directory within the <a
+href="http://dist.codehaus.org/groovy/distributions"/>groovy distribution</a>).
+Then, you should be able to open the Groovy shell
+window from the Desktop's Tools menu. To check things are working,
+try a simple test script :<br>
+<pre>
+
+ print Jalview.getAlignframes()[0].getTitle();
+</pre>
+Executing this will print the title of the first alignment loaded into Jalview.</p>
+</hr>
+<h2>TODO</h2>
+<p>
+Using Java class methods from Groovy is straightforward, but currently, there isn't a set of easy to use methods for the jalview objects. A Jalview Scripting API needs to be developed to make this easier.</p>
+<h3>Making it easier</h3>
+<p>jalview.bin.JalviewScript could be a top level jalview instance of a script execution thread, creating and maintaining the context for scripts operating on the jalview datamodel and interfacing with the Jalview GUI.
+</p>
+</body>
+</html>
+
--- /dev/null
+<html>
+<head>
+Background Dependent Text Colour
+</head>
+<body>
+<strong>Background Dependent Text Colour</strong>
+<p>The <strong>Colour→Text Colour</strong> menu entry opens
+the <strong>"Adjust Foreground Text Colour Threshold"</strong>
+dialog box, allowing the colour of symbols rendered on dark or light
+backgrounds to be set for the current selection or the whole alignment.
+</p>
+<p><img src="textcolour.gif"></p>
+<p>The dialog box contains a slider, and two colour icons showing
+the text colour for dark backgrounds (left hand end of slider), and
+light backgrounds (right hand end of slider). Drag the slider to change
+the threshold for transitioning between dark and light background
+colours, and select either of the colour boxes to open a colour chooser
+to select a different text colour.</p>
+</body>
+</html>
--- /dev/null
+<html>
+<title>Jalview Command Line Arguments
+</title>
+<body>
+ <p><strong>The Jalview Executable's Command Line
+ Arguments</strong></p>
+ See <a href="commandline.html">running Jalview from the command
+ line</a> for more information.<br>
+ <table width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr >
+ <td width="27%"><div align="center">-nodisplay</div></td>
+ <td width="73%"><div align="left">Run Jalview without User Interface.</div></td>
+ </tr>
+
+ <tr>
+ <td><div align="center">-props FILE</div></td>
+ <td><div align="left">Use the given Jalview properties file instead
+ of users default.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-features FILE</div></td>
+ <td><div align="left">
+ <p>Use the given file to add sequence features to an alignment.
+ See <a href="featuresFormat.html" target="NEW">Features
+ File</a> (Known as Groups file prior to 2.08) description. </p>
+
+ </div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-annotations FILE</div></td>
+ <td>Add precalculated annotations to the alignment. See <a href="annotationsFormat.html" target="NEW">Annotation
+ File</a> description.</td>
+ </tr>
+ <tr>
+ <td><div align="center">-fasta FILE</div></td>
+
+ <td><div align="left">Create alignment file FILE in Fasta format.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-clustal FILE</div></td>
+ <td><div align="left">Create alignment file FILE in Clustal format.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-msf FILE</div></td>
+
+ <td><div align="left">Create alignment file FILE in MSF format.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-pileup FILE</div></td>
+ <td><div align="left">Create alignment file FILE in Pileup format.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-pir FILE</div></td>
+
+ <td><div align="left">Create alignment file FILE in PIR format.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-blc FILE</div></td>
+ <td><div align="left">Create alignment file FILE in BLC format.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-jalview FILE</div></td>
+
+ <td><div align="left">Create alignment file FILE in Jalview format.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-png FILE</div></td>
+ <td><div align="left">Create PNG image FILE from alignment.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-imgMap FILE</div></td>
+
+ <td><div align="left">Create HTML file FILE with image map of PNG
+ image.</div></td>
+ </tr>
+ <tr>
+ <td><div align="center">-eps FILE</div></td>
+ <td><div align="left">Create EPS file FILE from alignment.</div></td>
+ </tr>
+ </table>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<title>DNA Sequence Coding Region Definition</title>
+</head>
+<body>
+<p><strong>DNA Sequence Coding Region Definition</strong></p>
+<p>Jalview includes the standard DNA codon translation table in\r
+order to be able to dynamically translate cDNA to its expressed\r
+protein sequence. DNA Sequence Coding Regions are sequence \r
+features that can be defined on any DNA sequence in order to\r
+mark stretches of cDNA that will be concatenated to form the\r
+series of codons that are translated by the <strong>"\r
+Calculate→Translate cDNA"</strong> menu function. \r
+</p>\r
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<html>\r
+<head><title>Running Jalview from the command line</title></head>\r
+<body>\r
+ <p><strong>Running Jalview from the command line</strong></p>\r
+ <p>Jalview is most easily run from the command line if you have built\r
+ it from source, or via the 'Jalview' executable created from the\r
+ InstallAnywhere jalview installation. Both of these mechanisms allow\r
+ true command line execution of jalview - allowing you to provide\r
+ additional options.</p><p>\r
+The Java Webstart version of\r
+ jalview can be executed from the command line using something like\r
+ :\r
+ <pre>javaws http://www.jalview.org/webstart/jalview.jnlp -open\r
+ <em>yourFileName</em></pre>\r
+ But, this is not guaranteed to work on all versions of webstart on all\r
+ operating systems, and doesn't let you execute Jalview with any\r
+ additional parameters.\r
+ <p><strong>Running jalview from the InstallAnywhere\r
+ installation</strong></p>\r
+ <p>If you install with InstallAnywhere you can use several more commands. \r
+ However, if you call the application with the link provided by InstallAnywhere \r
+ any output from the application will be sent to output.txt, not standard \r
+ out.<br>\r
+ The jalview application also requires a number of additional\r
+ libraries on the class path. The command line below adds the Jalview\r
+ installation's 'lib' directory to the list of directories that are\r
+ searched for jars to be added to the classpath:</p>\r
+<pre>java -Djava.ext.dirs=$INSTALL_DIR$/lib -cp $INSTALL_DIR$/jalview.jar jalview.bin.Jalview -open [FILE] </pre>\r
+ <p>Use '-help' to get more information on the <a\r
+ href="clarguments.html">command line arguments</a> that Jalview\r
+ accepts.</p>\r
+ <p> </p>\r
+ <p> </p>\r
+ </body>\r
+ </html>\r
--- /dev/null
+<html>
+<head>
+<title>Creating Sequence Features</title>
+</head>
+<body>
+<strong>Creating Sequence Features</strong>
+<p>Jalview can create sequence features from the matches of a <a
+ href="search.html">regular expression search</a>, or from the currently
+selected area via the <strong>"selection→Create
+sequence feature"</strong> entry in the <a href="../menus/popupMenu.html">selection area popup menu</a>. In both
+cases, the <strong>Create Features</strong> dialog box will then be
+opened:</p>
+<p><img src="crnewfeature.gif"></p>
+<p>Select or enter the attributes for the features being created,
+and then press OK to create the new features.</p>
+<p>Each attribute is described below:
+<ul>
+ <li><strong>Sequence Feature Name</strong>
+ <p>Either give the new features a new name or use the menu to
+ re-use an existing feature name.</p>
+ </li>
+ <li><strong>Feature group</strong>
+ <p>Enter a new group name, or re-use an existing group from the
+ pull-down menu.</p>
+ </li>
+ <li><strong>Feature Colour</strong>
+ <p>Keep the existing colour for this feature's name and group, or
+ select the colour box to open a colour chooser to pick a different one.</p>
+ </li>
+ <li><strong>Description</strong>
+ <p>Enter a description for all the features being created. Each
+ feature defined on a sequence may have its own description that will be
+ displayed in the tooltip for the feature in that region.</p>
+ </li>
+</ul>
+</p><p><em>Sequence Feature Creation was introduced in Jalview Version 2.2</em></p>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<html>
+<head>
+<title>Amending or Deleting Sequence Features</title>
+</head>
+<body>
+<strong>Amending or Deleting Sequence Features</strong>
+<p>Double clicking a position in the alignment with one or more
+displayed sequence features opens the <strong>"Amend/Delete
+Features"</strong> dialog box.</p>
+<p><img src="amendfeature.gif"></p>
+<p>The dialog box only allows one of the features at the
+double-clicked position to be edited or deleted at a time, and it will
+also be highlighted in black in the alignment window.</p>
+<p>Choose which feature is to be modified by selecting it from the <strong>Sequence
+Feature Name</strong> <!-- and <strong>Feature Group</strong> --> pull down
+menu. In addition to the Name, group, colour and description attributes
+described for the <a href="creatinFeatures.html">new feature dialog
+box</a>, a feature's start and end position can be changed either by
+entering a new position directly or by using the adjacent up and down
+buttons.</p>
+<p>Select <strong>Amend</strong> to update the feature, <strong>Delete</strong>
+to remove the selected feature, or <strong>Cancel</strong> to leave the
+feature unchanged.</p>
+<p><em>Sequence feature editing was implemented in Jalview 2.2</em></p>
+</body>
+</html>
--- /dev/null
+<html>\r
+<head>\r
+<title>Multiple Alignment Views</title>\r
+</head>\r
+<body>\r
+<p><strong>Multiple Alignment Views</strong></p>\r
+<p>Multiple alignment views allows the same alignment to be viewed\r
+independently in many different ways simultaneously. Each view is an\r
+independent visualization of the same alignment, so each may have a\r
+different ordering, colouring, row and column hiding and seuqence\r
+feature and annotation display setting, but alignment, feature and\r
+annotation edits are common to all, since this affects the underlying\r
+data.</p>\r
+<p>Create a new view using the <strong>"View→New\r
+View"</strong> menu item, or by pressing <strong>Control+T</strong>. A newly\r
+created view will be identical to the view it was created from, but any\r
+changes to the way the alignment is coloured or displayed will only\r
+affect the new view.</p>\r
+<p>A particular view may focus on some specific aspect of an\r
+alignment - for example, hiding all but the region of an alignment\r
+containing a particular domain. <strong>Right-clicking</strong> a view's\r
+tab opens the View Name dialog box, allowing it to be renamed to\r
+something more meaningful.</p>\r
+<p><strong>Viewing Multiple Views Simultaneously</strong></p>\r
+<p>Multiple views of an alignment are, by default, gathered together\r
+as tabs within a single alignment window. They can be viewed\r
+simultanously by pressing <strong>X</strong> (or via <strong>"View→Expand"</strong>)\r
+to expand each view into its own linked alignment window. Expanded views\r
+are gathered back into into a single tabbed alignment window by pressing\r
+<strong>G</strong>, or by selecting <strong>"View→Gather"</strong>).\r
+</p>\r
+<p><strong>Hidden Sequence Representatives and Multiple\r
+Views</strong></p>\r
+<p>There are some unexpected interactions between hidden sequence\r
+representatives and their display in multiple views. See the\r
+corresponding entry in the <a href="hiddenRegions.html">documentation\r
+for hidden regions</a>.</p>\r
+<p><strong>Structure and Analysis Viewers and Multiple\r
+Views</strong></p>\r
+<p>A tree calculated on a particular view, or loaded onto it, is by\r
+default associated with just that view. However, the <a\r
+ href="../calculations/treeviewer.html">Tree Viewer's</a> <strong>"View→Associate\r
+leaves"</strong> submenu allows a tree's view association to be changed to\r
+to any or all other views.</p>\r
+<p>The results of a <a href="../calculations/pca.html">PCA\r
+calculation</a> on a particular view may also be associated with other\r
+views, using the PCA Viewer's <strong>"View→Associate\r
+Nodes"</strong> submenu.</p>\r
+<p>Currently, a <a href="pdbviewer.html">PDB Structure Viewer</a>\r
+opened on a structure associated with a sequence in a particular view\r
+will only be associated with the seuqence as displayed in that view. <br>\r
+<em>This will be resolved in a future release</em><!-- also, by default, only be associated\r
+with the sequence as it is displayed in that view. The\r
+"View→Associate View" submenu allows the association of\r
+alternative views.</p> -->\r
+<p><em>Multiple Views were introduced in Jalview 2.2</em></p>\r
+</body>\r
+</html>\r
--- /dev/null
+<html>
+<title>New Key Strokes and Menus</title>
+<body>
+<strong>New Key Strokes and Menus</strong>
+<p>Many new <a href="../keys.html">keyboard shortcuts</a> have been
+added in Jalview 2.2 to make editing, selecting and navigating an
+alignment even easier. The selection commands in the <strong>Edit</strong>
+menu, and the alignment formatting controls within the <strong>View</strong>
+menu have also been moved into their own respective <strong>Select</strong>
+and <strong>Format</strong> menus.</p>
+<p>Some of the more important new keystrokes are shown below :
+<ul>
+ <li><strong>Page Up</strong> and <strong>Page Down</strong>
+ scrolls through the alignment view.</li>
+ <li><strong>Control I</strong> inverts the currently selected
+ sequence set, and <strong>Control Alt I</strong> will invert the
+ currently selected set of columns.
+ <li><strong>Control V</strong> will paste the contents of the
+ clipboard to the current alignment window, and <strong>Control
+ Shift V</strong> pastes the data to a new window.</li>
+ <li><strong>Control O</strong> opens the file browser for loading
+ a new alignment or Jalview archive.</li>
+ <li><strong>Control S</strong> saves the alignment with the
+ current filename and format, and <strong>Control Shift S</strong> opens
+ the <strong>Save As...</strong> dialog box.</li>
+ <li><strong>Control T</strong> creates a new alignment view, and <strong>Control
+ W</strong> closes the current view, or if none remain, then the whole alignment.</li>
+ <li><strong>Control E</strong> will remove gapped columns in the alignment.</li>
+ <li><strong>Control D</strong> opens the <strong>Remove Redundancy</strong> dialog box.</li>
+</ul>
+</p>
+</body>
+</html>
--- /dev/null
+<html>
+<head>\r
+<title>Mapping Between Different Sequences</title>\r
+</head>\r
+<body>
+<p><strong>Mapping Between Different Sequences</strong></p>\r
+<p>A new feature in Jalview 2.8 is the ability to map \r
+between sequences in different domains, based on alignment, \r
+or by the use of explicit mappings provided by databases.\r
+</p>\r
+<p>The most familiar mapping is the one used to identify\r
+the coordinates corresponding to a displayed sequence when\r
+viewing a PDB file associated with a sequence (see \r
+<a href="viewingpdbs.html">"Viewing PDB Files"</a> \r
+for more information.</p>\r
+<p>The newest form of mapping supported by Jalview is the \r
+correspondence between DNA and protein sequences. This mapping\r
+can be imported directly from EMBL and EMBLCDS database records \r
+retrieved by the <a href="seqfetch.html">Sequence Fetcher</a>,\r
+or by the definition of <a href="codingfeatures.html">coding regions</a>. \r
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<html>\r
+<head>\r
+<p><strong>Alignment Window Format Menu</strong></p>\r
+<ul>\r
+ <li><strong>Font...</strong><br>\r
+ <em>Opens the "Choose Font" dialog box, in order to change the font \r
+ of the display and enable or disable 'smooth fonts' (anti-aliasing) for faster \r
+ alignment rendering. </em></em></li>\r
+ <li><strong>Wrap<br>\r
+ </strong><em>When ticked, the alignment display is "<a\r
+ href="../features/wrap.html">wrapped</a>" to the width of the alignment \r
+ window. This is useful if your alignment has only a few sequences to view \r
+ its full width at once.<br>\r
+ Additional options for display of sequence numbering and scales are also visible \r
+ in wrapped layout mode:</em>\r
+ <ul>\r
+ <li><strong>Scale Left</strong><br>\r
+ <em>Show the sequence position for the first aligned residue in each row \r
+ in the left column of the alignment.</em></li>\r
+ <li><strong>Scale Right</strong><br>\r
+ <em>Show the sequence position for the last aligned residue in each row \r
+ in the right-most column of the alignment.</em></li>\r
+ </ul>\r
+ \r
+ <li><strong>Scale Above</strong><br>\r
+ <em>Show the alignment column position scale.</em></li>\r
+ <li><strong>Show Sequence Limits<br>\r
+ </strong><em>If this box is selected the sequence name will have the start \r
+ and end position of the sequence appended to the name, in the format NAME/START-END</em></li>\r
+ <li><strong>Right Align Sequence ID<br>\r
+ </strong> <em>If this box is selected then the sequence names displayed in \r
+ the sequence label area will be aligned against the left-hand edge of the \r
+ alignment display, rather than the left-hand edge of the alignment window.</em></li>\r
+ <li><strong>Show Hidden Markers<br>\r
+ </strong><em>When this box is selected, positions in the alignment where rows \r
+ and columns are hidden will be marked by blue arrows.</em></li>\r
+ <li><strong>Boxes</strong><em><br>\r
+ If this is selected the background of a residue will be coloured using the \r
+ selected background colour. Useful if used in conjunction with "Colour \r
+ Text." </em></li>\r
+ <li><strong>Text<br>\r
+ </strong><em>If this is selected the residues will be displayed using the \r
+ standard 1 character amino acid alphabet.</em></li>\r
+ <li><strong>Colour Text<br>\r
+ </strong><em>If this is selected the residues will be coloured according to \r
+ the background colour associated with that residue. The colour is slightly \r
+ darker than background so the amino acid symbol remains visible. </em></li>\r
+ <li><strong>Show Gaps<br>\r
+ </strong><em>When this is selected, gap characters will be displayed as "." \r
+ or "-". If unselected, then gap characters will appear as blank \r
+ spaces. <br>\r
+ You may set the default gap character in <a\r
+ href="../features/preferences.html">preferences</a>.</em></li>\r
+</ul>\r
+</body>\r
+</html>\r
--- /dev/null
+<html>\r
+<head><body>\r
+<p><strong>Alignment Window Select Menu</strong></p>\r
+<ul>\r
+ \r
+ <li><a href="../features/search.html"><strong>Find... (Control F)</strong></a><br>\r
+ <em>Opens the Find dialog box to search for residues, sequence name or residue \r
+ position within the alignment and create new sequence features from the queries. \r
+ </em>\r
+ <li><strong>Select All (Control A)</strong><strong><br>\r
+ </strong><em>Selects all the sequences and residues in the alignment. <br>\r
+ Use <CTRL> and A (<APPLE> and A on a MacOSX) to select all.</em></em></li>\r
+ <li><strong>Deselect All (Escape)<br>\r
+ </strong><em>Removes the current selection box (red dashed box) from the\r
+ alignment window. All selected sequences, residues and marked columns\r
+ will be deselected. </em><em> <br>\r
+ Use <ESCAPE> to deselect all.</em></li>\r
+ <li><strong>Invert Sequence Selection (Control I)<br>\r
+ </strong><em>Any sequence ids currently not selected will replace the\r
+ current selection. </em></li>\r
+ <li><strong>Invert Column Selection (Control Alt I)<br>\r
+ </strong><em>Any columns currently not selected will replace the current\r
+ column selection. </em></li>\r
+ <li><strong>Undefine Groups (Control U)<br>\r
+ </strong><em>The alignment will be reset with no defined groups.<br>\r
+ <strong>WARNING</strong>: This cannot be undone.</em></li>\r
+</ul>\r
+</body>\r
+</html>\r
--- /dev/null
+package jalview.analysis;\r
+\r
+import java.util.*;\r
+\r
+import jalview.datamodel.*;\r
+\r
+public class Finder\r
+{\r
+ /**\r
+ * Implements the search algorithms for the Find dialog box.\r
+ */\r
+ SearchResults searchResults;\r
+ AlignmentI alignment;\r
+ jalview.datamodel.SequenceGroup selection = null;\r
+ Vector idMatch = null;\r
+ boolean caseSensitive = false;\r
+ boolean findAll = false;\r
+ com.stevesoft.pat.Regex regex = null;\r
+ /**\r
+ * hold's last-searched position between calles to find(false)\r
+ */\r
+ int seqIndex = 0, resIndex = 0;\r
+ public Finder(AlignmentI alignment, SequenceGroup selection)\r
+ {\r
+ this.alignment = alignment;\r
+ this.selection = selection;\r
+ }\r
+\r
+ public Finder(AlignmentI alignment, SequenceGroup selectionGroup,\r
+ int seqIndex, int resIndex)\r
+ {\r
+ this(alignment, selectionGroup);\r
+ this.seqIndex = seqIndex;\r
+ this.resIndex = resIndex;\r
+ }\r
+\r
+ public boolean find(String searchString)\r
+ {\r
+ boolean hasResults = false;\r
+ if (!caseSensitive)\r
+ {\r
+ searchString = searchString.toUpperCase();\r
+ }\r
+ regex = new com.stevesoft.pat.Regex(searchString);\r
+ searchResults = new SearchResults();\r
+ idMatch = new Vector();\r
+ Sequence seq;\r
+ String item = null;\r
+ boolean found = false;\r
+\r
+ ////// is the searchString a residue number?\r
+ try\r
+ {\r
+ int res = Integer.parseInt(searchString);\r
+ found = true;\r
+ if (selection == null || selection.getSize() < 1)\r
+ {\r
+ seq = (Sequence) alignment.getSequenceAt(0);\r
+ }\r
+ else\r
+ {\r
+ seq = (Sequence) (selection.getSequenceAt(0));\r
+ }\r
+\r
+ searchResults.addResult(seq, res, res);\r
+ hasResults = true;\r
+ }\r
+ catch (NumberFormatException ex)\r
+ {\r
+ }\r
+\r
+ ///////////////////////////////////////////////\r
+\r
+ int end = alignment.getHeight();\r
+\r
+ if (selection != null)\r
+ {\r
+ if ( (selection.getSize() < 1) ||\r
+ ( (selection.getEndRes() - selection.getStartRes()) < 2))\r
+ {\r
+ selection = null;\r
+ }\r
+ }\r
+\r
+ while (!found && (seqIndex < end))\r
+ {\r
+ seq = (Sequence) alignment.getSequenceAt(seqIndex);\r
+\r
+ if ( (selection != null) && !selection.getSequences(null).contains(seq))\r
+ {\r
+ seqIndex++;\r
+ resIndex = 0;\r
+\r
+ continue;\r
+ }\r
+\r
+ item = seq.getSequenceAsString();\r
+ // JBPNote - check if this toUpper which is present in the application implementation makes a difference\r
+ //if(!caseSensitive)\r
+ // item = item.toUpperCase();\r
+\r
+ if ( (selection != null) &&\r
+ (selection.getEndRes() < alignment.getWidth() - 1))\r
+ {\r
+ item = item.substring(0, selection.getEndRes() + 1);\r
+ }\r
+\r
+ ///Shall we ignore gaps???? - JBPNote: Add Flag for forcing this or not\r
+ StringBuffer noGapsSB = new StringBuffer();\r
+ int insertCount = 0;\r
+ Vector spaces = new Vector();\r
+\r
+ for (int j = 0; j < item.length(); j++)\r
+ {\r
+ if (!jalview.util.Comparison.isGap(item.charAt(j)))\r
+ {\r
+ noGapsSB.append(item.charAt(j));\r
+ spaces.addElement(new Integer(insertCount));\r
+ }\r
+ else\r
+ {\r
+ insertCount++;\r
+ }\r
+ }\r
+\r
+ String noGaps = noGapsSB.toString();\r
+\r
+ for (int r = resIndex; r < noGaps.length(); r++)\r
+ {\r
+\r
+ if (regex.searchFrom(noGaps, r))\r
+ {\r
+ resIndex = regex.matchedFrom();\r
+\r
+ if ( (selection != null) &&\r
+ ( (resIndex +\r
+ Integer.parseInt(spaces.elementAt(resIndex).toString())) <\r
+ selection.getStartRes()))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ int sres = seq.findPosition(resIndex +\r
+ Integer.parseInt(spaces.elementAt(\r
+ resIndex)\r
+ .toString()));\r
+ int eres = seq.findPosition(regex.matchedTo() - 1 +\r
+ Integer.parseInt(spaces.elementAt(regex.\r
+ matchedTo() -\r
+ 1).toString()));\r
+\r
+ searchResults.addResult(seq, sres, eres);\r
+ hasResults = true;\r
+ if (!findAll)\r
+ {\r
+ // thats enough, break and display the result\r
+ found = true;\r
+ resIndex++;\r
+\r
+ break;\r
+ }\r
+\r
+ r = resIndex;\r
+ }\r
+ else\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!found)\r
+ {\r
+ seqIndex++;\r
+ resIndex = 0;\r
+ }\r
+ }\r
+\r
+ for (int id = 0; id < alignment.getHeight(); id++)\r
+ {\r
+ if (regex.search(alignment.getSequenceAt(id).getName()))\r
+ {\r
+ idMatch.addElement(alignment.getSequenceAt(id));\r
+ hasResults = true;\r
+ }\r
+ }\r
+ return hasResults;\r
+ }\r
+\r
+ /**\r
+ * @return the alignment\r
+ */\r
+ public AlignmentI getAlignment()\r
+ {\r
+ return alignment;\r
+ }\r
+\r
+ /**\r
+ * @param alignment the alignment to set\r
+ */\r
+ public void setAlignment(AlignmentI alignment)\r
+ {\r
+ this.alignment = alignment;\r
+ }\r
+\r
+ /**\r
+ * @return the caseSensitive\r
+ */\r
+ public boolean isCaseSensitive()\r
+ {\r
+ return caseSensitive;\r
+ }\r
+\r
+ /**\r
+ * @param caseSensitive the caseSensitive to set\r
+ */\r
+ public void setCaseSensitive(boolean caseSensitive)\r
+ {\r
+ this.caseSensitive = caseSensitive;\r
+ }\r
+\r
+ /**\r
+ * @return the findAll\r
+ */\r
+ public boolean isFindAll()\r
+ {\r
+ return findAll;\r
+ }\r
+\r
+ /**\r
+ * @param findAll the findAll to set\r
+ */\r
+ public void setFindAll(boolean findAll)\r
+ {\r
+ this.findAll = findAll;\r
+ }\r
+\r
+ /**\r
+ * @return the selection\r
+ */\r
+ public jalview.datamodel.SequenceGroup getSelection()\r
+ {\r
+ return selection;\r
+ }\r
+\r
+ /**\r
+ * @param selection the selection to set\r
+ */\r
+ public void setSelection(jalview.datamodel.SequenceGroup selection)\r
+ {\r
+ this.selection = selection;\r
+ }\r
+\r
+ /**\r
+ * @return the idMatch\r
+ */\r
+ public Vector getIdMatch()\r
+ {\r
+ return idMatch;\r
+ }\r
+\r
+ /**\r
+ * @return the regex\r
+ */\r
+ public com.stevesoft.pat.Regex getRegex()\r
+ {\r
+ return regex;\r
+ }\r
+\r
+ /**\r
+ * @return the searchResults\r
+ */\r
+ public SearchResults getSearchResults()\r
+ {\r
+ return searchResults;\r
+ }\r
+\r
+ /**\r
+ * @return the resIndex\r
+ */\r
+ public int getResIndex()\r
+ {\r
+ return resIndex;\r
+ }\r
+\r
+ /**\r
+ * @param resIndex the resIndex to set\r
+ */\r
+ public void setResIndex(int resIndex)\r
+ {\r
+ this.resIndex = resIndex;\r
+ }\r
+\r
+ /**\r
+ * @return the seqIndex\r
+ */\r
+ public int getSeqIndex()\r
+ {\r
+ return seqIndex;\r
+ }\r
+\r
+ /**\r
+ * @param seqIndex the seqIndex to set\r
+ */\r
+ public void setSeqIndex(int seqIndex)\r
+ {\r
+ this.seqIndex = seqIndex;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+\r
+package jalview.appletgui;\r
+\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+\r
+public class EditNameDialog\r
+ extends Dialog implements ActionListener\r
+{\r
+ TextField id, description;\r
+ Button ok = new Button("Accept");\r
+ Button cancel = new Button("Cancel");\r
+ boolean accept = false;\r
+\r
+ public String getName()\r
+ {\r
+ return id.getText();\r
+ }\r
+\r
+ public String getDescription()\r
+ {\r
+ if (description.getText().length() < 1)\r
+ {\r
+ return null;\r
+ }\r
+ else\r
+ {\r
+ return description.getText();\r
+ }\r
+ }\r
+\r
+ public EditNameDialog(String name,\r
+ String desc,\r
+ String label1,\r
+ String label2,\r
+ AlignmentPanel ap,\r
+ String title)\r
+ {\r
+ super(ap.alignFrame, title, true);\r
+\r
+ id = new TextField(name, 40);\r
+ description = new TextField(desc, 40);\r
+ Panel panel = new Panel(new BorderLayout());\r
+ Panel panel2 = new Panel(new BorderLayout());\r
+ Label label = new Label(label1);\r
+ label.setFont(new Font("Monospaced", Font.PLAIN, 12));\r
+ panel2.add(label, BorderLayout.WEST);\r
+ panel2.add(id, BorderLayout.CENTER);\r
+ panel.add(panel2, BorderLayout.NORTH);\r
+ panel2 = new Panel(new BorderLayout());\r
+ label = new Label(label2);\r
+ label.setFont(new Font("Monospaced", Font.PLAIN, 12));\r
+ panel2.add(label, BorderLayout.WEST);\r
+ panel2.add(description, BorderLayout.CENTER);\r
+ panel.add(panel2, BorderLayout.CENTER);\r
+\r
+ panel2 = new Panel(new FlowLayout());\r
+\r
+ panel2.add(ok);\r
+ panel2.add(cancel);\r
+ ok.addActionListener(this);\r
+ cancel.addActionListener(this);\r
+\r
+ panel.add(panel2, BorderLayout.SOUTH);\r
+\r
+ add(panel, BorderLayout.NORTH);\r
+\r
+ int width = 500, height = 100;\r
+\r
+ pack();\r
+\r
+ height += getInsets().top + getInsets().bottom;\r
+\r
+ setBounds(ap.alignFrame.getBounds().x\r
+ + (ap.alignFrame.getSize().width - width) / 2,\r
+ ap.alignFrame.getBounds().y\r
+ + (ap.alignFrame.getSize().height - height) / 2,\r
+ width, height);\r
+\r
+ show();\r
+\r
+ }\r
+\r
+ public void actionPerformed(ActionEvent evt)\r
+ {\r
+ if (evt.getSource() == ok)\r
+ {\r
+ accept = true;\r
+ }\r
+\r
+ setVisible(false);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+package jalview.commands;\r
+\r
+import jalview.datamodel.*;\r
+\r
+public class ChangeCaseCommand\r
+ implements CommandI\r
+{\r
+ String description;\r
+ public static int TO_LOWER = 0;\r
+ public static int TO_UPPER = 1;\r
+ public static int TOGGLE_CASE = 2;\r
+ int caseChange = -1;\r
+ SequenceI[] seqs;\r
+ int[][] regions;\r
+ public ChangeCaseCommand(String description,\r
+ SequenceI[] seqs,\r
+ int[][] regions,\r
+ int caseChange)\r
+ {\r
+ this.description = description;\r
+ this.seqs = seqs;\r
+ this.regions = regions;\r
+ this.caseChange = caseChange;\r
+ doCommand();\r
+ }\r
+\r
+ public String getDescription()\r
+ {\r
+ return description;\r
+ }\r
+\r
+ public int getSize()\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ public void doCommand()\r
+ {\r
+ changeCase(true);\r
+ }\r
+\r
+ public void undoCommand()\r
+ {\r
+ changeCase(false);\r
+ }\r
+\r
+ void changeCase(boolean doCommand)\r
+ {\r
+ String sequence;\r
+ int start, end;\r
+ char nextChar;\r
+ for (int r = 0; r < regions.length; r++)\r
+ {\r
+ start = regions[r][0];\r
+ for (int s = 0; s < seqs.length; s++)\r
+ {\r
+ sequence = seqs[s].getSequenceAsString();\r
+ StringBuffer newSeq = new StringBuffer();\r
+\r
+ if (regions[r][1] > sequence.length())\r
+ {\r
+ end = sequence.length();\r
+ }\r
+ else\r
+ {\r
+ end = regions[r][1];\r
+ }\r
+\r
+ if (start > 0)\r
+ {\r
+ newSeq.append(sequence.substring(0, start));\r
+ }\r
+\r
+ if ( (caseChange == TO_UPPER && doCommand)\r
+ || (caseChange == TO_LOWER && !doCommand))\r
+ {\r
+ newSeq.append(sequence.substring(start, end).toUpperCase());\r
+ }\r
+\r
+ else if ( (caseChange == TO_LOWER && doCommand)\r
+ || (caseChange == TO_UPPER && !doCommand))\r
+ {\r
+ newSeq.append(sequence.substring(start, end).toLowerCase());\r
+ }\r
+\r
+ else //TOGGLE CASE\r
+ {\r
+ for (int c = start; c < end; c++)\r
+ {\r
+ nextChar = sequence.charAt(c);\r
+ if ('a' <= nextChar && nextChar <= 'z')\r
+ {\r
+ // TO UPPERCASE !!!\r
+ nextChar -= ('a' - 'A');\r
+ }\r
+ else if ('A' <= nextChar && nextChar <= 'Z')\r
+ {\r
+ // TO LOWERCASE !!!\r
+ nextChar += ('a' - 'A');\r
+ }\r
+ newSeq.append(nextChar);\r
+ }\r
+ }\r
+\r
+ if (end < sequence.length())\r
+ {\r
+ newSeq.append(sequence.substring(end));\r
+ }\r
+\r
+ seqs[s].setSequence(newSeq.toString());\r
+ }\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+package jalview.commands;\r
+\r
+public interface CommandI\r
+{\r
+ public void doCommand();\r
+\r
+ public void undoCommand();\r
+\r
+ public String getDescription();\r
+\r
+ public int getSize();\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+package jalview.commands;\r
+\r
+import java.util.*;\r
+\r
+import jalview.datamodel.*;\r
+\r
+/**\r
+ *\r
+ * <p>Title: EditCommmand</p>\r
+ *\r
+ * <p>Description: Essential information for performing\r
+ * undo and redo for cut/paste insert/delete gap\r
+ * which can be stored in the HistoryList </p>\r
+ *\r
+ * <p>Copyright: Copyright (c) 2006</p>\r
+ *\r
+ * <p>Company: Dundee University</p>\r
+ *\r
+ * @author not attributable\r
+ * @version 1.0\r
+ */\r
+public class EditCommand\r
+ implements CommandI\r
+{\r
+ public static final int INSERT_GAP = 0;\r
+ public static final int DELETE_GAP = 1;\r
+ public static final int CUT = 2;\r
+ public static final int PASTE = 3;\r
+\r
+ Edit[] edits;\r
+\r
+ String description;\r
+\r
+ public EditCommand()\r
+ {}\r
+\r
+ public EditCommand(String description)\r
+ {\r
+ this.description = description;\r
+ }\r
+\r
+ public EditCommand(String description,\r
+ int command,\r
+ SequenceI[] seqs,\r
+ int position,\r
+ int number,\r
+ AlignmentI al)\r
+ {\r
+ this.description = description;\r
+ if (command == CUT || command == PASTE)\r
+ {\r
+ edits = new Edit[]\r
+ {\r
+ new Edit(command, seqs, position, number, al)};\r
+ }\r
+\r
+ performEdit(0);\r
+ }\r
+\r
+ final public String getDescription()\r
+ {\r
+ return description;\r
+ }\r
+\r
+ public int getSize()\r
+ {\r
+ return edits == null ? 0 : edits.length;\r
+ }\r
+\r
+ final public AlignmentI getAlignment()\r
+ {\r
+ return edits[0].al;\r
+ }\r
+\r
+ final public void appendEdit(int command,\r
+ SequenceI[] seqs,\r
+ int position,\r
+ int number,\r
+ AlignmentI al,\r
+ boolean performEdit)\r
+ {\r
+ Edit edit = new Edit(command, seqs, position, number, al.getGapCharacter());\r
+ if (al.getHeight() == seqs.length)\r
+ {\r
+ edit.al = al;\r
+ edit.fullAlignmentHeight = true;\r
+ }\r
+\r
+ if (edits != null)\r
+ {\r
+ Edit[] temp = new Edit[edits.length + 1];\r
+ System.arraycopy(edits, 0, temp, 0, edits.length);\r
+ edits = temp;\r
+ edits[edits.length - 1] = edit;\r
+ }\r
+ else\r
+ {\r
+ edits = new Edit[]\r
+ {\r
+ edit};\r
+ }\r
+\r
+ if (performEdit)\r
+ {\r
+ performEdit(edits.length - 1);\r
+ }\r
+ }\r
+\r
+ final void performEdit(int commandIndex)\r
+ {\r
+ int eSize = edits.length;\r
+ for (int e = commandIndex; e < eSize; e++)\r
+ {\r
+ if (edits[e].command == INSERT_GAP)\r
+ {\r
+ insertGap(edits[e]);\r
+ }\r
+ else if (edits[e].command == DELETE_GAP)\r
+ {\r
+ deleteGap(edits[e]);\r
+ }\r
+ else if (edits[e].command == CUT)\r
+ {\r
+ cut(edits[e]);\r
+ }\r
+ else if (edits[e].command == PASTE)\r
+ {\r
+ paste(edits[e]);\r
+ }\r
+ }\r
+ }\r
+\r
+ final public void doCommand()\r
+ {\r
+ performEdit(0);\r
+ }\r
+\r
+ final public void undoCommand()\r
+ {\r
+ int e = 0, eSize = edits.length;\r
+ for (e = eSize - 1; e > -1; e--)\r
+ {\r
+ if (edits[e].command == INSERT_GAP)\r
+ {\r
+ deleteGap(edits[e]);\r
+ }\r
+ else if (edits[e].command == DELETE_GAP)\r
+ {\r
+ insertGap(edits[e]);\r
+ }\r
+ else if (edits[e].command == CUT)\r
+ {\r
+ paste(edits[e]);\r
+ }\r
+ else if (edits[e].command == PASTE)\r
+ {\r
+ cut(edits[e]);\r
+ }\r
+ }\r
+ }\r
+\r
+ final void insertGap(Edit command)\r
+ {\r
+ for (int s = 0; s < command.seqs.length; s++)\r
+ {\r
+ command.seqs[s].insertCharAt(command.position,\r
+ command.number,\r
+ command.gapChar);\r
+ }\r
+\r
+ adjustAnnotations(command, true);\r
+ }\r
+\r
+ final void deleteGap(Edit command)\r
+ {\r
+ for (int s = 0; s < command.seqs.length; s++)\r
+ {\r
+ command.seqs[s].deleteChars(command.position,\r
+ command.position + command.number);\r
+ }\r
+\r
+ adjustAnnotations(command, false);\r
+ }\r
+\r
+ void cut(Edit command)\r
+ {\r
+ command.string = new char[command.seqs.length][];\r
+\r
+ for (int i = 0; i < command.seqs.length; i++)\r
+ {\r
+ if (command.seqs[i].getLength() > command.position)\r
+ {\r
+ command.string[i] = command.seqs[i].getSequence(command.position,\r
+ command.position + command.number);\r
+\r
+ if (command.seqs[i].getDatasetSequence() != null\r
+ || command.seqs[i].getSequenceFeatures() != null)\r
+ {\r
+ for (int s = command.position; s < command.position + command.number;\r
+ s++)\r
+ {\r
+ if (jalview.schemes.ResidueProperties\r
+ .aaIndex[command.seqs[i].getCharAt(s)] != 23)\r
+ {\r
+ adjustFeatures(command, i,\r
+ command.seqs[i].findPosition(command.position),\r
+ command.seqs[i].findPosition(command.position +\r
+ command.number),\r
+ false);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ command.seqs[i].deleteChars(command.position,\r
+ command.position + command.number);\r
+ }\r
+\r
+ if (command.seqs[i].getLength() < 1)\r
+ {\r
+ command.al.deleteSequence(command.seqs[i]);\r
+ }\r
+ }\r
+\r
+ adjustAnnotations(command, false);\r
+ }\r
+\r
+ void paste(Edit command)\r
+ {\r
+ StringBuffer tmp;\r
+ boolean newDSNeeded;\r
+ int start = 0, end = 0;\r
+\r
+ for (int i = 0; i < command.seqs.length; i++)\r
+ {\r
+ newDSNeeded = false;\r
+ if (command.seqs[i].getLength() < 1)\r
+ {\r
+ // ie this sequence was deleted, we need to\r
+ // read it to the alignment\r
+ if (command.alIndex[i] < command.al.getHeight())\r
+ {\r
+ command.al.getSequences().insertElementAt(command.seqs[i],\r
+ command.alIndex[i]);\r
+ }\r
+ else\r
+ {\r
+ command.al.addSequence(command.seqs[i]);\r
+ }\r
+ }\r
+ tmp = new StringBuffer();\r
+ tmp.append(command.seqs[i].getSequence());\r
+\r
+ if (command.string != null && command.string[i] != null)\r
+ {\r
+ if (command.position >= tmp.length())\r
+ {\r
+ //This occurs if padding is on, and residues\r
+ //are removed from end of alignment\r
+ int length = command.position - tmp.length();\r
+ while (length > 0)\r
+ {\r
+ tmp.append(command.gapChar);\r
+ length--;\r
+ }\r
+ }\r
+ tmp.insert(command.position, command.string[i]);\r
+\r
+ for (int s = 0; s < command.string[i].length; s++)\r
+ {\r
+ if (jalview.schemes.ResidueProperties.aaIndex[command.string[i][s]] !=\r
+ 23)\r
+ {\r
+ newDSNeeded = true;\r
+ start = command.seqs[i].findPosition(command.position);\r
+ end = command.seqs[i].findPosition(command.position +\r
+ command.number);\r
+ break;\r
+ }\r
+ }\r
+ command.string[i] = null;\r
+ }\r
+\r
+ command.seqs[i].setSequence(tmp.toString());\r
+\r
+ if (newDSNeeded)\r
+ {\r
+ if (command.seqs[i].getDatasetSequence() != null)\r
+ {\r
+ Sequence ds = new Sequence(command.seqs[i].getName(),\r
+ jalview.analysis.AlignSeq.extractGaps(\r
+ jalview.util.Comparison.GapChars,\r
+ command.seqs[i].getSequenceAsString()\r
+ ),\r
+ command.seqs[i].getStart(),\r
+ command.seqs[i].getEnd());\r
+ ds.setDescription(command.seqs[i].getDescription());\r
+ command.seqs[i].setDatasetSequence(ds);\r
+ }\r
+\r
+ adjustFeatures(command, i, start, end, true);\r
+ }\r
+ }\r
+\r
+ adjustAnnotations(command, true);\r
+\r
+ command.string = null;\r
+ }\r
+\r
+ final void adjustAnnotations(Edit command, boolean insert)\r
+ {\r
+\r
+ AlignmentAnnotation[] annotations = null;\r
+\r
+ if (command.fullAlignmentHeight)\r
+ {\r
+ annotations = command.al.getAlignmentAnnotation();\r
+ }\r
+ else\r
+ {\r
+ int aSize = 0;\r
+ AlignmentAnnotation[] tmp;\r
+ for (int s = 0; s < command.seqs.length; s++)\r
+ {\r
+ if (command.seqs[s].getAnnotation() == null)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ if (aSize == 0)\r
+ {\r
+ annotations = command.seqs[s].getAnnotation();\r
+ }\r
+ else\r
+ {\r
+ tmp = new AlignmentAnnotation\r
+ [aSize + command.seqs[s].getAnnotation().length];\r
+\r
+ System.arraycopy(annotations, 0, tmp, 0, aSize);\r
+\r
+ System.arraycopy(command.seqs[s].getAnnotation(),\r
+ 0, tmp, aSize,\r
+ command.seqs[s].getAnnotation().length);\r
+\r
+ annotations = tmp;\r
+ }\r
+\r
+ aSize = annotations.length;\r
+ }\r
+ }\r
+\r
+ if (annotations == null)\r
+ {\r
+ return;\r
+ }\r
+\r
+ if (!insert)\r
+ {\r
+ command.deletedAnnotations = new Hashtable();\r
+ }\r
+\r
+ int aSize;\r
+ Annotation[] temp;\r
+ for (int a = 0; a < annotations.length; a++)\r
+ {\r
+ if (annotations[a].autoCalculated)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ int tSize = 0;\r
+\r
+ aSize = annotations[a].annotations.length;\r
+ if (insert)\r
+ {\r
+ temp = new Annotation[aSize + command.number];\r
+ }\r
+ else\r
+ {\r
+ if (command.position < aSize)\r
+ {\r
+ if (command.position + command.number > aSize)\r
+ {\r
+ tSize = aSize;\r
+ }\r
+ else\r
+ {\r
+ tSize = aSize - command.number + command.position;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ tSize = aSize;\r
+ }\r
+\r
+ if (tSize < 0)\r
+ {\r
+ tSize = aSize;\r
+ }\r
+ temp = new Annotation[tSize];\r
+\r
+ }\r
+\r
+ if (insert)\r
+ {\r
+ if (command.position < annotations[a].annotations.length)\r
+ {\r
+ System.arraycopy(annotations[a].annotations,\r
+ 0, temp, 0, command.position);\r
+\r
+ if (command.deletedAnnotations != null\r
+ &&\r
+ command.deletedAnnotations.containsKey(annotations[a].\r
+ annotationId))\r
+ {\r
+ Annotation[] restore = (Annotation[])\r
+ command.deletedAnnotations.get(annotations[a].annotationId);\r
+\r
+ System.arraycopy(restore,\r
+ 0,\r
+ temp,\r
+ command.position,\r
+ command.number);\r
+\r
+ }\r
+\r
+ System.arraycopy(annotations[a].annotations,\r
+ command.position, temp,\r
+ command.position + command.number,\r
+ aSize - command.position);\r
+ }\r
+ else\r
+ {\r
+ if (command.deletedAnnotations != null\r
+ &&\r
+ command.deletedAnnotations.containsKey(annotations[a].\r
+ annotationId))\r
+ {\r
+ Annotation[] restore = (Annotation[])\r
+ command.deletedAnnotations.get(annotations[a].annotationId);\r
+\r
+ temp = new Annotation[annotations[a].annotations.length +\r
+ restore.length];\r
+ System.arraycopy(annotations[a].annotations,\r
+ 0, temp, 0,\r
+ annotations[a].annotations.length);\r
+ System.arraycopy(restore, 0, temp,\r
+ annotations[a].annotations.length, restore.length);\r
+ }\r
+ else\r
+ {\r
+ temp = annotations[a].annotations;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (tSize != aSize || command.position < 2)\r
+ {\r
+ System.arraycopy(annotations[a].annotations,\r
+ 0, temp, 0, command.position);\r
+\r
+ Annotation[] deleted = new Annotation[command.number];\r
+ System.arraycopy(annotations[a].annotations,\r
+ command.position, deleted, 0, command.number);\r
+\r
+ command.deletedAnnotations.put(annotations[a].annotationId,\r
+ deleted);\r
+\r
+ System.arraycopy(annotations[a].annotations,\r
+ command.position + command.number,\r
+ temp, command.position,\r
+ aSize - command.position - command.number);\r
+ }\r
+ else\r
+ {\r
+ int dSize = aSize - command.position;\r
+\r
+ if (dSize > 0)\r
+ {\r
+ Annotation[] deleted = new Annotation[command.number];\r
+ System.arraycopy(annotations[a].annotations,\r
+ command.position, deleted, 0, dSize);\r
+\r
+ command.deletedAnnotations.put(annotations[a].annotationId,\r
+ deleted);\r
+\r
+ tSize = Math.min(annotations[a].annotations.length,\r
+ command.position);\r
+ temp = new Annotation[tSize];\r
+ System.arraycopy(annotations[a].annotations,\r
+ 0, temp, 0, tSize);\r
+ }\r
+ else\r
+ {\r
+ temp = annotations[a].annotations;\r
+ }\r
+ }\r
+ }\r
+\r
+ annotations[a].annotations = temp;\r
+ }\r
+ }\r
+\r
+ final void adjustFeatures(Edit command, int index, int i, int j,\r
+ boolean insert)\r
+ {\r
+ SequenceI seq = command.seqs[index];\r
+ SequenceI sequence = seq.getDatasetSequence();\r
+ if (sequence == null)\r
+ {\r
+ sequence = seq;\r
+ }\r
+\r
+ if (insert)\r
+ {\r
+ if (command.editedFeatures != null\r
+ && command.editedFeatures.containsKey(seq))\r
+ {\r
+ sequence.setSequenceFeatures(\r
+ (SequenceFeature[]) command.editedFeatures.get(seq)\r
+ );\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+ SequenceFeature[] sf = sequence.getSequenceFeatures();\r
+\r
+ if (sf == null)\r
+ {\r
+ return;\r
+ }\r
+\r
+ SequenceFeature[] oldsf = new SequenceFeature[sf.length];\r
+\r
+ int cSize = j - i;\r
+\r
+ for (int s = 0; s < sf.length; s++)\r
+ {\r
+ SequenceFeature copy = new SequenceFeature(sf[s]);\r
+\r
+ oldsf[s] = copy;\r
+\r
+ if (sf[s].getEnd() < i)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ if (sf[s].getBegin() > j)\r
+ {\r
+ sf[s].setBegin(copy.getBegin() - cSize);\r
+ sf[s].setEnd(copy.getEnd() - cSize);\r
+ continue;\r
+ }\r
+\r
+ if (sf[s].getBegin() >= i)\r
+ {\r
+ sf[s].setBegin(i);\r
+ }\r
+\r
+ if (sf[s].getEnd() < j)\r
+ {\r
+ sf[s].setEnd(j - 1);\r
+ }\r
+\r
+ sf[s].setEnd(sf[s].getEnd() - (cSize));\r
+\r
+ if (sf[s].getBegin() > sf[s].getEnd())\r
+ {\r
+ sequence.deleteFeature(sf[s]);\r
+ }\r
+ }\r
+\r
+ if (command.editedFeatures == null)\r
+ {\r
+ command.editedFeatures = new Hashtable();\r
+ }\r
+\r
+ command.editedFeatures.put(seq, oldsf);\r
+\r
+ }\r
+\r
+ class Edit\r
+ {\r
+ boolean fullAlignmentHeight = false;\r
+ Hashtable deletedAnnotations;\r
+ Hashtable editedFeatures;\r
+ AlignmentI al;\r
+ int command;\r
+ char[][] string;\r
+ SequenceI[] seqs;\r
+ int[] alIndex;\r
+ int position, number;\r
+ char gapChar;\r
+\r
+ Edit(int command,\r
+ SequenceI[] seqs,\r
+ int position,\r
+ int number,\r
+ char gapChar)\r
+ {\r
+ this.command = command;\r
+ this.seqs = seqs;\r
+ this.position = position;\r
+ this.number = number;\r
+ this.gapChar = gapChar;\r
+ }\r
+\r
+ Edit(int command,\r
+ SequenceI[] seqs,\r
+ int position,\r
+ int number,\r
+ AlignmentI al)\r
+ {\r
+ this.gapChar = al.getGapCharacter();\r
+ this.command = command;\r
+ this.seqs = seqs;\r
+ this.position = position;\r
+ this.number = number;\r
+ this.al = al;\r
+\r
+ alIndex = new int[seqs.length];\r
+ for (int i = 0; i < seqs.length; i++)\r
+ {\r
+ alIndex[i] = al.findIndex(seqs[i]);\r
+ }\r
+\r
+ fullAlignmentHeight = (al.getHeight() == seqs.length);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+package jalview.commands;\r
+\r
+import jalview.analysis.*;\r
+import jalview.datamodel.*;\r
+\r
+public class OrderCommand\r
+ implements CommandI\r
+{\r
+ String description;\r
+ SequenceI[] seqs;\r
+ SequenceI[] seqs2;\r
+ AlignmentI al;\r
+\r
+ public OrderCommand(String description,\r
+ SequenceI[] seqs,\r
+ AlignmentI al)\r
+ {\r
+ this.description = description;\r
+ this.seqs = seqs;\r
+ this.seqs2 = al.getSequencesArray();\r
+ this.al = al;\r
+ doCommand();\r
+ }\r
+\r
+ public String getDescription()\r
+ {\r
+ return description;\r
+ }\r
+\r
+ public int getSize()\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ public void doCommand()\r
+ {\r
+ AlignmentSorter.setOrder(al, seqs2);\r
+ }\r
+\r
+ public void undoCommand()\r
+ {\r
+ AlignmentSorter.setOrder(al, seqs);\r
+ }\r
+}\r
--- /dev/null
+package jalview.commands;\r
+\r
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+\r
+import jalview.datamodel.*;\r
+\r
+public class RemoveGapColCommand\r
+ extends EditCommand\r
+{\r
+ int columnsDeleted;\r
+ public RemoveGapColCommand(String description,\r
+ SequenceI[] seqs,\r
+ int start, int end, AlignmentI al)\r
+ {\r
+ this.description = description;\r
+\r
+ int j, jSize = seqs.length;\r
+\r
+ int startCol = -1, endCol = -1;\r
+ columnsDeleted = 0;\r
+\r
+ edits = new Edit[0];\r
+\r
+ boolean delete = true;\r
+ for (int i = start; i <= end; i++)\r
+ {\r
+ delete = true;\r
+\r
+ for (j = 0; j < jSize; j++)\r
+ {\r
+ if (seqs[j].getLength() > i)\r
+ {\r
+ if (!jalview.util.Comparison.isGap(seqs[j].getCharAt(i)))\r
+ {\r
+ if (delete)\r
+ {\r
+ endCol = i;\r
+ }\r
+\r
+ delete = false;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (delete && startCol == -1)\r
+ {\r
+ startCol = i;\r
+ }\r
+\r
+ if (!delete && startCol > -1)\r
+ {\r
+ this.appendEdit(DELETE_GAP, seqs,\r
+ startCol - columnsDeleted,\r
+ endCol - startCol,\r
+ al,\r
+ false);\r
+\r
+ columnsDeleted += (endCol - startCol);\r
+ startCol = -1;\r
+ endCol = -1;\r
+ }\r
+ }\r
+\r
+ if (delete && startCol > -1)\r
+ {\r
+ //This is for empty columns at the\r
+ //end of the alignment\r
+\r
+ this.appendEdit(DELETE_GAP, seqs,\r
+ startCol - columnsDeleted,\r
+ end - startCol + 1,\r
+ al,\r
+ false);\r
+\r
+ columnsDeleted += (end - startCol + 1);\r
+ }\r
+\r
+ performEdit(0);\r
+ }\r
+\r
+ public int getSize()\r
+ {\r
+ //We're interested in the number of columns deleted,\r
+ //Not the number of sequence edits.\r
+ return columnsDeleted;\r
+ }\r
+\r
+}\r
--- /dev/null
+package jalview.commands;\r
+\r
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+\r
+import jalview.datamodel.*;\r
+\r
+public class RemoveGapsCommand\r
+ extends EditCommand\r
+{\r
+ public RemoveGapsCommand(String description,\r
+ SequenceI[] seqs, AlignmentI al)\r
+ {\r
+ this.description = description;\r
+ int width = 0;\r
+ for (int i = 0; i < seqs.length; i++)\r
+ {\r
+ if (seqs[i].getLength() > width)\r
+ {\r
+ width = seqs[i].getLength();\r
+ }\r
+ }\r
+\r
+ findGaps(seqs, 0, width, al);\r
+ }\r
+\r
+ public RemoveGapsCommand(String description,\r
+ SequenceI[] seqs,\r
+ int start, int end, AlignmentI al)\r
+ {\r
+ this.description = description;\r
+ findGaps(seqs, start, end, al);\r
+ }\r
+\r
+ void findGaps(SequenceI[] seqs, int start, int end, AlignmentI al)\r
+ {\r
+\r
+ int startCol = -1, endCol = -1;\r
+ int deletedCols = 0;\r
+\r
+ int j, jSize;\r
+\r
+ edits = new Edit[0];\r
+\r
+ boolean delete = true;\r
+ char[] sequence;\r
+\r
+ for (int s = 0; s < seqs.length; s++)\r
+ {\r
+ deletedCols = 0;\r
+ startCol = -1;\r
+ endCol = -1;\r
+ sequence = seqs[s].getSequence(start, end + 1);\r
+\r
+ jSize = sequence.length;\r
+ for (j = 0; j < jSize; j++)\r
+ {\r
+ delete = true;\r
+\r
+ if (!jalview.util.Comparison.isGap(sequence[j]))\r
+ {\r
+ if (delete)\r
+ {\r
+ endCol = j;\r
+ }\r
+\r
+ delete = false;\r
+ }\r
+\r
+ if (delete && startCol == -1)\r
+ {\r
+ startCol = j;\r
+ }\r
+\r
+ if (!delete && startCol > -1)\r
+ {\r
+ this.appendEdit(DELETE_GAP, new SequenceI[]\r
+ {seqs[s]},\r
+ start + startCol - deletedCols,\r
+ endCol - startCol,\r
+ al,\r
+ false);\r
+\r
+ deletedCols += (endCol - startCol);\r
+ startCol = -1;\r
+ endCol = -1;\r
+ }\r
+ }\r
+ if (delete && startCol > -1)\r
+ {\r
+ this.appendEdit(DELETE_GAP, new SequenceI[]\r
+ {seqs[s]},\r
+ start + startCol - deletedCols,\r
+ jSize - startCol,\r
+ al,\r
+ false);\r
+ }\r
+\r
+ }\r
+\r
+ performEdit(0);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+package jalview.commands;\r
+\r
+import java.util.*;\r
+\r
+import jalview.datamodel.*;\r
+import jalview.util.*;\r
+\r
+public class TrimRegionCommand\r
+ extends EditCommand\r
+{\r
+ public static String TRIM_LEFT = "TrimLeft";\r
+ public static String TRIM_RIGHT = "TrimRight";\r
+\r
+ public ColumnSelection colSel = null;\r
+\r
+ int[] start;\r
+\r
+ ShiftList shiftList;\r
+\r
+ SequenceGroup selectionGroup;\r
+\r
+ Vector deletedHiddenColumns;\r
+\r
+ int columnsDeleted;\r
+\r
+ public TrimRegionCommand(String description,\r
+ String command,\r
+ SequenceI[] seqs,\r
+ int column,\r
+ AlignmentI al,\r
+ ColumnSelection colSel,\r
+ SequenceGroup selectedRegion)\r
+ {\r
+ this.description = description;\r
+ this.selectionGroup = selectedRegion;\r
+ this.colSel = colSel;\r
+ if (command.equalsIgnoreCase(TRIM_LEFT))\r
+ {\r
+ if (column == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ columnsDeleted = column;\r
+\r
+ edits = new Edit[]\r
+ {\r
+ new Edit(CUT, seqs, 0, column, al)};\r
+ }\r
+ else if (command.equalsIgnoreCase(TRIM_RIGHT))\r
+ {\r
+ int width = al.getWidth() - column - 1;\r
+ if (width < 2)\r
+ {\r
+ return;\r
+ }\r
+\r
+ columnsDeleted = width - 1;\r
+\r
+ edits = new Edit[]\r
+ {\r
+ new Edit(CUT, seqs, column + 1, width, al)};\r
+ }\r
+\r
+ //We need to keep a record of the sequence start\r
+ //in order to restore the state after a redo\r
+ int i, isize = edits[0].seqs.length;\r
+ start = new int[isize];\r
+ for (i = 0; i < isize; i++)\r
+ {\r
+ start[i] = edits[0].seqs[i].getStart();\r
+ }\r
+\r
+ performEdit(0);\r
+ }\r
+\r
+ void cut(Edit command)\r
+ {\r
+ int column, j, jSize = command.seqs.length;\r
+ for (j = 0; j < jSize; j++)\r
+ {\r
+ if (command.position == 0)\r
+ {\r
+ //This is a TRIM_LEFT command\r
+ column = command.seqs[j].findPosition(command.number);\r
+ command.seqs[j].setStart(column);\r
+ }\r
+ else\r
+ {\r
+ //This is a TRIM_RIGHT command\r
+ column = command.seqs[j].findPosition(command.position) - 1;\r
+ command.seqs[j].setEnd(column);\r
+ }\r
+ }\r
+\r
+ super.cut(command);\r
+\r
+ if (command.position == 0)\r
+ {\r
+ deletedHiddenColumns = colSel.compensateForEdit(0, command.number);\r
+ if (selectionGroup != null)\r
+ {\r
+ selectionGroup.adjustForRemoveLeft(command.number);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ deletedHiddenColumns = colSel.compensateForEdit(command.position,\r
+ command.number);\r
+ if (selectionGroup != null)\r
+ {\r
+ selectionGroup.adjustForRemoveRight(command.position);\r
+ }\r
+ }\r
+ }\r
+\r
+ void paste(Edit command)\r
+ {\r
+ super.paste(command);\r
+ int column, j, jSize = command.seqs.length;\r
+ for (j = 0; j < jSize; j++)\r
+ {\r
+ if (command.position == 0)\r
+ {\r
+ command.seqs[j].setStart(start[j]);\r
+ }\r
+ else\r
+ {\r
+ column = command.seqs[j]\r
+ .findPosition(command.number + command.position) - 1;\r
+ command.seqs[j].setEnd(column);\r
+ }\r
+ }\r
+\r
+ if (command.position == 0)\r
+ {\r
+ colSel.compensateForEdit(0, -command.number);\r
+ if (selectionGroup != null)\r
+ {\r
+ selectionGroup.adjustForRemoveLeft( -command.number);\r
+ }\r
+ }\r
+\r
+ if (deletedHiddenColumns != null)\r
+ {\r
+ int[] region;\r
+ for (int i = 0; i < deletedHiddenColumns.size(); i++)\r
+ {\r
+ region = (int[]) deletedHiddenColumns.elementAt(i);\r
+ colSel.hideColumns(region[0], region[1]);\r
+ }\r
+ }\r
+ }\r
+\r
+ public int getSize()\r
+ {\r
+ return columnsDeleted;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+\r
+package jalview.gui;\r
+\r
+import java.awt.*;\r
+import javax.swing.*;\r
+\r
+public class EditNameDialog\r
+{\r
+ JTextField id, description;\r
+ JButton ok = new JButton("Accept");\r
+ JButton cancel = new JButton("Cancel");\r
+ boolean accept = false;\r
+\r
+ public String getName()\r
+ {\r
+ return id.getText();\r
+ }\r
+\r
+ public String getDescription()\r
+ {\r
+ if (description.getText().length() < 1)\r
+ {\r
+ return null;\r
+ }\r
+ else\r
+ {\r
+ return description.getText();\r
+ }\r
+ }\r
+\r
+ public EditNameDialog(String name,\r
+ String desc,\r
+ String label1,\r
+ String label2,\r
+ String title)\r
+ {\r
+ JLabel idlabel = new JLabel(label1);\r
+ JLabel desclabel = new JLabel(label2);\r
+ idlabel.setFont(new Font("Courier", Font.PLAIN, 12));\r
+ desclabel.setFont(new Font("Courier", Font.PLAIN, 12));\r
+ id = new JTextField(name, 40);\r
+ description = new JTextField(desc, 40);\r
+ JPanel panel = new JPanel(new BorderLayout());\r
+ JPanel panel2 = new JPanel(new BorderLayout());\r
+ panel2.add(idlabel, BorderLayout.WEST);\r
+ panel2.add(id, BorderLayout.CENTER);\r
+ panel.add(panel2, BorderLayout.NORTH);\r
+ panel2 = new JPanel(new BorderLayout());\r
+ panel2.add(desclabel, BorderLayout.WEST);\r
+ panel2.add(description, BorderLayout.CENTER);\r
+ panel.add(panel2, BorderLayout.SOUTH);\r
+\r
+ int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
+ panel, title,\r
+ JOptionPane.OK_CANCEL_OPTION);\r
+\r
+ if (reply == JOptionPane.OK_OPTION)\r
+ {\r
+ accept = true;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+\r
+package jalview.gui;\r
+\r
+import java.util.*;\r
+\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+import javax.swing.*;\r
+import javax.swing.event.*;\r
+\r
+import jalview.datamodel.*;\r
+\r
+public class TextColourChooser\r
+{\r
+ AlignmentPanel ap;\r
+ SequenceGroup sg;\r
+\r
+ public void chooseColour(AlignmentPanel ap, SequenceGroup sg)\r
+ {\r
+ this.ap = ap;\r
+ this.sg = sg;\r
+\r
+ int original1, original2, originalThreshold;\r
+ if (sg == null)\r
+ {\r
+ original1 = ap.av.textColour.getRGB();\r
+ original2 = ap.av.textColour2.getRGB();\r
+ originalThreshold = ap.av.thresholdTextColour;\r
+ }\r
+ else\r
+ {\r
+ original1 = sg.textColour.getRGB();\r
+ original2 = sg.textColour2.getRGB();\r
+ originalThreshold = sg.thresholdTextColour;\r
+ }\r
+\r
+ final JSlider slider = new JSlider(0, 750, originalThreshold);\r
+ final JPanel col1 = new JPanel();\r
+ col1.setPreferredSize(new Dimension(40, 20));\r
+ col1.setBorder(BorderFactory.createEtchedBorder());\r
+ col1.setToolTipText("Dark Colour");\r
+ col1.setBackground(new Color(original1));\r
+ final JPanel col2 = new JPanel();\r
+ col2.setPreferredSize(new Dimension(40, 20));\r
+ col2.setBorder(BorderFactory.createEtchedBorder());\r
+ col2.setToolTipText("Light Colour");\r
+ col2.setBackground(new Color(original2));\r
+ final JPanel bigpanel = new JPanel(new BorderLayout());\r
+ JPanel panel = new JPanel();\r
+ bigpanel.add(panel, BorderLayout.CENTER);\r
+ bigpanel.add(new JLabel(\r
+ "<html><i>Select a dark and light text colour, then set the threshold to"\r
+ + "<br>switch between colours, based on background colour</i></html>"),\r
+ BorderLayout.NORTH);\r
+ panel.add(col1);\r
+ panel.add(slider);\r
+ panel.add(col2);\r
+\r
+ col1.addMouseListener(new MouseAdapter()\r
+ {\r
+ public void mousePressed(MouseEvent e)\r
+ {\r
+ Color col = JColorChooser.showDialog(bigpanel,\r
+ "Select Colour for Text",\r
+ col1.getBackground());\r
+ if (col != null)\r
+ {\r
+ colour1Changed(col);\r
+ col1.setBackground(col);\r
+ }\r
+ }\r
+ });\r
+\r
+ col2.addMouseListener(new MouseAdapter()\r
+ {\r
+ public void mousePressed(MouseEvent e)\r
+ {\r
+ Color col = JColorChooser.showDialog(bigpanel,\r
+ "Select Colour for Text",\r
+ col2.getBackground());\r
+ if (col != null)\r
+ {\r
+ colour2Changed(col);\r
+ col2.setBackground(col);\r
+ }\r
+ }\r
+ });\r
+\r
+ slider.addChangeListener(new ChangeListener()\r
+ {\r
+ public void stateChanged(ChangeEvent evt)\r
+ {\r
+ thresholdChanged(slider.getValue());\r
+ }\r
+ });\r
+\r
+ int reply = JOptionPane.showInternalOptionDialog(\r
+ ap,\r
+ bigpanel,\r
+ "Adjust Foreground Text Colour Threshold",\r
+ JOptionPane.OK_CANCEL_OPTION,\r
+ JOptionPane.QUESTION_MESSAGE,\r
+ null,\r
+ null, null);\r
+\r
+ if (reply == JOptionPane.CANCEL_OPTION)\r
+ {\r
+ if (sg == null)\r
+ {\r
+ ap.av.textColour = new Color(original1);\r
+ ap.av.textColour2 = new Color(original2);\r
+ ap.av.thresholdTextColour = originalThreshold;\r
+ }\r
+ else\r
+ {\r
+ sg.textColour = new Color(original1);\r
+ sg.textColour2 = new Color(original2);\r
+ sg.thresholdTextColour = originalThreshold;\r
+ }\r
+ }\r
+ }\r
+\r
+ void colour1Changed(Color col)\r
+ {\r
+ if (sg == null)\r
+ {\r
+ ap.av.textColour = col;\r
+ if (ap.av.colourAppliesToAllGroups)\r
+ {\r
+ setGroupTextColour();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ sg.textColour = col;\r
+ }\r
+\r
+ ap.repaint();\r
+ }\r
+\r
+ void colour2Changed(Color col)\r
+ {\r
+ if (sg == null)\r
+ {\r
+ ap.av.textColour2 = col;\r
+ if (ap.av.colourAppliesToAllGroups)\r
+ {\r
+ setGroupTextColour();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ sg.textColour2 = col;\r
+ }\r
+\r
+ ap.repaint();\r
+ }\r
+\r
+ void thresholdChanged(int value)\r
+ {\r
+ if (sg == null)\r
+ {\r
+ ap.av.thresholdTextColour = value;\r
+ if (ap.av.colourAppliesToAllGroups)\r
+ {\r
+ setGroupTextColour();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ sg.thresholdTextColour = value;\r
+ }\r
+\r
+ ap.repaint();\r
+ }\r
+\r
+ void setGroupTextColour()\r
+ {\r
+ if (ap.av.alignment.getGroups() == null)\r
+ {\r
+ return;\r
+ }\r
+\r
+ Vector groups = ap.av.alignment.getGroups();\r
+\r
+ for (int i = 0; i < groups.size(); i++)\r
+ {\r
+ SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
+ sg.textColour = ap.av.textColour;\r
+ sg.textColour2 = ap.av.textColour2;\r
+ sg.thresholdTextColour = ap.av.thresholdTextColour;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package jalview.gui;
+
+import java.io.*;
+import java.net.*;
+
+import javax.swing.*;
+
+public class UserQuestionnaireCheck
+ implements Runnable
+{
+ /**
+ * Implements the client side machinery for detecting a new questionnaire,
+ * checking if the user has responded to an existing one,
+ * and prompting the user for responding to a questionnaire.
+ * This is intended to work with the perl CGI scripts checkresponder.pl and
+ * questionnaire.pl
+ */
+ String url = null;
+ UserQuestionnaireCheck(String url)
+ {
+ if (url.indexOf("questionnaire.pl") == -1)
+ {
+ jalview.bin.Cache.log.error("'" + url +
+ "' is an Invalid URL for the checkForQuestionnaire() method.\n"
+ + "This argument is only for questionnaires derived from jalview's questionnaire.pl cgi interface.");
+ }
+ else
+ {
+ this.url = url;
+ }
+ }
+
+ String qid = null, rid = null;
+ private boolean checkresponse(URL qurl)
+ throws Exception
+ {
+ jalview.bin.Cache.log.debug("Checking Response for : " + qurl);
+ boolean prompt = false;
+ // see if we have already responsed to this questionnaire or get a new qid/rid pair
+ BufferedReader br = new BufferedReader(new InputStreamReader(qurl.
+ openStream()));
+ String qresp;
+ while ( (qresp = br.readLine()) != null)
+ {
+ if (qresp.indexOf("NOTYET:") == 0)
+ {
+ prompt = true; // not yet responded under that ID
+ }
+ else
+ {
+ if (qresp.indexOf("QUESTIONNAIRE:") == 0)
+ {
+ // QUESTIONNAIRE:qid:rid for the latest questionnaire.
+ int p = qresp.indexOf(':', 14);
+ if (p > -1)
+ {
+ rid = null;
+ qid = qresp.substring(14, p);
+ if (p < (qresp.length() - 1))
+ {
+ rid = qresp.substring(p + 1);
+ prompt = true; // this is a new qid/rid pair
+ }
+ }
+ }
+ }
+ }
+ return prompt;
+ }
+
+ public void run()
+ {
+ if (url == null)
+ {
+ return;
+ }
+ boolean prompt = false;
+ try
+ {
+ // First - check to see if wee have an old questionnaire/response id pair.
+ String lastq = jalview.bin.Cache.getProperty("QUESTIONNAIRE");
+ if (lastq == null)
+ {
+ prompt = checkresponse(new URL(url + (url.indexOf('?') > -1 ? "&" : "?") +
+ "checkresponse=1"));
+ }
+ else
+ {
+ String qurl = url + (url.indexOf('?') > -1 ? "&" : "?") +
+ "checkresponse=1";
+ // query the server with the old qid/id pair
+ String qqid = lastq.indexOf(':') > -1 ?
+ lastq.substring(0, lastq.indexOf(':')) : null;
+ if (qqid != null && qqid != "null" && qqid.length() > 0)
+ {
+ qurl += "&qid=" + qqid;
+ qid = qqid;
+ String qrid = lastq.substring(lastq.indexOf(':') + 1); // retrieve old rid
+ if (qrid != null && !qrid.equals("null"))
+ {
+ rid = qrid;
+ qurl += "&rid=" + qrid;
+ }
+ }
+ // see if we have already responsed to this questionnaire.
+ prompt = checkresponse(new URL(qurl));
+ }
+ if (qid != null && rid != null)
+ {
+ // Update our local property cache with latest qid and rid
+ jalview.bin.Cache.setProperty("QUESTIONNAIRE", qid + ":" + rid);
+ }
+ if (prompt)
+ {
+ String qurl = url + (url.indexOf('?') > -1 ? "&" : "?") + "qid=" + qid +
+ "&rid=" + rid;
+ jalview.bin.Cache.log.info("Prompting user for questionnaire at " +
+ qurl);
+ int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
+ "There is a new Questionnaire available." +
+ "Would you like to complete it now ?\n",
+ "Jalview User Survey",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE);
+
+ if (reply == JOptionPane.YES_OPTION)
+ {
+ jalview.bin.Cache.log.debug("Opening " + qurl);
+ jalview.util.BrowserLauncher.openURL(qurl);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ jalview.bin.Cache.log.warn("When trying to access questionnaire URL " +
+ url, e);
+ }
+ }
+
+}
--- /dev/null
+/**
+ *
+ */
+package jalview.gui;
+
+import java.io.File;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Vector;
+import java.util.jar.JarOutputStream;
+
+import javax.swing.JInternalFrame;
+
+import jalview.bin.Cache;
+import jalview.io.VamsasDatastore;
+
+import org.vamsas.client.UserHandle;
+import org.vamsas.client.simpleclient.FileWatcher;
+import org.vamsas.client.simpleclient.VamsasArchive;
+import org.vamsas.client.simpleclient.VamsasFile;
+import org.vamsas.objects.core.Entry;
+import org.vamsas.objects.core.VamsasDocument;
+import org.vamsas.test.simpleclient.ArchiveClient;
+import org.vamsas.test.simpleclient.ClientDoc;
+
+/**
+ * @author jimp
+ *
+ */
+public class VamsasClient
+ extends ArchiveClient
+{
+ // Cache.preferences for vamsas client session arena
+ // preferences for check for default session at startup.
+ // user and organisation stuff.
+ public VamsasClient(Desktop jdesktop,
+ File sessionPath)
+ {
+ super(System.getProperty("user.name"), System.getProperty("host.name"),
+ "jalview", "2.7",
+ sessionPath);
+ }
+
+ public void initial_update()
+ {
+ Cache.log.info("Jalview loading the Vamsas Session.");
+ // load in the vamsas archive for the first time
+ ClientDoc cdoc = this.getUpdateable();
+ updateJalview(cdoc);
+ JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+ if (frames == null)
+ {
+ return;
+ }
+
+ try
+ {
+ //REVERSE ORDER
+ for (int i = frames.length - 1; i > -1; i--)
+ {
+ if (frames[i] instanceof AlignFrame)
+ {
+ AlignFrame af = (AlignFrame) frames[i];
+ af.alignPanel.alignmentChanged();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Cache.log.warn(
+ "Exception whilst refreshing jalview windows after a vamsas document update.",
+ e);
+ }
+ doUpdate(cdoc);
+ cdoc.closeDoc();
+ }
+
+ /**
+ * this will close all windows currently in Jalview.
+ *
+
+ protected void closeWindows() {
+ JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+ if (frames == null)
+ {
+ return;
+ }
+
+ try
+ {
+ for (int i = frames.length - 1; i > -1; i--) {
+ frames[i].dispose();
+ }
+ } catch (Exception e) {
+ Cache.log.error("Whilst closing windows",e);
+ }
+
+ }
+
+ public void get_update(VamsasArchive doc) {
+ // Close windows - load update.
+ Cache.log.info("Jalview updating from Vamsas Session.");
+ }
+ */
+ VamsasClientWatcher watcher = null;
+ public void push_update()
+ {
+ watchForChange = false;
+ try
+ {
+ Thread.sleep(WATCH_SLEEP);
+ }
+ catch (Exception e)
+ {
+
+ }
+ ;
+ ClientDoc cdoc = getUpdateable();
+ updateVamsasDocument(cdoc);
+ doUpdate(cdoc);
+ cdoc.closeDoc();
+ cdoc = null;
+ watchForChange = true;
+ if (watcher != null)
+ {
+ watcher.start();
+ }
+ // collect all uncached alignments and put them into the vamsas dataset.
+ // store them.
+ Cache.log.info("Jalview updating the Vamsas Session.");
+ }
+
+ public void end_session()
+ {
+ // stop any update/watcher thread.
+ watchForChange = false; // this makes any watch(long) loops return.
+ // we should also wait arount for this.WATCH_SLEEP to really make sure the watcher thread has stopped.
+ try
+ {
+ Thread.sleep(WATCH_SLEEP);
+ }
+ catch (Exception e)
+ {
+
+ }
+ ;
+ Cache.log.info("Jalview disconnecting from the Vamsas Session.");
+ }
+
+ public void updateJalview(ClientDoc cdoc)
+ {
+ ensureJvVamsas();
+ VamsasDatastore vds = new VamsasDatastore(cdoc, vobj2jv, jv2vobj,
+ baseProvEntry());
+ vds.updateToJalview();
+ }
+
+ private void ensureJvVamsas()
+ {
+ if (jv2vobj == null)
+ {
+ jv2vobj = new IdentityHashMap();
+ vobj2jv = new Hashtable();
+ }
+ }
+
+ /**
+ * jalview object binding to VorbaIds
+ */
+ IdentityHashMap jv2vobj = null;
+ Hashtable vobj2jv = null;
+ public void updateVamsasDocument(ClientDoc doc)
+ {
+ ensureJvVamsas();
+ VamsasDatastore vds = new VamsasDatastore(doc, vobj2jv, jv2vobj,
+ baseProvEntry());
+ // wander through frames
+ JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+ if (frames == null)
+ {
+ return;
+ }
+
+ try
+ {
+ //REVERSE ORDER
+ for (int i = frames.length - 1; i > -1; i--)
+ {
+ if (frames[i] instanceof AlignFrame)
+ {
+ AlignFrame af = (AlignFrame) frames[i];
+
+ // update alignment and root from frame.
+ vds.storeVAMSAS(af.getViewport(), af.getTitle());
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Cache.log.error("Vamsas Document store exception", e);
+ }
+ }
+
+ private Entry baseProvEntry()
+ {
+ org.vamsas.objects.core.Entry pentry = new org.vamsas.objects.core.Entry();
+ pentry.setUser(this.getProvenanceUser());
+ pentry.setApp(this.getClientHandle().getClientName());
+ pentry.setDate(new org.exolab.castor.types.Date(new java.util.Date()));
+ pentry.setAction("created");
+ return pentry;
+ }
+
+ protected class VamsasClientWatcher
+ extends Thread
+ {
+ /* (non-Javadoc)
+ * @see java.lang.Thread#run()
+ */
+ VamsasClient client = null;
+ VamsasClientWatcher(VamsasClient client)
+ {
+ this.client = client;
+ }
+
+ boolean running = false;
+ public void run()
+ {
+ running = true;
+ while (client.watchForChange)
+ {
+ ClientDoc docio = client.watch(0);
+ if (docio != null)
+ {
+ client.disableGui(true);
+ Cache.log.debug("Updating jalview from changed vamsas document.");
+ client.updateJalview(docio);
+ Cache.log.debug("Finished updating from document change.");
+ docio.closeDoc();
+ docio = null;
+ client.disableGui(false);
+ }
+ }
+ running = false;
+
+ }
+
+ }
+
+ public void disableGui(boolean b)
+ {
+ Desktop.instance.setVamsasUpdate(b);
+ }
+
+ public void startWatcher()
+ {
+ if (watcher == null)
+ {
+ watcher = new VamsasClientWatcher(this);
+ }
+ Thread thr = new Thread()
+ {
+ public void run()
+ {
+ watcher.start();
+ }
+ };
+ thr.start();
+ }
+}
--- /dev/null
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ */\r
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+\r
+public class AMSAFile\r
+ extends jalview.io.FastaFile\r
+{\r
+\r
+ AlignmentI al;\r
+ /**\r
+ * Creates a new AMSAFile object for output.\r
+ */\r
+ public AMSAFile(AlignmentI al)\r
+ {\r
+ this.al = al;\r
+ }\r
+\r
+ /**\r
+ * DOCUMENT ME!\r
+ *\r
+ * @return DOCUMENT ME!\r
+ */\r
+ public String print()\r
+ {\r
+ super.print(getSeqsAsArray());\r
+\r
+ AlignmentAnnotation aa;\r
+ if (al.getAlignmentAnnotation() != null)\r
+ {\r
+ for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
+ {\r
+ aa = al.getAlignmentAnnotation()[i];\r
+ if (aa.autoCalculated || !aa.visible)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ out.append(">#_" + aa.label);\r
+ if (aa.description != null)\r
+ {\r
+ out.append(" " + aa.description);\r
+ }\r
+\r
+ out.append("\n");\r
+\r
+ int nochunks = (aa.annotations.length / len) + 1;\r
+\r
+ for (int j = 0; j < nochunks; j++)\r
+ {\r
+ int start = j * len;\r
+ int end = start + len;\r
+ if (end > aa.annotations.length)\r
+ {\r
+ end = aa.annotations.length;\r
+ }\r
+\r
+ String ch;\r
+ for (int k = start; k < end; k++)\r
+ {\r
+ if (aa.annotations[k] == null)\r
+ {\r
+ ch = " ";\r
+ }\r
+ else\r
+ {\r
+ ch = aa.annotations[k].displayCharacter;\r
+ }\r
+\r
+ out.append(ch);\r
+\r
+ }\r
+ out.append("\n");\r
+ }\r
+ }\r
+ }\r
+ return out.toString();\r
+ }\r
+}\r
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer
+ * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package jalview.io;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
+import jalview.gui.Desktop;
+import jalview.gui.TreePanel;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Vector;
+
+import org.vamsas.client.Vobject;
+import org.vamsas.client.VorbaId;
+import org.vamsas.objects.core.Alignment;
+import org.vamsas.objects.core.AlignmentSequence;
+import org.vamsas.objects.core.AlignmentSequenceAnnotation;
+import org.vamsas.objects.core.AnnotationElement;
+import org.vamsas.objects.core.DataSet;
+import org.vamsas.objects.core.DataSetAnnotations;
+import org.vamsas.objects.core.DbRef;
+import org.vamsas.objects.core.Entry;
+import org.vamsas.objects.core.Glyph;
+import org.vamsas.objects.core.Input;
+import org.vamsas.objects.core.Link;
+import org.vamsas.objects.core.Newick;
+import org.vamsas.objects.core.Param;
+import org.vamsas.objects.core.Property;
+import org.vamsas.objects.core.Provenance;
+import org.vamsas.objects.core.RangeAnnotation;
+import org.vamsas.objects.core.RangeType;
+import org.vamsas.objects.core.Seg;
+import org.vamsas.objects.core.Sequence;
+import org.vamsas.objects.core.Tree;
+import org.vamsas.objects.core.VAMSAS;
+import org.vamsas.test.simpleclient.ClientDoc;
+
+/*
+ *
+ * static {
+ * org.exolab.castor.util.LocalConfiguration.getInstance().getProperties().setProperty(
+ * "org.exolab.castor.serializer", "org.apache.xml.serialize.XMLSerilazizer"); }
+ *
+ */
+
+public class VamsasDatastore
+{
+ Entry provEntry = null;
+
+ // AlignViewport av;
+
+ org.exolab.castor.types.Date date = new org.exolab.castor.types.Date(
+ new java.util.Date());
+
+ ClientDoc cdoc;
+
+ Hashtable vobj2jv;
+
+ IdentityHashMap jv2vobj;
+
+ public VamsasDatastore(ClientDoc cdoc, Hashtable vobj2jv,
+ IdentityHashMap jv2vobj, Entry provEntry)
+ {
+ this.cdoc = cdoc;
+ this.vobj2jv = vobj2jv;
+ this.jv2vobj = jv2vobj;
+ this.provEntry = provEntry;
+ }
+
+ /*
+ * public void storeJalview(String file, AlignFrame af) { try { // 1. Load the
+ * mapping information from the file Mapping map = new
+ * Mapping(getClass().getClassLoader()); java.net.URL url =
+ * getClass().getResource("/jalview_mapping.xml"); map.loadMapping(url); // 2.
+ * Unmarshal the data // Unmarshaller unmar = new Unmarshaller();
+ * //unmar.setIgnoreExtraElements(true); //unmar.setMapping(map); // uni =
+ * (UniprotFile) unmar.unmarshal(new FileReader(file)); // 3. marshal the data
+ * with the total price back and print the XML in the console Marshaller
+ * marshaller = new Marshaller( new FileWriter(file) );
+ *
+ * marshaller.setMapping(map); marshaller.marshal(af); } catch (Exception e) {
+ * e.printStackTrace(); } }
+ *
+ *
+ */
+ /**
+ * @return the Vobject bound to Jalview datamodel object
+ */
+ protected Vobject getjv2vObj(Object jvobj)
+ {
+ if (jv2vobj.containsKey(jvobj))
+ {
+ return cdoc.getObject( (VorbaId) jv2vobj.get(jvobj));
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @param vobj
+ * @return Jalview datamodel object bound to the vamsas document object
+ */
+ protected Object getvObj2jv(org.vamsas.client.Vobject vobj)
+ {
+ VorbaId id = vobj.getVorbaId();
+ if (id == null)
+ {
+ id = cdoc.registerObject(vobj);
+ Cache.log
+ .debug("Registering new object and returning null for getvObj2jv");
+ return null;
+ }
+ if (vobj2jv.containsKey(vobj.getVorbaId()))
+ {
+ return vobj2jv.get(vobj.getVorbaId());
+ }
+ return null;
+ }
+
+ protected void bindjvvobj(Object jvobj, org.vamsas.client.Vobject vobj)
+ {
+ VorbaId id = vobj.getVorbaId();
+ if (id == null)
+ {
+ id = cdoc.registerObject(vobj);
+ if (id == null || vobj.getVorbaId() == null)
+ {
+ Cache.log.error("Failed to get id for " +
+ (vobj.isRegisterable() ? "registerable" :
+ "unregisterable") + " object " + vobj);
+ }
+ }
+
+ if (vobj2jv.containsKey(vobj.getVorbaId()) &&
+ ! ( (VorbaId) vobj2jv.get(vobj.getVorbaId())).equals(jvobj))
+ {
+ Cache.log.debug("Warning? Overwriting existing vamsas id binding for " +
+ vobj.getVorbaId(),
+ new Exception("Overwriting vamsas id binding."));
+ }
+ else if (jv2vobj.containsKey(jvobj) &&
+ ! ( (VorbaId) jv2vobj.get(jvobj)).equals(vobj.getVorbaId()))
+ {
+ Cache.log.debug(
+ "Warning? Overwriting existing jalview object binding for " + jvobj,
+ new Exception("Overwriting jalview object binding."));
+ }
+ /* Cache.log.error("Attempt to make conflicting object binding! "+vobj+" id " +vobj.getVorbaId()+" already bound to "+getvObj2jv(vobj)+" and "+jvobj+" already bound to "+getjv2vObj(jvobj),new Exception("Excessive call to bindjvvobj"));
+ }*/
+ // we just update the hash's regardless!
+ vobj2jv.put(vobj.getVorbaId(), jvobj);
+ // JBPNote - better implementing a hybrid invertible hash.
+ jv2vobj.put(jvobj, vobj.getVorbaId());
+ }
+
+ /**
+ * put the alignment viewed by AlignViewport into cdoc.
+ *
+ * @param av alignViewport to be stored
+ * @param aFtitle title for alignment
+ */
+ public void storeVAMSAS(AlignViewport av, String aFtitle)
+ {
+ try
+ {
+ jalview.datamodel.AlignmentI jal = av.getAlignment();
+ boolean nw = false;
+ VAMSAS root = null; // will be resolved based on Dataset Parent.
+ // /////////////////////////////////////////
+ // SAVE THE DATASET
+ if (jal.getDataset() == null)
+ {
+ Cache.log.warn("Creating new dataset for an alignment.");
+ jal.setDataset(null);
+ }
+ DataSet dataset = (DataSet) getjv2vObj(jal.getDataset());
+ if (dataset == null)
+ {
+ root = cdoc.getVamsasRoots()[0]; // default vamsas root for modifying.
+ dataset = new DataSet();
+ root.addDataSet(dataset);
+ bindjvvobj(jal.getDataset(), dataset);
+ dataset.setProvenance(dummyProvenance());
+ dataset.getProvenance().addEntry(provEntry);
+ nw = true;
+ }
+ else
+ {
+ root = (VAMSAS) dataset.getV_parent();
+ }
+ // update dataset
+ Sequence sequence;
+ DbRef dbref;
+ // set new dataset and alignment sequences based on alignment Nucleotide
+ // flag.
+ // this *will* break when alignment contains both nucleotide and amino
+ // acid sequences.
+ String dict = jal.isNucleotide() ?
+ org.vamsas.objects.utils.SymbolDictionary.STANDARD_NA
+ : org.vamsas.objects.utils.SymbolDictionary.STANDARD_AA;
+ for (int i = 0; i < jal.getHeight(); i++)
+ {
+ SequenceI sq = jal.getSequenceAt(i).getDatasetSequence(); // only insert
+ // referenced
+ // sequences
+ // to dataset.
+ sequence = (Sequence) getjv2vObj(sq);
+ if (sequence == null)
+ {
+ sequence = new Sequence();
+ bindjvvobj(sq, sequence);
+ sq.setVamsasId(sequence.getVorbaId().getId());
+ sequence.setSequence(sq.getSequenceAsString());
+ sequence.setDictionary(dict);
+ sequence.setName(jal.getDataset().getSequenceAt(i).getName());
+ sequence.setStart(jal.getDataset().getSequenceAt(i).getStart());
+ sequence.setEnd(jal.getDataset().getSequenceAt(i).getEnd());
+ dataset.addSequence(sequence);
+ }
+ else
+ {
+ // verify principal attributes. and update any new
+ // features/references.
+ System.out.println("update dataset sequence object.");
+ }
+ if (sq.getSequenceFeatures() != null)
+ {
+ int sfSize = sq.getSequenceFeatures().length;
+
+ for (int sf = 0; sf < sfSize; sf++)
+ {
+ jalview.datamodel.SequenceFeature feature = (jalview.datamodel.
+ SequenceFeature) sq
+ .getSequenceFeatures()[sf];
+
+ DataSetAnnotations dsa = (DataSetAnnotations) getjv2vObj(feature);
+ if (dsa == null)
+ {
+ dsa = (DataSetAnnotations) getDSAnnotationFromJalview(
+ new DataSetAnnotations(), feature);
+ if (dsa.getProvenance() == null)
+ {
+ dsa.setProvenance(new Provenance());
+ }
+ addProvenance(dsa.getProvenance(), "created"); // JBPNote - need
+ // to update
+ dsa.setSeqRef(sequence);
+ bindjvvobj(feature, dsa);
+ dataset.addDataSetAnnotations(dsa);
+ }
+ else
+ {
+ // todo: verify and update dataset annotations for sequence
+ System.out.println("update dataset sequence annotations.");
+ }
+ }
+ }
+
+ if (sq.getDBRef() != null)
+ {
+ DBRefEntry[] entries = sq.getDBRef();
+ jalview.datamodel.DBRefEntry dbentry;
+ for (int db = 0; db < entries.length; db++)
+ {
+ dbentry = entries[db];
+ dbref = (DbRef) getjv2vObj(dbentry);
+ if (dbref == null)
+ {
+ dbref = new DbRef();
+ bindjvvobj(dbentry, dbref);
+ dbref.setAccessionId(dbentry.getAccessionId());
+ dbref.setSource(dbentry.getSource());
+ dbref.setVersion(dbentry.getVersion());
+ /*
+ * TODO: Maps are not yet supported by Jalview. Map vMap = new
+ * Map(); vMap.set dbref.addMap(vMap);
+ */
+ sequence.addDbRef(dbref);
+ }
+ else
+ {
+ // TODO: verify and update dbrefs in vamsas document
+ // there will be trouble when a dataset sequence is modified to
+ // contain more residues than were originally referenced - we must
+ // then make a number of dataset sequence entries
+ System.out
+ .println("update dataset sequence database references.");
+ }
+ }
+
+ }
+ }
+ // dataset.setProvenance(getVamsasProvenance(jal.getDataset().getProvenance()));
+ // ////////////////////////////////////////////
+
+ // ////////////////////////////////////////////
+ // Save the Alignments
+
+ Alignment alignment = (Alignment) getjv2vObj(av); // this is so we can get the alignviewport back
+ if (alignment == null)
+ {
+ alignment = new Alignment();
+ bindjvvobj(av, alignment);
+ if (alignment.getProvenance() == null)
+ {
+ alignment.setProvenance(new Provenance());
+ }
+ addProvenance(alignment.getProvenance(), "added"); // TODO: insert some
+ // sensible source
+ // here
+ dataset.addAlignment(alignment);
+ {
+ Property title = new Property();
+ title.setName("jalview:AlTitle");
+ title.setType("string");
+ title.setContent(aFtitle);
+ alignment.addProperty(title);
+ }
+ alignment.setGapChar(String.valueOf(av.getGapCharacter()));
+ AlignmentSequence alseq = null;
+ for (int i = 0; i < jal.getHeight(); i++)
+ {
+ alseq = new AlignmentSequence();
+ // TODO: VAMSAS: translate lowercase symbols to annotation ?
+ alseq.setSequence(jal.getSequenceAt(i).getSequenceAsString());
+ alseq.setName(jal.getSequenceAt(i).getName());
+ alseq.setStart(jal.getSequenceAt(i).getStart());
+ alseq.setEnd(jal.getSequenceAt(i).getEnd());
+ alseq.setRefid(getjv2vObj(jal.getSequenceAt(i).getDatasetSequence()));
+ alignment.addAlignmentSequence(alseq);
+ bindjvvobj(jal.getSequenceAt(i), alseq);
+ }
+ }
+ else
+ {
+ // todo: verify and update mutable alignment props.
+ if (alignment.getModifiable())
+ {
+ System.out.println("update alignment in document.");
+ }
+ else
+ {
+ System.out
+ .println("update edited alignment to new alignment in document.");
+ }
+ }
+ // ////////////////////////////////////////////
+ // SAVE Alignment Sequence Features
+ for (int i = 0, iSize = alignment.getAlignmentSequenceCount(); i < iSize;
+ i++)
+ {
+ AlignmentSequence valseq;
+ SequenceI alseq = (SequenceI) getvObj2jv(valseq = alignment
+ .getAlignmentSequence(i));
+ if (alseq != null && alseq.getSequenceFeatures() != null)
+ {
+ jalview.datamodel.SequenceFeature[] features = alseq
+ .getSequenceFeatures();
+ for (int f = 0; f < features.length; f++)
+ {
+ if (features[f] != null)
+ {
+ AlignmentSequenceAnnotation valseqf = (
+ AlignmentSequenceAnnotation) getjv2vObj(features[i]);
+ if (valseqf == null)
+ {
+
+ valseqf = (AlignmentSequenceAnnotation)
+ getDSAnnotationFromJalview(
+ new AlignmentSequenceAnnotation(), features[i]);
+ if (valseqf.getProvenance() == null)
+ {
+ valseqf.setProvenance(new Provenance());
+ }
+ addProvenance(valseqf.getProvenance(), "created"); // JBPNote -
+ // need to
+ // update
+ bindjvvobj(features[i], valseqf);
+ valseq.addAlignmentSequenceAnnotation(valseqf);
+ }
+ }
+
+ }
+ }
+ }
+
+ // ////////////////////////////////////////////
+ // SAVE ANNOTATIONS
+ if (jal.getAlignmentAnnotation() != null)
+ {
+ jalview.datamodel.AlignmentAnnotation[] aa = jal
+ .getAlignmentAnnotation();
+ java.util.HashMap AlSeqMaps = new HashMap(); // stores int maps from
+ // alignment columns to
+ // sequence positions.
+ for (int i = 0; i < aa.length; i++)
+ {
+ if (aa[i] == null || isJalviewOnly(aa[i]))
+ {
+ continue;
+ }
+ if (aa[i].sequenceRef != null)
+ {
+ org.vamsas.objects.core.AlignmentSequence alsref = (org.vamsas.
+ objects.core.AlignmentSequence) getjv2vObj(aa[i].sequenceRef);
+ org.vamsas.objects.core.AlignmentSequenceAnnotation an = (org.
+ vamsas.objects.core.AlignmentSequenceAnnotation) getjv2vObj(aa[
+ i]);
+ int[] gapMap = null;
+ if (AlSeqMaps.containsKey(aa[i].sequenceRef))
+ {
+ gapMap = (int[]) AlSeqMaps.get(aa[i].sequenceRef);
+ }
+ else
+ {
+ gapMap = new int[aa[i].sequenceRef.getLength()];
+ // map from alignment position to sequence position.
+ int[] sgapMap = aa[i].sequenceRef.gapMap();
+ for (int a = 0; a < sgapMap.length; a++)
+ {
+ gapMap[sgapMap[a]] = a;
+ }
+ }
+ if (an == null)
+ {
+ an = new org.vamsas.objects.core.AlignmentSequenceAnnotation();
+ Seg vSeg = new Seg();
+ vSeg.setStart(1);
+ vSeg.setInclusive(true);
+ vSeg.setEnd(gapMap.length);
+ an.addSeg(vSeg);
+ an.setType("jalview:SecondaryStructurePrediction"); // TODO: better fix this rough guess ;)
+ alsref.addAlignmentSequenceAnnotation(an);
+ bindjvvobj(aa[i], an);
+ // LATER: much of this is verbatim from the alignmentAnnotation
+ // method below. suggests refactoring to make rangeAnnotation the
+ // base class
+ an.setDescription(aa[i].description);
+ if (aa[i].graph > 0)
+ {
+ an.setGraph(true); // aa[i].graph);
+ }
+ else
+ {
+ an.setGraph(false);
+ }
+ an.setLabel(aa[i].label);
+ an.setProvenance(dummyProvenance()); // get provenance as user
+ // created, or jnet, or
+ // something else.
+ an.setGroup(Integer.toString(aa[i].graphGroup)); // // JBPNote -
+ // originally we
+ // were going to
+ // store
+ // graphGroup in
+ // the Jalview
+ // specific
+ // bits.
+ AnnotationElement ae;
+ for (int a = 0; a < aa[i].annotations.length; a++)
+ {
+ if (aa[i].annotations[a] == null)
+ {
+ continue;
+ }
+
+ ae = new AnnotationElement();
+ ae.setDescription(aa[i].annotations[a].description);
+ ae.addGlyph(new Glyph());
+ ae.getGlyph(0)
+ .setContent(aa[i].annotations[a].displayCharacter); // assume
+ // jax-b
+ // takes
+ // care
+ // of
+ // utf8
+ // translation
+ if (aa[i].graph !=
+ jalview.datamodel.AlignmentAnnotation.NO_GRAPH)
+ {
+ ae.addValue(aa[i].annotations[a].value);
+ }
+ ae.setPosition(gapMap[a] + 1); // position w.r.t. AlignmentSequence
+ // symbols
+ if (aa[i].annotations[a].secondaryStructure != ' ')
+ {
+ // we only write an annotation where it really exists.
+ Glyph ss = new Glyph();
+ ss
+ .setDict(org.vamsas.objects.utils.GlyphDictionary.
+ PROTEIN_SS_3STATE);
+ ss.setContent(String
+ .valueOf(aa[i].annotations[a].
+ secondaryStructure));
+ ae.addGlyph(ss);
+ }
+ an.addAnnotationElement(ae);
+ }
+ }
+ else
+ {
+ // update reference sequence Annotation
+ if (an.getModifiable())
+ {
+ // verify existing alignment sequence annotation is up to date
+ System.out.println("update alignment sequence annotation.");
+ }
+ else
+ {
+ // verify existing alignment sequence annotation is up to date
+ System.out
+ .println(
+ "make new alignment sequence annotation if modification has happened.");
+ }
+ }
+ }
+ else
+ {
+ // add Alignment Annotation
+ org.vamsas.objects.core.AlignmentAnnotation an = (org.vamsas.
+ objects.core.AlignmentAnnotation) getjv2vObj(aa[i]);
+ if (an == null)
+ {
+ an = new org.vamsas.objects.core.AlignmentAnnotation();
+ an.setType("jalview:AnnotationRow");
+ an.setDescription(aa[i].description);
+ alignment.addAlignmentAnnotation(an);
+ Seg vSeg = new Seg();
+ vSeg.setStart(1);
+ vSeg.setInclusive(true);
+ vSeg.setEnd(jal.getWidth());
+ an.addSeg(vSeg);
+ if (aa[i].graph > 0)
+ {
+ an.setGraph(true); // aa[i].graph);
+ }
+ an.setLabel(aa[i].label);
+ an.setProvenance(dummyProvenance());
+ if (aa[i].graph != aa[i].NO_GRAPH)
+ {
+ an.setGroup(Integer.toString(aa[i].graphGroup)); // // JBPNote -
+ // originally we
+ // were going to
+ // store
+ // graphGroup in
+ // the Jalview
+ // specific
+ // bits.
+ an.setGraph(true);
+ }
+ else
+ {
+ an.setGraph(false);
+ }
+ AnnotationElement ae;
+
+ for (int a = 0; a < aa[i].annotations.length; a++)
+ {
+ if ( (aa[i] == null) || (aa[i].annotations[a] == null))
+ {
+ continue;
+ }
+
+ ae = new AnnotationElement();
+ ae.setDescription(aa[i].annotations[a].description);
+ ae.addGlyph(new Glyph());
+ ae.getGlyph(0)
+ .setContent(aa[i].annotations[a].displayCharacter); // assume
+ // jax-b
+ // takes
+ // care
+ // of
+ // utf8
+ // translation
+ ae.addValue(aa[i].annotations[a].value);
+ ae.setPosition(a + 1);
+ if (aa[i].annotations[a].secondaryStructure != ' ')
+ {
+ Glyph ss = new Glyph();
+ ss
+ .setDict(org.vamsas.objects.utils.GlyphDictionary.
+ PROTEIN_SS_3STATE);
+ ss.setContent(String
+ .valueOf(aa[i].annotations[a].
+ secondaryStructure));
+ ae.addGlyph(ss);
+ }
+ an.addAnnotationElement(ae);
+ }
+ if (aa[i].editable)
+ {
+ //an.addProperty(newProperty("jalview:editable", null, "true"));
+ an.setModifiable(true);
+ }
+ if (aa[i].graph != jalview.datamodel.AlignmentAnnotation.NO_GRAPH)
+ {
+ an.setGraph(true);
+ an.setGroup(Integer.toString(aa[i].graphGroup));
+ an.addProperty(newProperty("jalview:graphType", null,
+ ( (aa[i].graph ==
+ jalview.datamodel.AlignmentAnnotation.
+ BAR_GRAPH) ? "BAR_GRAPH" :
+ "LINE_GRAPH")));
+
+ /** and on and on..
+ vProperty=new Property();
+ vProperty.setName("jalview:graphThreshhold");
+ vProperty.setContent(aa[i].threshold);
+ */
+
+ }
+ }
+ else
+ {
+ if (an.getModifiable())
+ {
+ // verify annotation - update (perhaps)
+ Cache.log.info(
+ "update alignment sequence annotation. not yet implemented.");
+ }
+ else
+ {
+ // verify annotation - update (perhaps)
+ Cache.log.info("updated alignment sequence annotation added.");
+ }
+ }
+ }
+ }
+ }
+ // /////////////////////////////////////////////////////
+
+ // //////////////////////////////////////////////
+ // /SAVE THE TREES
+ // /////////////////////////////////
+ // FIND ANY ASSOCIATED TREES
+ if (Desktop.desktop != null)
+ {
+ javax.swing.JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+ for (int t = 0; t < frames.length; t++)
+ {
+ if (frames[t] instanceof TreePanel)
+ {
+ TreePanel tp = (TreePanel) frames[t];
+
+ if (tp.getAlignment() == jal)
+ {
+ Tree tree = (Tree) getjv2vObj(tp);
+ if (tree == null)
+ {
+ tree = new Tree();
+ bindjvvobj(tp, tree);
+ tree.setTitle(tp.getTitle());
+ Newick newick = new Newick();
+ // TODO: translate sequenceI to leaf mappings to vamsas
+ // references - see tree specification in schema.
+ newick.setContent(tp.getTree().toString());
+ newick.setTitle(tp.getTitle());
+ tree.addNewick(newick);
+ tree.setProvenance(makeTreeProvenance(jal, tp));
+ alignment.addTree(tree);
+ }
+ else
+ {
+ if (tree.getModifiable())
+ {
+ // verify any changes.
+ System.out.println("Update tree in document.");
+ }
+ else
+ {
+ System.out
+ .println("Add modified tree as new tree in document.");
+ }
+ }
+ }
+ }
+ }
+ }
+ // Store Jalview specific stuff in the Jalview appData
+ // not implemented in the SimpleDoc interface.
+ }
+
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ private Property newProperty(String name, String type, String content)
+ {
+ Property vProperty = new Property();
+ vProperty.setName(name);
+ if (type != null)
+ {
+ vProperty.setType(type);
+ }
+ else
+ {
+ vProperty.setType("String");
+ }
+ vProperty.setContent(content);
+ return vProperty;
+ }
+
+ /**
+ * correctly create a RangeAnnotation from a jalview sequence feature
+ *
+ * @param dsa
+ * (typically DataSetAnnotations or AlignmentSequenceAnnotation)
+ * @param feature
+ * (the feature to be mapped from)
+ * @return
+ */
+ private RangeAnnotation getDSAnnotationFromJalview(RangeAnnotation dsa,
+ SequenceFeature feature)
+ {
+ dsa.setType(feature.getType());
+ Seg vSeg = new Seg();
+ vSeg.setStart(feature.getBegin());
+ vSeg.setEnd(feature.getEnd());
+ vSeg.setInclusive(true);
+ dsa.addSeg(vSeg);
+ dsa.setDescription(feature.getDescription());
+ dsa.setStatus(feature.getStatus());
+ if (feature.links != null && feature.links.size() > 0)
+ {
+ for (int i = 0, iSize = feature.links.size(); i < iSize; i++)
+ {
+ String link = (String) feature.links.elementAt(i);
+ int sep = link.indexOf('|');
+ if (sep > -1)
+ {
+ Link vLink = new Link();
+ if (sep > 0)
+ {
+ vLink.setContent(link.substring(0, sep - 1));
+ }
+ else
+ {
+ vLink.setContent("");
+ }
+ vLink.setHref(link.substring(sep + 1)); // TODO: validate href.
+ dsa.addLink(vLink);
+ }
+ }
+ }
+ dsa.setGroup(feature.getFeatureGroup());
+ return dsa;
+ }
+
+ /**
+ * correctly creates provenance for trees calculated on an alignment by
+ * jalview.
+ *
+ * @param jal
+ * @param tp
+ * @return
+ */
+ private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp)
+ {
+ Provenance prov = new Provenance();
+ prov.addEntry(new Entry());
+ prov.getEntry(0).setAction("imported " + tp.getTitle());
+ prov.getEntry(0).setUser(provEntry.getUser());
+ prov.getEntry(0).setApp(provEntry.getApp());
+ prov.getEntry(0).setDate(provEntry.getDate());
+ if (tp.getTree().hasOriginalSequenceData())
+ {
+ Input vInput = new Input();
+ // LATER: check to see if tree input data is contained in this alignment -
+ // or just correctly resolve the tree's seqData to the correct alignment in
+ // the document.
+ // vInput.setObjRef(getjv2vObj(jal));
+ vInput.setObjRef(getjv2vObj(tp.getViewPort()));
+ prov.getEntry(0).setAction("created " + tp.getTitle());
+ prov.getEntry(0).addInput(vInput);
+ vInput.setName("jalview:seqdist");
+ prov.getEntry(0).addParam(new Param());
+ prov.getEntry(0).getParam(0).setName("treeType");
+ prov.getEntry(0).getParam(0).setType("utf8");
+ prov.getEntry(0).getParam(0).setContent("NJ");
+
+ int ranges[] = tp.getTree().seqData.getVisibleContigs();
+ // VisibleContigs are with respect to alignment coordinates. Still need offsets
+ int start = tp.getTree().seqData.getAlignmentOrigin();
+ for (int r = 0; r < ranges.length; r += 2)
+ {
+ Seg visSeg = new Seg();
+ visSeg.setStart(1 + start + ranges[r]);
+ visSeg.setEnd(start + ranges[r + 1]);
+ visSeg.setInclusive(true);
+ vInput.addSeg(visSeg);
+ }
+ }
+ return prov;
+ }
+
+ /**
+ *
+ * @param tp
+ * @return Object[] { AlignmentView, AlignmentI - reference alignment for
+ * input }
+ */
+ private Object[] recoverInputData(Provenance tp)
+ {
+ for (int pe = 0; pe < tp.getEntryCount(); pe++)
+ {
+ if (tp.getEntry(pe).getInputCount() > 0)
+ {
+ if (tp.getEntry(pe).getInputCount() > 1)
+ {
+ Cache.log.warn("Ignoring additional input spec in provenance entry "
+ + tp.getEntry(pe).toString());
+ }
+ // LATER: deal sensibly with multiple inputs.
+ Input vInput = tp.getEntry(pe).getInput(0);
+ if (vInput.getObjRef() instanceof org.vamsas.objects.core.Alignment)
+ {
+ // recover an AlignmentView for the input data
+ AlignViewport javport = (AlignViewport) getvObj2jv( (org.vamsas.
+ client.Vobject) vInput
+ .getObjRef());
+ jalview.datamodel.AlignmentI jal = javport.getAlignment();
+ jalview.datamodel.CigarArray view = javport.getAlignment().
+ getCompactAlignment();
+ int from = 1, to = jal.getWidth();
+ int offset = 0; // deleteRange modifies its frame of reference
+ for (int r = 0, s = vInput.getSegCount(); r < s; r++)
+ {
+ Seg visSeg = vInput.getSeg(r);
+ int se[] = getSegRange(visSeg, true); // jalview doesn't do bidirection alignments yet.
+ if (to < se[1])
+ {
+ Cache.log.warn("Ignoring invalid segment in InputData spec.");
+ }
+ else
+ {
+ if (se[0] > from)
+ {
+ view.deleteRange(offset + from - 1, offset + se[0] - 2);
+ offset -= se[0] - from;
+ }
+ from = se[1] + 1;
+ }
+ }
+ if (from < to)
+ {
+ view.deleteRange(offset + from - 1, offset + to - 1); // final deletion - TODO: check off by
+ // one for to
+ }
+ return new Object[]
+ {
+ new AlignmentView(view), jal};
+ }
+ }
+ }
+ Cache.log.debug("Returning null for input data recovery from provenance.");
+ return null;
+ }
+
+ /**
+ * get start<end range of segment, adjusting for inclusivity flag and
+ * polarity.
+ *
+ * @param visSeg
+ * @param ensureDirection when true - always ensure start is less than end.
+ * @return int[] { start, end, direction} where direction==1 for range running from end to start.
+ */
+ private int[] getSegRange(Seg visSeg, boolean ensureDirection)
+ {
+ boolean incl = visSeg.getInclusive();
+ // adjust for inclusive flag.
+ int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of
+ // region.
+ int start = visSeg.getStart() + (incl ? 0 : pol);
+ int end = visSeg.getEnd() + (incl ? 0 : -pol);
+ if (ensureDirection && pol == -1)
+ {
+ // jalview doesn't deal with inverted ranges, yet.
+ int t = end;
+ end = start;
+ start = t;
+ }
+ return new int[]
+ {
+ start, end, pol < 0 ? 1 : 0};
+ }
+
+ /**
+ *
+ * @param annotation
+ * @return true if annotation is not to be stored in document
+ */
+ private boolean isJalviewOnly(AlignmentAnnotation annotation)
+ {
+ return annotation.label.equals("Quality")
+ || annotation.label.equals("Conservation")
+ || annotation.label.equals("Consensus");
+ }
+
+ /**
+ * This will return the first AlignFrame viewing AlignViewport av.
+ * It will break if there are more than one AlignFrames viewing a particular av.
+ * This also shouldn't be in the io package.
+ * @param av
+ * @return alignFrame for av
+ */
+ public AlignFrame getAlignFrameFor(AlignViewport av)
+ {
+ if (Desktop.desktop != null)
+ {
+ javax.swing.JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+ for (int t = 0; t < frames.length; t++)
+ {
+ if (frames[t] instanceof AlignFrame)
+ {
+ if ( ( (AlignFrame) frames[t]).getViewport() == av)
+ {
+ return (AlignFrame) frames[t];
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public void updateToJalview()
+ {
+ VAMSAS _roots[] = cdoc.getVamsasRoots();
+
+ for (int _root = 0; _root < _roots.length; _root++)
+ {
+ VAMSAS root = _roots[_root];
+ boolean newds = false;
+ for (int _ds = 0, _nds = root.getDataSetCount(); _ds < _nds; _ds++)
+ {
+ // ///////////////////////////////////
+ // ///LOAD DATASET
+ DataSet dataset = root.getDataSet(_ds);
+ int i, iSize = dataset.getSequenceCount();
+ Vector dsseqs;
+ jalview.datamodel.Alignment jdataset = (jalview.datamodel.Alignment)
+ getvObj2jv(dataset);
+ int jremain = 0;
+ if (jdataset == null)
+ {
+ Cache.log.debug("Initialising new jalview dataset fields");
+ newds = true;
+ dsseqs = new Vector();
+ }
+ else
+ {
+ Cache.log.debug("Update jalview dataset from vamsas.");
+ jremain = jdataset.getHeight();
+ dsseqs = jdataset.getSequences();
+ }
+
+ // TODO: test sequence merging - we preserve existing non vamsas
+ // sequences but add in any new vamsas ones, and don't yet update any
+ // sequence attributes
+ for (i = 0; i < iSize; i++)
+ {
+ Sequence vdseq = dataset.getSequence(i);
+ jalview.datamodel.SequenceI dsseq = (SequenceI) getvObj2jv(vdseq);
+ if (dsseq != null)
+ {
+ if (!dsseq.getSequence().equals(vdseq.getSequence()))
+ {
+ throw new Error(
+ "Broken! - mismatch of dataset sequence and jalview internal dataset sequence.");
+ }
+ jremain--;
+ }
+ else
+ {
+ dsseq = new jalview.datamodel.Sequence(
+ dataset.getSequence(i).getName(),
+ dataset.getSequence(i).getSequence(),
+ dataset.getSequence(i).getStart(),
+ dataset.getSequence(i).getEnd());
+ dsseq.setDescription(dataset.getSequence(i).getDescription());
+ bindjvvobj(dsseq, dataset.getSequence(i));
+ dsseq.setVamsasId(dataset.getSequence(i).getVorbaId().getId());
+ dsseqs.add(dsseq);
+ }
+ if (vdseq.getDbRefCount() > 0)
+ {
+ DbRef[] dbref = vdseq.getDbRef();
+ for (int db = 0; db < dbref.length; db++)
+ {
+ jalview.datamodel.DBRefEntry dbr = (jalview.datamodel.DBRefEntry)
+ getvObj2jv(dbref[db]);
+ if (dbr == null)
+ {
+ // add new dbref
+ dsseq.addDBRef(dbr = new jalview.datamodel.DBRefEntry
+ (
+ dbref[db].getSource().toString(),
+ dbref[db].getVersion().toString(),
+ dbref[db].getAccessionId().toString()));
+ bindjvvobj(dbr, dbref[db]);
+ }
+ }
+ }
+ }
+
+ if (newds)
+ {
+ SequenceI[] seqs = new SequenceI[dsseqs.size()];
+ for (i = 0, iSize = dsseqs.size(); i < iSize; i++)
+ {
+ seqs[i] = (SequenceI) dsseqs.elementAt(i);
+ dsseqs.setElementAt(null, i);
+ }
+ jdataset = new jalview.datamodel.Alignment(seqs);
+ Cache.log.debug("New vamsas dataset imported into jalview.");
+ bindjvvobj(jdataset, dataset);
+ }
+ // ////////
+ // add any new dataset sequence feature annotations
+ if (dataset.getDataSetAnnotations() != null)
+ {
+ for (int dsa = 0; dsa < dataset.getDataSetAnnotationsCount(); dsa++)
+ {
+ DataSetAnnotations dseta = dataset.getDataSetAnnotations(dsa);
+ SequenceI dsSeq = (SequenceI) getvObj2jv( (Vobject) dseta.getSeqRef());
+ if (dsSeq == null)
+ {
+ jalview.bin.Cache.log.warn(
+ "Couldn't resolve jalview sequenceI for dataset object reference " +
+ ( (Vobject) dataset.getDataSetAnnotations(dsa).getSeqRef()).
+ getVorbaId().getId());
+ }
+ else
+ {
+ if (dseta.getAnnotationElementCount() == 0)
+ {
+ jalview.datamodel.SequenceFeature sf = (jalview.datamodel.
+ SequenceFeature) getvObj2jv(dseta);
+ if (sf == null)
+ {
+ dsSeq.addSequenceFeature(sf = getJalviewSeqFeature(dseta));
+ bindjvvobj(sf, dseta);
+ }
+ }
+ else
+ {
+ // TODO: deal with alignmentAnnotation style annotation
+ // appearing on dataset sequences.
+ // JBPNote: we could just add them to all alignments but
+ // that may complicate cross references in the jalview
+ // datamodel
+ Cache.log.warn("Ignoring dataset annotation with annotationElements. Not yet supported in jalview.");
+ }
+ }
+ }
+ }
+
+ if (dataset.getAlignmentCount() > 0)
+ {
+ // LOAD ALIGNMENTS from DATASET
+
+ for (int al = 0, nal = dataset.getAlignmentCount(); al < nal; al++)
+ {
+ org.vamsas.objects.core.Alignment alignment = dataset.getAlignment(
+ al);
+ AlignViewport av = (AlignViewport) getvObj2jv(alignment);
+ jalview.datamodel.AlignmentI jal = null;
+ if (av != null)
+ {
+ jal = av.getAlignment();
+ }
+ iSize = alignment.getAlignmentSequenceCount();
+ boolean newal = (jal == null) ? true : false;
+ Vector newasAnnots = new Vector();
+ char gapChar = ' '; // default for new alignments read in from the document
+ if (jal != null)
+ {
+ dsseqs = jal.getSequences(); // for merge/update
+ gapChar = jal.getGapCharacter();
+ }
+ else
+ {
+ dsseqs = new Vector();
+ }
+ char valGapchar = alignment.getGapChar().charAt(0);
+ for (i = 0; i < iSize; i++)
+ {
+ AlignmentSequence valseq = alignment.getAlignmentSequence(i);
+ jalview.datamodel.SequenceI alseq = (SequenceI) getvObj2jv(valseq);
+ if (alseq != null)
+ {
+ //TODO: upperCase/LowerCase situation here ? do we allow it ?
+ //if (!alseq.getSequence().equals(valseq.getSequence())) {
+ // throw new Error("Broken! - mismatch of dataset sequence and jalview internal dataset sequence.");
+ if (Cache.log.isDebugEnabled())
+ {
+ Cache.log.debug("Updating apparently edited sequence " +
+ alseq.getName());
+ }
+ // this might go *horribly* wrong
+ alseq.setSequence(new String(valseq.getSequence()).replace(
+ valGapchar, gapChar));
+ jremain--;
+ }
+ else
+ {
+ alseq = new jalview.datamodel.Sequence(
+ valseq.getName(),
+ valseq.getSequence().replace(valGapchar, gapChar),
+ valseq.getStart(),
+ valseq.getEnd());
+
+ Vobject datsetseq = (Vobject) valseq.getRefid();
+ if (datsetseq != null)
+ {
+ alseq.setDatasetSequence( (SequenceI) getvObj2jv(datsetseq)); // exceptions if AlignemntSequence reference isn't a simple SequenceI
+ }
+ else
+ {
+ Cache.log.error(
+ "Invalid dataset sequence id (null) for alignment sequence " +
+ valseq.getVorbaId());
+ }
+ bindjvvobj(alseq, valseq);
+ alseq.setVamsasId(valseq.getVorbaId().getId());
+ dsseqs.add(alseq);
+ }
+ if (valseq.getAlignmentSequenceAnnotationCount() > 0)
+ {
+ AlignmentSequenceAnnotation[] vasannot = valseq.
+ getAlignmentSequenceAnnotation();
+ for (int a = 0; a < vasannot.length; a++)
+ {
+ jalview.datamodel.AlignmentAnnotation asa = (jalview.
+ datamodel.AlignmentAnnotation) getvObj2jv(vasannot[a]); // TODO: 1:many jalview alignment sequence annotations
+ if (asa == null)
+ {
+ int se[] = getBounds(vasannot[a]);
+ asa = getjAlignmentAnnotation(jal, vasannot[a]);
+ asa.sequenceRef = alseq;
+ asa.createSequenceMapping(alseq, alseq.getStart() + se[0], false); // TODO: verify that positions in alseqAnnotation correspond to ungapped residue positions.
+ bindjvvobj(asa, vasannot[a]);
+ newasAnnots.add(asa);
+ }
+ else
+ {
+ // update existing annotation - can do this in place
+ if (vasannot[a].getModifiable())
+ {
+ Cache.log.info(
+ "UNIMPLEMENTED: not recovering user modifiable sequence alignment annotation");
+ // TODO: should at least replace with new one - otherwise things will break
+ // basically do this:
+ // int se[] = getBounds(vasannot[a]);
+ // asa.update(getjAlignmentAnnotation(jal, vasannot[a])); // update from another annotation object in place.
+ // asa.createSequenceMapping(alseq, se[0], false);
+
+ }
+ }
+ }
+ }
+ }
+ if (jal == null)
+ {
+ SequenceI[] seqs = new SequenceI[dsseqs.size()];
+ for (i = 0, iSize = dsseqs.size(); i < iSize; i++)
+ {
+ seqs[i] = (SequenceI) dsseqs.elementAt(i);
+ dsseqs.setElementAt(null, i);
+ }
+ jal = new jalview.datamodel.Alignment(seqs);
+ Cache.log.debug("New vamsas alignment imported into jalview " +
+ alignment.getVorbaId().getId());
+ jal.setDataset(jdataset);
+ }
+ if (newasAnnots != null && newasAnnots.size() > 0)
+ {
+ // Add the new sequence annotations in to the alignment.
+ for (int an = 0, anSize = newasAnnots.size(); an < anSize; an++)
+ {
+ jal.addAnnotation( (AlignmentAnnotation) newasAnnots.elementAt(
+ an));
+ // TODO: check if anything has to be done - like calling adjustForAlignment or something.
+ newasAnnots.setElementAt(null, an);
+ }
+ newasAnnots = null;
+ }
+ // //////////////////////////////////////////
+ // //LOAD ANNOTATIONS FOR THE ALIGNMENT
+ // ////////////////////////////////////
+ if (alignment.getAlignmentAnnotationCount() > 0)
+ {
+ org.vamsas.objects.core.AlignmentAnnotation[] an = alignment.
+ getAlignmentAnnotation();
+
+ for (int j = 0; j < an.length; j++)
+ {
+ jalview.datamodel.AlignmentAnnotation jan = (jalview.datamodel.
+ AlignmentAnnotation) getvObj2jv(an[j]);
+ if (jan != null)
+ {
+ // update or stay the same.
+ // TODO: should at least replace with a new one - otherwise things will break
+ // basically do this:
+ // jan.update(getjAlignmentAnnotation(jal, an[a])); // update from another annotation object in place.
+
+ Cache.log.debug("update from vamsas alignment annotation to existing jalview alignment annotation.");
+ if (an[j].getModifiable())
+ {
+ // TODO: user defined annotation is totally mutable... - so load it up or throw away if locally edited.
+ Cache.log.info(
+ "NOT IMPLEMENTED - Recovering user-modifiable annotation - yet...");
+ }
+ // TODO: compare annotation element rows
+ // TODO: compare props.
+ }
+ else
+ {
+ jan = getjAlignmentAnnotation(jal, an[j]);
+ jal.addAnnotation(jan);
+ bindjvvobj(jan, an[j]);
+ }
+ }
+ }
+ AlignFrame alignFrame;
+ if (av == null)
+ {
+ Cache.log.debug("New alignframe for alignment " +
+ alignment.getVorbaId());
+ // ///////////////////////////////
+ // construct alignment view
+ alignFrame = new AlignFrame(jal, AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+ av = alignFrame.getViewport();
+ String title = alignment.getProvenance().getEntry(alignment.
+ getProvenance().getEntryCount() - 1).getAction();
+ if (alignment.getPropertyCount() > 0)
+ {
+ for (int p = 0, pe = alignment.getPropertyCount(); p < pe; p++)
+ {
+ if (alignment.getProperty(p).getName().equals(
+ "jalview:AlTitle"))
+ {
+ title = alignment.getProperty(p).getContent();
+ }
+ }
+ }
+ // TODO: automatically create meaningful title for a vamsas alignment using its provenance.
+ jalview.gui.Desktop.addInternalFrame(alignFrame,
+ title + "(" + alignment.getVorbaId() + ")",
+ AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+ bindjvvobj(av, alignment);
+ }
+ else
+ {
+ // find the alignFrame for jal.
+ // TODO: fix this so we retrieve the alignFrame handing av *directly*
+ alignFrame = getAlignFrameFor(av);
+ }
+ // LOAD TREES
+ // /////////////////////////////////////
+ if (alignment.getTreeCount() > 0)
+ {
+
+ for (int t = 0; t < alignment.getTreeCount(); t++)
+ {
+ Tree tree = alignment.getTree(t);
+ TreePanel tp = (TreePanel) getvObj2jv(tree);
+ if (tp != null)
+ {
+ Cache.log.info(
+ "Update from vamsas document to alignment associated tree not implemented yet.");
+ }
+ else
+ {
+ // make a new tree
+ Object[] idata = this.recoverInputData(tree.getProvenance());
+ try
+ {
+ AlignmentView inputData = null;
+ if (idata != null && idata[0] != null)
+ {
+ inputData = (AlignmentView) idata[0];
+ }
+ tp = alignFrame.ShowNewickTree(
+ new jalview.io.NewickFile(tree.getNewick(0).getContent()),
+ tree.getNewick(0).getTitle() + " (" + tree.getVorbaId() +
+ ")", inputData,
+ 600, 500,
+ t * 20 + 50, t * 20 + 50);
+ bindjvvobj(tp, tree);
+ }
+ catch (Exception e)
+ {
+ Cache.log.warn("Problems parsing treefile '" +
+ tree.getNewick(0).getContent() + "'", e);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ // bitfields - should be a template in j1.5
+ private static int HASSECSTR = 0;
+ private static int HASVALS = 1;
+ private static int HASHPHOB = 2;
+ private static int HASDC = 3;
+ private static int HASDESCSTR = 4;
+ private static int HASTWOSTATE = 5; // not used yet.
+ /**
+ * parses the AnnotationElements - if they exist - into jalview.datamodel.Annotation[] rows
+ * Two annotation rows are made if there are distinct annotation for both at 'pos' and 'after pos' at any particular site.
+ * @param annotation
+ * @return { boolean[static int constants ], int[ae.length] - map to annotated object frame, jalview.datamodel.Annotation[], jalview.datamodel.Annotation[] (after)}
+ */
+ private Object[] parseRangeAnnotation(org.vamsas.objects.core.RangeAnnotation
+ annotation)
+ {
+ // set these attributes by looking in the annotation to decide what kind of alignment annotation rows will be made
+ // TODO: potentially we might make several annotation rows from one vamsas alignment annotation. the jv2Vobj binding mechanism
+ // may not quite cope with this (without binding an array of annotations to a vamsas alignment annotation)
+ // summary flags saying what we found over the set of annotation rows.
+ boolean[] AeContent = new boolean[]
+ {
+ false, false, false, false, false};
+ int[] rangeMap = getMapping(annotation);
+ jalview.datamodel.Annotation[][] anot = new jalview.datamodel.Annotation[][]
+ {
+ new jalview.datamodel.Annotation[rangeMap.length],
+ new jalview.datamodel.Annotation[rangeMap.length]
+ };
+ boolean mergeable = true; //false if 'after positions cant be placed on same annotation row as positions.
+
+ if (annotation.getAnnotationElementCount() > 0)
+ {
+ AnnotationElement ae[] = annotation.getAnnotationElement();
+ for (int aa = 0; aa < ae.length; aa++)
+ {
+ int pos = ae[aa].getPosition() - 1; // pos counts from 1 to (|seg.start-seg.end|+1)
+ if (pos >= 0 && pos < rangeMap.length)
+ {
+ int row = ae[aa].getAfter() ? 1 : 0;
+ if (anot[row][pos] != null)
+ {
+ // only time this should happen is if the After flag is set.
+ Cache.log.debug("Ignoring duplicate annotation site at " + pos);
+ continue;
+ }
+ if (anot[1 - row][pos] != null)
+ {
+ mergeable = false;
+ }
+ String desc = "";
+ if (ae[aa].getDescription() != null)
+ {
+ desc = ae[aa].getDescription();
+ if (desc.length() > 0)
+ {
+ // have imported valid description string
+ AeContent[HASDESCSTR] = true;
+ }
+ }
+ String dc = null; //ae[aa].getDisplayCharacter()==null ? "dc" : ae[aa].getDisplayCharacter();
+ String ss = null; //ae[aa].getSecondaryStructure()==null ? "ss" : ae[aa].getSecondaryStructure();
+ java.awt.Color colour = null;
+ if (ae[aa].getGlyphCount() > 0)
+ {
+ Glyph[] glyphs = ae[aa].getGlyph();
+ for (int g = 0; g < glyphs.length; g++)
+ {
+ if (glyphs[g].getDict().equals(org.vamsas.objects.utils.
+ GlyphDictionary.PROTEIN_SS_3STATE))
+ {
+ ss = glyphs[g].getContent();
+ AeContent[HASSECSTR] = true;
+ }
+ else if (glyphs[g].getDict().equals(org.vamsas.objects.utils.
+ GlyphDictionary.
+ PROTEIN_HD_HYDRO))
+ {
+ Cache.log.debug("ignoring hydrophobicity glyph marker.");
+ AeContent[HASHPHOB] = true;
+ char c = (dc = glyphs[g].getContent()).charAt(0);
+ // dc may get overwritten - but we still set the colour.
+ colour = new java.awt.Color(c == '+' ? 255 : 0,
+ c == '.' ? 255 : 0,
+ c == '-' ? 255 : 0);
+
+ }
+ else if (glyphs[g].getDict().equals(org.vamsas.objects.utils.
+ GlyphDictionary.DEFAULT))
+ {
+ dc = glyphs[g].getContent();
+ AeContent[HASDC] = true;
+ }
+ else
+ {
+ Cache.log.debug("Ignoring unknown glyph type " +
+ glyphs[g].getDict());
+ }
+ }
+ }
+ float val = 0;
+ if (ae[aa].getValueCount() > 0)
+ {
+ AeContent[HASVALS] = true;
+ if (ae[aa].getValueCount() > 1)
+ {
+ Cache.log.warn("ignoring additional " +
+ (ae[aa].getValueCount() - 1) +
+ "values in annotation element.");
+ }
+ val = ae[aa].getValue(0);
+ }
+ if (colour == null)
+ {
+ anot[row][pos] = new jalview.datamodel.Annotation( (dc != null) ?
+ dc : "", desc, (ss != null) ? ss.charAt(0) : ' ', val);
+ }
+ else
+ {
+ anot[row][pos] = new jalview.datamodel.Annotation( (dc != null) ?
+ dc : "", desc, (ss != null) ? ss.charAt(0) : ' ', val, colour);
+ }
+ }
+ else
+ {
+ Cache.log.warn("Ignoring out of bound annotation element " + aa +
+ " in " + annotation.getVorbaId().getId());
+ }
+ }
+ // decide on how many annotation rows are needed.
+ if (mergeable)
+ {
+ for (int i = 0; i < anot[0].length; i++)
+ {
+ if (anot[1][i] != null)
+ {
+ anot[0][i] = anot[1][i];
+ anot[0][i].description = anot[0][i].description + " (after)";
+ AeContent[HASDESCSTR] = true; // we have valid description string data
+ anot[1][i] = null;
+ }
+ }
+ anot[1] = null;
+ }
+ else
+ {
+ for (int i = 0; i < anot[0].length; i++)
+ {
+ anot[1][i].description = anot[1][i].description + " (after)";
+ }
+ }
+ return new Object[]
+ {
+ AeContent, rangeMap, anot[0], anot[1]};
+ }
+ else
+ {
+ // no annotations to parse. Just return an empty annotationElement[] array.
+ return new Object[]
+ {
+ AeContent, rangeMap, anot[0], anot[1]};
+ }
+ // return null;
+ }
+
+ /**
+ * @param jal the jalview alignment to which the annotation will be attached (ideally - freshly updated from corresponding vamsas alignment)
+ * @param annotation
+ * @return unbound jalview alignment annotation object.
+ */
+ private jalview.datamodel.AlignmentAnnotation getjAlignmentAnnotation(jalview.
+ datamodel.AlignmentI jal,
+ org.vamsas.objects.core.RangeAnnotation annotation)
+ {
+ jalview.datamodel.AlignmentAnnotation jan = null;
+ if (annotation == null)
+ {
+ return null;
+ }
+ // boolean hasSequenceRef=annotation.getClass().equals(org.vamsas.objects.core.AlignmentSequenceAnnotation.class);
+ //boolean hasProvenance=hasSequenceRef || (annotation.getClass().equals(org.vamsas.objects.core.AlignmentAnnotation.class));
+ /*int se[] = getBounds(annotation);
+ if (se==null)
+ se=new int[] {0,jal.getWidth()-1};
+ */
+ Object[] parsedRangeAnnotation = parseRangeAnnotation(annotation);
+ String a_label = annotation.getLabel();
+ String a_descr = annotation.getDescription();
+ if (a_label == null || a_label.length() == 0)
+ {
+ a_label = annotation.getType();
+ if (a_label.length() == 0)
+ {
+ a_label = "Unamed annotation";
+ }
+ }
+ if (a_descr == null || a_descr.length() == 0)
+ {
+ a_descr = "Annotation of type '" + annotation.getType() + "'";
+ }
+ if (parsedRangeAnnotation == null)
+ {
+ Cache.log.debug(
+ "Inserting empty annotation row elements for a whole-alignment annotation.");
+
+ }
+ else
+ {
+ if (parsedRangeAnnotation[3] != null)
+ {
+ Cache.log.warn("Ignoring 'After' annotation row in " +
+ annotation.getVorbaId());
+ }
+ jalview.datamodel.Annotation[] arow = (jalview.datamodel.Annotation[])
+ parsedRangeAnnotation[2];
+ boolean[] has = (boolean[]) parsedRangeAnnotation[0];
+ // VAMSAS: getGraph is only on derived annotation for alignments - in this way its 'odd' - there is already an existing TODO about removing this flag as being redundant
+ /*if ((annotation.getClass().equals(org.vamsas.objects.core.AlignmentAnnotation.class) && ((org.vamsas.objects.core.AlignmentAnnotation)annotation).getGraph())
+ || (hasSequenceRef=true && ((org.vamsas.objects.core.AlignmentSequenceAnnotation)annotation).getGraph())) {
+ */
+ if (has[HASVALS])
+ {
+ // make bounds and automatic description strings for jalview user's benefit (these shouldn't be written back to vamsas document)
+ boolean first = true;
+ float min = 0, max = 1;
+ int lastval = 0;
+ for (int i = 0; i < arow.length; i++)
+ {
+ if (arow[i] != null)
+ {
+ if (i - lastval > 1)
+ {
+ // do some interpolation *between* points
+ if (arow[lastval] != null)
+ {
+ float interval = arow[i].value - arow[lastval].value;
+ interval /= i - lastval;
+ float base = arow[lastval].value;
+ for (int ip = lastval + 1, np = 0; ip < i; np++, ip++)
+ {
+ arow[ip] = new jalview.datamodel.Annotation("", "", ' ',
+ interval * np + base);
+ // NB - Interpolated points don't get a tooltip and description.
+ }
+ }
+ }
+ lastval = i;
+ // check range - shouldn't we have a min and max property in the annotation object ?
+ if (first)
+ {
+ min = max = arow[i].value;
+ first = false;
+ }
+ else
+ {
+ if (arow[i].value < min)
+ {
+ min = arow[i].value;
+ }
+ else if (arow[i].value > max)
+ {
+ max = arow[i].value;
+ }
+ }
+ // make tooltip and display char value
+ if (!has[HASDESCSTR])
+ {
+ arow[i].description = arow[i].value + "";
+ }
+ if (!has[HASDC])
+ {
+ arow[i].displayCharacter = arow[i].value + "";
+ }
+ }
+ }
+ int type = jalview.datamodel.AlignmentAnnotation.LINE_GRAPH;
+ if (has[HASHPHOB])
+ {
+ type = jalview.datamodel.AlignmentAnnotation.BAR_GRAPH;
+ }
+ jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr, arow,
+ min, max, type);
+ }
+ else
+ {
+ jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr, arow);
+ jan.setThreshold(null);
+ }
+ if (annotation.getLinkCount() > 0)
+ {
+ Cache.log.warn("Ignoring " + annotation.getLinkCount() +
+ "links added to AlignmentAnnotation.");
+ }
+ if (annotation.getModifiable())
+ {
+ jan.editable = true;
+ }
+
+ if (annotation.getPropertyCount() > 0)
+ {
+ // look for special jalview properties
+ org.vamsas.objects.core.Property[] props = annotation.getProperty();
+ for (int p = 0; p < props.length; p++)
+ {
+ if (props[p].getName().equalsIgnoreCase("jalview:graphType"))
+ {
+ try
+ {
+ // probably a jalview annotation graph so recover the visualization hints.
+ jan.graph = jalview.datamodel.AlignmentAnnotation.
+ getGraphValueFromString(props[p].getContent());
+ }
+ catch (Exception e)
+ {
+ Cache.log.debug(
+ "Invalid graph type value in jalview:graphType property.");
+ }
+ try
+ {
+ if (annotation.getGroup() != null &&
+ annotation.getGroup().length() > 0)
+ {
+ jan.graphGroup = Integer.parseInt(annotation.getGroup());
+ }
+ }
+ catch (Exception e)
+ {
+ Cache.log.info("UNIMPLEMENTED : Couldn't parse non-integer group value for setting graphGroup correctly.");
+ }
+ }
+ }
+ }
+
+ return jan;
+
+ }
+
+ return null;
+ }
+
+ private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta)
+ {
+ int[] se = getBounds(dseta);
+ SequenceFeature sf = new jalview.datamodel.SequenceFeature(dseta.getType(),
+ dseta.getDescription(), dseta.getStatus(), se[0], se[1], dseta
+ .getGroup());
+ if (dseta.getLinkCount() > 0)
+ {
+ Link[] links = dseta.getLink();
+ for (int i = 0; i < links.length; i++)
+ {
+ sf.addLink(links[i].getContent() + "|" + links[i].getHref());
+ }
+ }
+ return sf;
+ }
+
+ /**
+ * get real bounds of a RangeType's specification. start and end are an
+ * inclusive range within which all segments and positions lie.
+ * TODO: refactor to vamsas utils
+ * @param dseta
+ * @return int[] { start, end}
+ */
+ private int[] getBounds(RangeType dseta)
+ {
+ if (dseta != null)
+ {
+ int[] se = null;
+ if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
+ {
+ throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
+ }
+ if (dseta.getSegCount() > 0)
+ {
+ se = getSegRange(dseta.getSeg(0), true);
+ for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)
+ {
+ int nse[] = getSegRange(dseta.getSeg(s), true);
+ if (se[0] > nse[0])
+ {
+ se[0] = nse[0];
+ }
+ if (se[1] < nse[1])
+ {
+ se[1] = nse[1];
+ }
+ }
+ }
+ if (dseta.getPosCount() > 0)
+ {
+ // could do a polarity for pos range too. and pass back indication of discontinuities.
+ int pos = dseta.getPos(0).getI();
+ se = new int[]
+ {
+ pos, pos};
+ for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
+ {
+ pos = dseta.getPos(p).getI();
+ if (se[0] > pos)
+ {
+ se[0] = pos;
+ }
+ if (se[1] < pos)
+ {
+ se[1] = pos;
+ }
+ }
+ }
+ return se;
+ }
+ return null;
+ }
+
+ /**
+ * map from a rangeType's internal frame to the referenced object's coordinate frame.
+ * @param dseta
+ * @return int [] { ref(pos)...} for all pos in rangeType's frame.
+ */
+ private int[] getMapping(RangeType dseta)
+ {
+ Vector posList = new Vector();
+ if (dseta != null)
+ {
+ int[] se = null;
+ if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
+ {
+ throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
+ }
+ if (dseta.getSegCount() > 0)
+ {
+ for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)
+ {
+ se = getSegRange(dseta.getSeg(s), false);
+ int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
+ for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)
+ {
+ posList.add(new Integer(p));
+ }
+ }
+ }
+ else if (dseta.getPosCount() > 0)
+ {
+ int pos = dseta.getPos(0).getI();
+
+ for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
+ {
+ pos = dseta.getPos(p).getI();
+ posList.add(new Integer(pos));
+ }
+ }
+ }
+ if (posList != null && posList.size() > 0)
+ {
+ int[] range = new int[posList.size()];
+ for (int i = 0; i < range.length; i++)
+ {
+ range[i] = ( (Integer) posList.elementAt(i)).intValue();
+ }
+ posList.clear();
+ return range;
+ }
+ return null;
+ }
+
+ /* not needed now.
+ * Provenance getVamsasProvenance(jalview.datamodel.Provenance jprov) {
+ jalview.datamodel.ProvenanceEntry[] entries = null;
+ // TODO: fix App and Action here.
+ Provenance prov = new Provenance();
+ org.exolab.castor.types.Date date = new org.exolab.castor.types.Date(
+ new java.util.Date());
+ Entry provEntry;
+
+ if (jprov != null)
+ {
+ entries = jprov.getEntries();
+ for (int i = 0; i < entries.length; i++)
+ {
+ provEntry = new Entry();
+ try
+ {
+ date = new org.exolab.castor.types.Date(entries[i].getDate());
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+
+ date = new org.exolab.castor.types.Date(entries[i].getDate());
+ }
+ provEntry.setDate(date);
+ provEntry.setUser(entries[i].getUser());
+ provEntry.setAction(entries[i].getAction());
+ prov.addEntry(provEntry);
+ }
+ }
+ else
+ {
+ provEntry = new Entry();
+ provEntry.setDate(date);
+ provEntry.setUser(System.getProperty("user.name")); // TODO: ext string
+ provEntry.setApp("JVAPP"); // TODO: ext string
+ provEntry.setAction(action);
+ prov.addEntry(provEntry);
+ }
+
+ return prov;
+ }
+ */
+ jalview.datamodel.Provenance getJalviewProvenance(Provenance prov)
+ {
+ // TODO: fix App and Action entries and check use of provenance in jalview.
+ jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();
+ for (int i = 0; i < prov.getEntryCount(); i++)
+ {
+ jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i).getAction(),
+ prov.getEntry(i).getDate().toDate(),
+ prov.getEntry(i).getId());
+ }
+
+ return jprov;
+ }
+
+ /**
+ *
+ * @return default initial provenance list for a Jalview created vamsas
+ * object.
+ */
+ Provenance dummyProvenance()
+ {
+ return dummyProvenance(null);
+ }
+
+ Entry dummyPEntry(String action)
+ {
+ Entry entry = new Entry();
+ entry.setApp(this.provEntry.getApp());
+ if (action != null)
+ {
+ entry.setAction(action);
+ }
+ else
+ {
+ entry.setAction("created.");
+ }
+ entry.setDate(new org.exolab.castor.types.Date(new java.util.Date()));
+ entry.setUser(this.provEntry.getUser());
+ return entry;
+ }
+
+ Provenance dummyProvenance(String action)
+ {
+ Provenance prov = new Provenance();
+ prov.addEntry(dummyPEntry(action));
+ return prov;
+ }
+
+ void addProvenance(Provenance p, String action)
+ {
+ p.addEntry(dummyPEntry(action));
+ }
+
+}
--- /dev/null
+package jalview.schemes;\r
+\r
+public class ScoreMatrix\r
+{\r
+ String name;\r
+ /**\r
+ * reference to integer score matrix\r
+ */\r
+ int[][] matrix;\r
+ /**\r
+ * 0 for Protein Score matrix. 1 for dna score matrix\r
+ */\r
+ int type;\r
+ ScoreMatrix(String name, int[][] matrix, int type)\r
+ {\r
+ this.matrix = matrix;\r
+ this.type = type;\r
+ }\r
+\r
+ public boolean isDNA()\r
+ {\r
+ return type == 1;\r
+ }\r
+\r
+ public boolean isProtein()\r
+ {\r
+ return type == 0;\r
+ }\r
+\r
+ public int[][] getMatrix()\r
+ {\r
+ return matrix;\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param A1\r
+ * @param A2\r
+ * @return score for substituting first char in A1 with first char in A2\r
+ */\r
+ public int getPairwiseScore(String A1, String A2)\r
+ {\r
+ return getPairwiseScore(A1.charAt(0), A2.charAt(0));\r
+ }\r
+\r
+ public int getPairwiseScore(char c, char d)\r
+ {\r
+ int pog = 0;\r
+\r
+ try\r
+ {\r
+ int a = (type == 0) ? ResidueProperties.aaIndex[c] :\r
+ ResidueProperties.nucleotideIndex[c];\r
+ int b = (type == 0) ? ResidueProperties.aaIndex[d] :\r
+ ResidueProperties.nucleotideIndex[d];\r
+\r
+ pog = matrix[a][b];\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ //System.out.println("Unknown residue in " + A1 + " " + A2);\r
+ }\r
+\r
+ return pog;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer
+ * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package jalview.util;
+
+import java.util.*;
+
+/**
+ * MapList
+ * Simple way of bijectively mapping a non-contiguous linear range to another non-contiguous linear range
+ * Use at your own risk!
+ * TODO: efficient implementation of private posMap method
+ * TODO: test/ensure that sense of from and to ratio start position is conserved (codon start position recovery)
+ * TODO: optimize to use int[][] arrays rather than vectors.
+ */
+public class MapList
+{
+ public Vector fromShifts;
+ public Vector toShifts;
+ int fromRatio; // number of steps in fromShifts to one toRatio unit
+ int toRatio; // number of steps in toShifts to one fromRatio
+ public MapList(int from[], int to[], int fromRatio, int toRatio)
+ {
+ fromShifts = new Vector();
+ for (int i = 0; i < from.length; i += 2)
+ {
+ fromShifts.add(new int[]
+ {from[i], from[i + 1]});
+ }
+ toShifts = new Vector();
+ for (int i = 0; i < to.length; i += 2)
+ {
+ toShifts.add(new int[]
+ {to[i], to[i + 1]});
+ }
+ this.fromRatio = fromRatio;
+ this.toRatio = toRatio;
+ }
+
+ /**
+ * get all mapped positions from 'from' to 'to'
+ * @return int[][] { int[] { fromStart, fromFinish, toStart, toFinish }, int [fromFinish-fromStart+2] { toStart..toFinish mappings}}
+ */
+ public int[][] makeFromMap()
+ {
+ return posMap(fromShifts, fromRatio, toShifts, toRatio);
+ }
+
+ /**
+ * get all mapped positions from 'to' to 'from'
+ * @return int[to position]=position mapped in from
+ */
+ public int[][] makeToMap()
+ {
+ return posMap(toShifts, toRatio, fromShifts, fromRatio);
+ }
+
+ /**
+ * construct an int map for intervals in intVals
+ * @param intVals
+ * @return int[] { from, to pos in range }, int[range.to-range.from+1] returning mapped position
+ */
+ private int[][] posMap(Vector intVals, int ratio, Vector toIntVals,
+ int toRatio)
+ {
+ Iterator iv = intVals.iterator();
+ if (!iv.hasNext())
+ {
+ return null;
+ }
+ int[] intv = (int[]) iv.next();
+ int from = intv[0], to = intv[1];
+ if (from > to)
+ {
+ from = intv[1];
+ to = intv[0];
+ }
+ while (iv.hasNext())
+ {
+ intv = (int[]) iv.next();
+ if (intv[0] < from)
+ {
+ from = intv[0];
+ }
+ if (intv[1] < from)
+ {
+ from = intv[1];
+ }
+ if (intv[0] > to)
+ {
+ to = intv[0];
+ }
+ if (intv[1] > to)
+ {
+ to = intv[1];
+ }
+ }
+ int tF = 0, tT = 0;
+ int mp[][] = new int[to - from + 2][];
+ for (int i = 0; i < mp.length; i++)
+ {
+ int[] m = shift(i + from, intVals, ratio, toIntVals, toRatio);
+ if (m != null)
+ {
+ if (i == 0)
+ {
+ tF = tT = m[0];
+ }
+ else
+ {
+ if (m[0] < tF)
+ {
+ tF = m[0];
+ }
+ if (m[0] > tT)
+ {
+ tT = m[0];
+ }
+ }
+ }
+ mp[i] = m;
+ }
+ int[][] map = new int[][]
+ {
+ new int[]
+ {
+ from, to, tF, tT}, new int[to - from + 2]};
+
+ map[0][2] = tF;
+ map[0][3] = tT;
+
+ for (int i = 0; i < mp.length; i++)
+ {
+ if (mp[i] != null)
+ {
+ map[1][i] = mp[i][0] - tF;
+ }
+ else
+ {
+ map[1][i] = -1; // indicates an out of range mapping
+ }
+ }
+ return map;
+ }
+
+ /**
+ * addShift
+ * @param pos start position for shift (in original reference frame)
+ * @param shift length of shift
+ *
+ public void addShift(int pos, int shift)
+ {
+ int sidx = 0;
+ int[] rshift=null;
+ while (sidx<shifts.size() && (rshift=(int[]) shifts.elementAt(sidx))[0]<pos)
+ sidx++;
+ if (sidx==shifts.size())
+ shifts.insertElementAt(new int[] { pos, shift}, sidx);
+ else
+ rshift[1]+=shift;
+ }
+ */
+ /**
+ * shift from pos to To(pos)
+ *
+ * @param pos int
+ * @return int shifted position in To, frameshift in From
+ */
+ public int[] shiftFrom(int pos)
+ {
+ return shift(pos, fromShifts, fromRatio, toShifts, toRatio);
+ }
+
+ /**
+ * inverse of shiftFrom - maps pos in To to a position in From
+ * @param pos (in To)
+ * @return shifted position in From, frameshift in To
+ */
+ public int[] shiftTo(int pos)
+ {
+ return shift(pos, toShifts, toRatio, fromShifts, fromRatio);
+ }
+
+ /**
+ *
+ * @param fromShifts
+ * @param fromRatio
+ * @param toShifts
+ * @param toRatio
+ * @return
+ */
+ private int[] shift(int pos, Vector fromShifts, int fromRatio,
+ Vector toShifts, int toRatio)
+ {
+ int[] fromCount = countPos(fromShifts.iterator(), pos);
+ if (fromCount == null)
+ {
+ return null;
+ }
+ int fromRemainder = (fromCount[0] - 1) % fromRatio;
+ int toCount = 1 + ( ( (fromCount[0] - 1) / fromRatio) * toRatio);
+ int[] toPos = countToPos(toShifts.iterator(), toCount);
+ if (toPos == null)
+ {
+ return null; // throw new Error("Bad Mapping!");
+ }
+ //System.out.println(fromCount[0]+" "+fromCount[1]+" "+toCount);
+ return new int[]
+ {
+ toPos[0], fromRemainder};
+ }
+
+ /**
+ * count how many positions pos is along the series of intervals.
+ * @param intVals
+ * @param pos
+ * @return number of positions or null if pos is not within intervals
+ */
+ private int[] countPos(Iterator intVals, int pos)
+ {
+ int count = 0, intv[];
+ while (intVals.hasNext())
+ {
+ intv = (int[]) intVals.next();
+ if (intv[0] <= intv[1])
+ {
+ if (pos >= intv[0] && pos <= intv[1])
+ {
+ return new int[]
+ {
+ count + pos - intv[0] + 1, +1};
+ }
+ else
+ {
+ count += intv[1] - intv[0] + 1;
+ }
+ }
+ else
+ {
+ if (pos >= intv[1] && pos <= intv[0])
+ {
+ return new int[]
+ {
+ count + intv[0] - pos + 1, -1};
+ }
+ else
+ {
+ count += intv[0] - intv[1] + 1;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * count out pos positions into a series of intervals and return the position
+ * @param intVals
+ * @param pos
+ * @return position pos in interval set
+ */
+ private int[] countToPos(Iterator intVals, int pos)
+ {
+ int count = 0, diff = 0, intv[] =
+ {
+ 0, 0};
+ while (intVals.hasNext())
+ {
+ intv = (int[]) intVals.next();
+ diff = intv[1] - intv[0];
+ if (diff >= 0)
+ {
+ if (pos <= count + 1 + diff)
+ {
+ return new int[]
+ {
+ pos - count - 1 + intv[0], +1};
+ }
+ else
+ {
+ count += 1 + diff;
+ }
+ }
+ else
+ {
+ if (pos <= count + 1 - diff)
+ {
+ return new int[]
+ {
+ intv[0] - (pos - count - 1), -1};
+ }
+ else
+ {
+ count += 1 - diff;
+ }
+ }
+ }
+ return null; //(diff<0) ? (intv[1]-1) : (intv[0]+1);
+ }
+
+ public static void testMap(MapList ml, int fromS, int fromE)
+ {
+ for (int from = 1; from <= 25; from++)
+ {
+ int[] too = ml.shiftFrom(from);
+ System.out.print("ShiftFrom(" + from + ")==");
+ if (too == null)
+ {
+ System.out.print("NaN\n");
+ }
+ else
+ {
+ System.out.print(too[0] + " % " + too[1]);
+ System.out.print("\t+--+\t");
+ int[] toofrom = ml.shiftTo(too[0]);
+ if (toofrom != null)
+ {
+ if (toofrom[0] != from)
+ {
+ System.err.println("Mapping not reflexive:" + from + " " + too[0] +
+ "->" + toofrom[0]);
+ }
+ System.out.println("ShiftTo(" + too[0] + ")==" + toofrom[0] + " % " +
+ toofrom[1]);
+ }
+ else
+ {
+ System.out.println("ShiftTo(" + too[0] + ")==" +
+ "NaN! - not Bijective Mapping!");
+ }
+ }
+ }
+ int mmap[][] = ml.makeFromMap();
+ System.out.println("FromMap : (" + mmap[0][0] + " " + mmap[0][1] + " " +
+ mmap[0][2] + " " + mmap[0][3] + " ");
+ for (int i = 1; i <= mmap[1].length; i++)
+ {
+ if (mmap[1][i - 1] == -1)
+ {
+ System.out.print(i + "=XXX");
+
+ }
+ else
+ {
+ System.out.print(i + "=" + (mmap[0][2] + mmap[1][i - 1]));
+ }
+ if (i % 20 == 0)
+ {
+ System.out.print("\n");
+ }
+ else
+ {
+ System.out.print(",");
+ }
+ }
+ System.out.print("\n");
+ }
+
+ public static void main(String argv[])
+ {
+ MapList ml = new MapList(new int[]
+ {1, 5, 10, 15, 25, 20},
+ new int[]
+ {51, 1}, 1, 3);
+ MapList ml1 = new MapList(new int[]
+ {1, 3, 17, 4},
+ new int[]
+ {51, 1}, 1, 3);
+
+ // test internal consistency
+ int to[] = new int[51];
+ MapList.testMap(ml, 1, 25);
+ /*
+ for (int from=1; from<=51; from++) {
+ int[] too=ml.shiftTo(from);
+ int[] toofrom=ml.shiftFrom(too[0]);
+ System.out.println("ShiftFrom("+from+")=="+too[0]+" % "+too[1]+"\t+-+\tShiftTo("+too[0]+")=="+toofrom[0]+" % "+toofrom[1]);
+ }*/
+ System.out.print("Success?\n"); // if we get here - something must be working!
+ }
+}
--- /dev/null
+package jalview.ws;\r
+\r
+import java.util.*;\r
+\r
+import jalview.analysis.*;\r
+import jalview.bin.*;\r
+import jalview.datamodel.*;\r
+import jalview.datamodel.Alignment;\r
+import jalview.gui.*;\r
+import jalview.io.*;\r
+import jalview.util.*;\r
+import vamsas.objects.simple.JpredResult;\r
+\r
+class JPredThread\r
+ extends WSThread implements WSClientI\r
+{\r
+ // TODO: put mapping between JPredJob input and input data here - JNetAnnotation adding is done after result parsing.\r
+ class JPredJob\r
+ extends WSThread.WSJob\r
+ {\r
+ // TODO: make JPredJob deal only with what was sent to and received from a JNet service\r
+ int[] predMap = null; // mapping from sequence(i) to the original sequence(predMap[i]) being predicted on\r
+ vamsas.objects.simple.Sequence sequence;\r
+ vamsas.objects.simple.Msfalignment msa;\r
+ java.util.Hashtable SequenceInfo = null;\r
+ int msaIndex = 0; // the position of the original sequence in the array of Sequences in the input object that this job holds a prediction for\r
+ /**\r
+ *\r
+ * @return true if getResultSet will return a valid alignment and prediction result.\r
+ */\r
+ public boolean hasResults()\r
+ {\r
+ if (subjobComplete && result != null && result.isFinished()\r
+ && ( (JpredResult) result).getPredfile() != null &&\r
+ ( (JpredResult) result).getAligfile() != null)\r
+ {\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ boolean hasValidInput()\r
+ {\r
+ if (sequence != null)\r
+ {\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @return null or Object[] { annotated alignment for this prediction, ColumnSelection for this prediction} or null if no results available.\r
+ * @throws Exception\r
+ */\r
+ public Object[] getResultSet()\r
+ throws Exception\r
+ {\r
+ if (result == null || !result.isFinished())\r
+ {\r
+ return null;\r
+ }\r
+ Alignment al = null;\r
+ ColumnSelection alcsel = null;\r
+ int FirstSeq = -1; // the position of the query sequence in Alignment al\r
+\r
+ JpredResult result = (JpredResult)this.result;\r
+\r
+ jalview.bin.Cache.log.debug("Parsing output from JNet job.");\r
+ // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt", "File");\r
+ jalview.io.JPredFile prediction = new jalview.io.JPredFile(result.\r
+ getPredfile(),\r
+ "Paste");\r
+ SequenceI[] preds = prediction.getSeqsAsArray();\r
+ jalview.bin.Cache.log.debug("Got prediction profile.");\r
+\r
+ if ( (this.msa != null) && (result.getAligfile() != null))\r
+ {\r
+ jalview.bin.Cache.log.debug("Getting associated alignment.");\r
+ // we ignore the returned alignment if we only predicted on a single sequence\r
+ String format = new jalview.io.IdentifyFile().Identify(result.\r
+ getAligfile(),\r
+ "Paste");\r
+\r
+ if (jalview.io.FormatAdapter.isValidFormat(format))\r
+ {\r
+ SequenceI sqs[];\r
+ if (predMap != null)\r
+ {\r
+ Object[] alandcolsel = input.getAlignmentAndColumnSelection(\r
+ alignFrame.getViewport().getGapCharacter());\r
+ sqs = (SequenceI[]) alandcolsel[0];\r
+ al = new Alignment(sqs);\r
+ alcsel = (ColumnSelection) alandcolsel[1];\r
+ }\r
+ else\r
+ {\r
+ al = new FormatAdapter().readFile(result.getAligfile(),\r
+ "Paste", format);\r
+ sqs = new SequenceI[al.getHeight()];\r
+\r
+ for (int i = 0, j = al.getHeight(); i < j; i++)\r
+ {\r
+ sqs[i] = al.getSequenceAt(i);\r
+ }\r
+ if (!jalview.analysis.SeqsetUtils.deuniquify( (Hashtable)\r
+ SequenceInfo, sqs))\r
+ {\r
+ throw (new Exception(\r
+ "Couldn't recover sequence properties for alignment."));\r
+ }\r
+ }\r
+ FirstSeq = 0;\r
+ al.setDataset(null);\r
+\r
+ jalview.io.JnetAnnotationMaker.add_annotation(prediction, al,\r
+ FirstSeq,\r
+ false, predMap);\r
+\r
+ }\r
+ else\r
+ {\r
+ throw (new Exception(\r
+ "Unknown format " + format + " for file : \n" +\r
+ result.getAligfile()));\r
+ }\r
+ }\r
+ else\r
+ {\r
+ al = new Alignment(preds);\r
+ FirstSeq = prediction.getQuerySeqPosition();\r
+ if (predMap != null)\r
+ {\r
+ char gc = alignFrame.getViewport().getGapCharacter();\r
+ SequenceI[] sqs = (SequenceI[]) ( (java.lang.Object[]) input.\r
+ getAlignmentAndColumnSelection(gc))[\r
+ 0];\r
+ if (this.msaIndex >= sqs.length)\r
+ {\r
+ throw new Error("Implementation Error! Invalid msaIndex for JPredJob on parent MSA input object!");\r
+ }\r
+\r
+ /////\r
+ //Uses RemoveGapsCommand\r
+ /////\r
+ new jalview.commands.RemoveGapsCommand("Remove Gaps",\r
+ new SequenceI[]\r
+ {sqs[msaIndex]},\r
+ alignFrame.getCurrentView().\r
+ getAlignment());\r
+\r
+ SequenceI profileseq = al.getSequenceAt(FirstSeq);\r
+ profileseq.setSequence(sqs[msaIndex].getSequenceAsString());\r
+ }\r
+\r
+ if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash(\r
+ al.getSequenceAt(FirstSeq), SequenceInfo))\r
+ {\r
+ throw (new Exception(\r
+ "Couldn't recover sequence properties for JNet Query sequence!"));\r
+ }\r
+ else\r
+ {\r
+ al.setDataset(null);\r
+ jalview.io.JnetAnnotationMaker.add_annotation(prediction, al,\r
+ FirstSeq,\r
+ true, predMap);\r
+ SequenceI profileseq = al.getSequenceAt(0); // this includes any gaps.\r
+ alignToProfileSeq(al, profileseq);\r
+ if (predMap != null)\r
+ {\r
+ // Adjust input view for gaps\r
+ // propagate insertions into profile\r
+ alcsel = propagateInsertions(profileseq, al, input);\r
+ }\r
+ }\r
+ }\r
+ return new Object[]\r
+ {\r
+ al, alcsel}; // , FirstSeq, noMsa};\r
+ }\r
+\r
+ /**\r
+ * Given an alignment where all other sequences except profileseq are aligned to the ungapped profileseq, insert gaps in the other sequences to realign them with the residues in profileseq\r
+ * @param al\r
+ * @param profileseq\r
+ */\r
+ private void alignToProfileSeq(Alignment al, SequenceI profileseq)\r
+ {\r
+ char gc = al.getGapCharacter();\r
+ int[] gapMap = profileseq.gapMap();\r
+ // insert gaps into profile\r
+ for (int lp = 0, r = 0; r < gapMap.length; r++)\r
+ {\r
+ if (gapMap[r] - lp > 1)\r
+ {\r
+ StringBuffer sb = new StringBuffer();\r
+ for (int s = 0, ns = gapMap[r] - lp; s < ns; s++)\r
+ {\r
+ sb.append(gc);\r
+ }\r
+ for (int s = 1, ns = al.getHeight(); s < ns; s++)\r
+ {\r
+ String sq = al.getSequenceAt(s).getSequenceAsString();\r
+ int diff = gapMap[r] - sq.length();\r
+ if (diff > 0)\r
+ {\r
+ // pad gaps\r
+ sq = sq + sb;\r
+ while ( (diff = gapMap[r] - sq.length()) > 0)\r
+ {\r
+ sq = sq +\r
+ ( (diff >= sb.length()) ? sb.toString() :\r
+ sb.substring(0, diff));\r
+ }\r
+ al.getSequenceAt(s).setSequence(sq);\r
+ }\r
+ else\r
+ {\r
+ al.getSequenceAt(s).setSequence(sq.substring(0, gapMap[r]) +\r
+ sb.toString() +\r
+ sq.substring(gapMap[r]));\r
+ }\r
+ }\r
+ }\r
+ lp = gapMap[r];\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Add gaps into the sequences aligned to profileseq under the given AlignmentView\r
+ * @param profileseq\r
+ * @param al\r
+ * @param input\r
+ */\r
+ private ColumnSelection propagateInsertions(SequenceI profileseq,\r
+ Alignment al,\r
+ AlignmentView input)\r
+ {\r
+ char gc = al.getGapCharacter();\r
+ Object[] alandcolsel = input.getAlignmentAndColumnSelection(gc);\r
+ ColumnSelection nview = (ColumnSelection) alandcolsel[1];\r
+ SequenceI origseq;\r
+ nview.pruneDeletions(ShiftList.parseMap( (origseq = ( (SequenceI[])\r
+ alandcolsel[0])[0]).gapMap())); // recover original prediction sequence's mapping to view.\r
+ int[] viscontigs = nview.getVisibleContigs(0, profileseq.getLength());\r
+ int spos = 0;\r
+ int offset = 0;\r
+ // input.pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()))\r
+ // add profile to visible contigs\r
+ for (int v = 0; v < viscontigs.length; v += 2)\r
+ {\r
+ if (viscontigs[v] > spos)\r
+ {\r
+ StringBuffer sb = new StringBuffer();\r
+ for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++)\r
+ {\r
+ sb.append(gc);\r
+ }\r
+ for (int s = 0, ns = al.getHeight(); s < ns; s++)\r
+ {\r
+ SequenceI sqobj = al.getSequenceAt(s);\r
+ if (sqobj != profileseq)\r
+ {\r
+ String sq = al.getSequenceAt(s).getSequenceAsString();\r
+ if (sq.length() <= spos + offset)\r
+ {\r
+ // pad sequence\r
+ int diff = spos + offset - sq.length() - 1;\r
+ if (diff > 0)\r
+ {\r
+ // pad gaps\r
+ sq = sq + sb;\r
+ while ( (diff = spos + offset - sq.length() - 1) > 0)\r
+ {\r
+ sq = sq +\r
+ ( (diff >= sb.length()) ? sb.toString() :\r
+ sb.substring(0, diff));\r
+ }\r
+ }\r
+ sq += sb.toString();\r
+ }\r
+ else\r
+ {\r
+ al.getSequenceAt(s).setSequence(sq.substring(0, spos + offset) +\r
+ sb.toString() +\r
+ sq.substring(spos + offset));\r
+ }\r
+ }\r
+ }\r
+ //offset+=sb.length();\r
+ }\r
+ spos = viscontigs[v + 1] + 1;\r
+ }\r
+ if ( (offset + spos) < profileseq.getLength())\r
+ {\r
+ StringBuffer sb = new StringBuffer();\r
+ for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)\r
+ {\r
+ sb.append(gc);\r
+ }\r
+ for (int s = 1, ns = al.getHeight(); s < ns; s++)\r
+ {\r
+ String sq = al.getSequenceAt(s).getSequenceAsString();\r
+ // pad sequence\r
+ int diff = origseq.getLength() - sq.length();\r
+ while (diff > 0)\r
+ {\r
+ sq = sq +\r
+ ( (diff >= sb.length()) ? sb.toString() : sb.substring(0, diff));\r
+ diff = origseq.getLength() - sq.length();\r
+ }\r
+ }\r
+ }\r
+ return nview;\r
+ }\r
+\r
+ public JPredJob(Hashtable SequenceInfo, SequenceI seq, int[] delMap)\r
+ {\r
+ super();\r
+ this.predMap = delMap;\r
+ String sq = AlignSeq.extractGaps(Comparison.GapChars,\r
+ seq.getSequenceAsString());\r
+ if (sq.length() >= 20)\r
+ {\r
+ this.SequenceInfo = SequenceInfo;\r
+ sequence = new vamsas.objects.simple.Sequence();\r
+ sequence.setId(seq.getName());\r
+ sequence.setSeq(sq);\r
+ }\r
+ }\r
+\r
+ public JPredJob(Hashtable SequenceInfo, SequenceI[] msf, int[] delMap)\r
+ {\r
+ this(SequenceInfo, msf[0], delMap);\r
+ if (sequence != null)\r
+ {\r
+ if (msf.length > 1)\r
+ {\r
+ msa = new vamsas.objects.simple.Msfalignment();\r
+ jalview.io.PileUpfile pileup = new jalview.io.PileUpfile();\r
+ msa.setMsf(pileup.print(msf));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ ext.vamsas.Jpred server;\r
+ String altitle = "";\r
+ JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,\r
+ String wsurl, AlignmentView alview, AlignFrame alframe)\r
+ {\r
+ super();\r
+ this.altitle = altitle;\r
+ this.server = server;\r
+ this.wsInfo = wsinfo;\r
+ this.input = alview;\r
+ this.alignFrame = alframe;\r
+ WsUrl = wsurl;\r
+ }\r
+\r
+ JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,\r
+ String wsurl, Hashtable SequenceInfo, SequenceI seq, int[] delMap,\r
+ AlignmentView alview, AlignFrame alframe)\r
+ {\r
+ this(wsinfo, altitle, server, wsurl, alview, alframe);\r
+ JPredJob job = new JPredJob(SequenceInfo, seq, delMap);\r
+ if (job.hasValidInput())\r
+ {\r
+ OutputHeader = wsInfo.getProgressText();\r
+ jobs = new WSJob[]\r
+ {\r
+ job};\r
+ job.jobnum = 0;\r
+ }\r
+ }\r
+\r
+ JPredThread(WebserviceInfo wsinfo, String altitle, ext.vamsas.Jpred server,\r
+ Hashtable SequenceInfo, SequenceI[] msf, int[] delMap,\r
+ AlignmentView alview, AlignFrame alframe, String wsurl)\r
+ {\r
+ this(wsinfo, altitle, server, wsurl, alview, alframe);\r
+ JPredJob job = new JPredJob(SequenceInfo, msf, delMap);\r
+ if (job.hasValidInput())\r
+ {\r
+ jobs = new WSJob[]\r
+ {\r
+ job};\r
+ OutputHeader = wsInfo.getProgressText();\r
+ job.jobnum = 0;\r
+ }\r
+ }\r
+\r
+ void StartJob(WSJob j)\r
+ {\r
+ if (! (j instanceof JPredJob))\r
+ {\r
+ throw new Error("Implementation error - StartJob(JpredJob) called on " +\r
+ j.getClass());\r
+ }\r
+ try\r
+ {\r
+ JPredJob job = (JPredJob) j;\r
+ if (job.msa != null)\r
+ {\r
+ job.jobId = server.predictOnMsa(job.msa);\r
+ }\r
+ else\r
+ if (job.sequence != null)\r
+ {\r
+ job.jobId = server.predict(job.sequence); // debug like : job.jobId = "/jobs/www-jpred/jp_Yatat29";//\r
+ }\r
+\r
+ if (job.jobId != null)\r
+ {\r
+ if (job.jobId.startsWith("Broken"))\r
+ {\r
+ job.result = (vamsas.objects.simple.Result)new JpredResult();\r
+ job.result.setInvalid(true);\r
+ job.result.setStatus("Submission " + job.jobId);\r
+ }\r
+ else\r
+ {\r
+ job.submitted = true;\r
+ job.subjobComplete = false;\r
+ Cache.log.info(WsUrl + " Job Id '" + job.jobId + "'");\r
+ }\r
+ }\r
+ else\r
+ {\r
+ throw new Exception("Server timed out - try again later\n");\r
+ }\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ if (e.getMessage().indexOf("Exception") > -1)\r
+ {\r
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
+ wsInfo.setProgressText(j.jobnum,\r
+ "Failed to submit the prediction. (Just close the window)\n"\r
+ +\r
+ "It is most likely that there is a problem with the server.\n");\r
+ System.err.println(\r
+ "JPredWS Client: Failed to submit the prediction. Quite possibly because of a server error - see below)\n" +\r
+ e.getMessage() + "\n");\r
+\r
+ jalview.bin.Cache.log.warn("Server Exception", e);\r
+ }\r
+ else\r
+ {\r
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);\r
+ // JBPNote - this could be a popup informing the user of the problem.\r
+ wsInfo.appendProgressText(j.jobnum,\r
+ "Failed to submit the prediction:\n"\r
+ + e.getMessage() +\r
+ wsInfo.getProgressText());\r
+\r
+ jalview.bin.Cache.log.debug("Failed Submission of job " + j.jobnum, e);\r
+\r
+ }\r
+ j.allowedServerExceptions = -1;\r
+ j.subjobComplete = true;\r
+ }\r
+ }\r
+\r
+ void parseResult()\r
+ {\r
+ int results = 0; // number of result sets received\r
+ JobStateSummary finalState = new JobStateSummary();\r
+ try\r
+ {\r
+ for (int j = 0; j < jobs.length; j++)\r
+ {\r
+ finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);\r
+ if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())\r
+ {\r
+ results++;\r
+ }\r
+ }\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+\r
+ Cache.log.error("Unexpected exception when processing results for " +\r
+ altitle, ex);\r
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);\r
+ }\r
+ if (results > 0)\r
+ {\r
+ wsInfo.showResultsNewFrame\r
+ .addActionListener(new java.awt.event.ActionListener()\r
+ {\r
+ public void actionPerformed(\r
+ java.awt.event.ActionEvent evt)\r
+ {\r
+ displayResults(true);\r
+ }\r
+ });\r
+ wsInfo.mergeResults\r
+ .addActionListener(new java.awt.event.ActionListener()\r
+ {\r
+ public void actionPerformed(\r
+ java.awt.event.ActionEvent evt)\r
+ {\r
+ displayResults(false);\r
+ }\r
+ });\r
+ wsInfo.setResultsReady();\r
+ }\r
+ else\r
+ {\r
+ wsInfo.setFinishedNoResults();\r
+ }\r
+ }\r
+\r
+ void displayResults(boolean newWindow)\r
+ {\r
+ // TODO: cope with multiple subjobs.\r
+ if (jobs != null)\r
+ {\r
+ Object[] res = null;\r
+ boolean msa = false;\r
+ for (int jn = 0; jn < jobs.length; jn++)\r
+ {\r
+ Object[] jobres = null;\r
+ JPredJob j = (JPredJob) jobs[jn];\r
+\r
+ if (j.hasResults())\r
+ {\r
+ // hack - we only deal with all single seuqence predictions or all profile predictions\r
+ msa = (j.msa != null) ? true : msa;\r
+ try\r
+ {\r
+ jalview.bin.Cache.log.debug("Parsing output of job " + jn);\r
+ jobres = j.getResultSet();\r
+ jalview.bin.Cache.log.debug("Finished parsing output.");\r
+ if (jobs.length == 1)\r
+ {\r
+ res = jobres;\r
+ }\r
+ else\r
+ {\r
+ // do merge with other job results\r
+ throw new Error(\r
+ "Multiple JNet subjob merging not yet implemented.");\r
+ }\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ jalview.bin.Cache.log.error(\r
+ "JNet Client: JPred Annotation Parse Error",\r
+ e);\r
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);\r
+ wsInfo.appendProgressText(j.jobnum,\r
+ OutputHeader + "\n" +\r
+ j.result.getStatus() +\r
+ "\nInvalid JNet job result data!\n" +\r
+ e.getMessage());\r
+ j.result.setBroken(true);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (res != null)\r
+ {\r
+ if (newWindow)\r
+ {\r
+ AlignFrame af;\r
+ if (input == null)\r
+ {\r
+ if (res[1] != null)\r
+ {\r
+ af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],\r
+ AlignFrame.DEFAULT_WIDTH,\r
+ AlignFrame.DEFAULT_HEIGHT);\r
+ }\r
+ else\r
+ {\r
+ af = new AlignFrame( (Alignment) res[0], AlignFrame.DEFAULT_WIDTH,\r
+ AlignFrame.DEFAULT_HEIGHT);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*java.lang.Object[] alandcolsel = input.getAlignmentAndColumnSelection(alignFrame.getViewport().getGapCharacter());\r
+ if (((SequenceI[])alandcolsel[0])[0].getLength()!=res.getWidth()) {\r
+ if (msa) {\r
+ throw new Error("Implementation Error! ColumnSelection from input alignment will not map to result alignment!");\r
+ }\r
+ }\r
+ if (!msa) {\r
+ // update hidden regions to account for loss of gaps in profile. - if any\r
+ // gapMap returns insert list, interpreted as delete list by pruneDeletions\r
+ //((ColumnSelection) alandcolsel[1]).pruneDeletions(ShiftList.parseMap(((SequenceI[]) alandcolsel[0])[0].gapMap()));\r
+ }*/\r
+\r
+ af = new AlignFrame( (Alignment) res[0], (ColumnSelection) res[1],\r
+ AlignFrame.DEFAULT_WIDTH,\r
+ AlignFrame.DEFAULT_HEIGHT);\r
+ }\r
+ Desktop.addInternalFrame(af, altitle,\r
+ AlignFrame.DEFAULT_WIDTH,\r
+ AlignFrame.DEFAULT_HEIGHT);\r
+ }\r
+ else\r
+ {\r
+ Cache.log.info("Append results onto existing alignment.");\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ void pollJob(WSJob job)\r
+ throws Exception\r
+ {\r
+ job.result = server.getresult(job.jobId);\r
+ }\r
+\r
+ public boolean isCancellable()\r
+ {\r
+ return false;\r
+ }\r
+\r
+ public void cancelJob()\r
+ {\r
+ throw new Error("Implementation error!");\r
+ }\r
+\r
+ public boolean canMergeResults()\r
+ {\r
+ return false;\r
+ }\r
+\r
+}\r