--- /dev/null
+build
+buildPropertiesFile
+buildTests
+buildextclients
+buildindices
+castorbinding
+clean
+compileApplet
+distclean
+help
+init
+linkcheck
+makeApplet
+makedist
+makefulldist
+obfuscate
+packageApplet
+prepare
+prepareTests
+preparejnlp
+prepubapplet_1
+pubapplet
+runenv
+signApplet
+sourcedist
+sourcedoc
+sourcescrub
+testclean
+testng
+usage
+writejnlpf
.gitattributes
TESTNG
/jalviewApplet.jar
+/benchmarking/lib
+*.class
\ No newline at end of file
-jalview.release=releases/Release_2_10_2_Branch
-jalview.version=2.10.2b1
+jalview.release=releases/Release_2_10_2b1_Branch
+jalview.version=2.10.2b2
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry combineaccessrules="false" kind="src" path="/Jalview Release 2.7"/>
+ <classpathentry kind="lib" path="/Jalview Release 2.7/jalviewApplet.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+/target/
+/bin
+/results
+*.log
+*.json
+*~
--- /dev/null
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding/<project>=UTF-8
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.8
--- /dev/null
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
--- /dev/null
+To set up benchmarking:
+
+1. In the jalview directory run
+ ant makedist
+
+This builds a jalview.jar file and puts it into dist/
+
+2. Make a lib directory in benchmarking/ if not already present.
+
+3. Purge any previous maven dependencies:
+ mvn dependency:purge-local-repository -DactTransitively=false -DreResolve=false
+
+4. Run
+ mvn install:install-file -Dfile=../dist/jalview.jar -DgroupId=jalview.org -DartifactId=jalview -Dversion=1.0 -Dpackaging=jar -DlocalRepositoryPath=lib
+
+to install the jalview.jar file in the local maven repository. The pom.xml in the benchmarking references this installation, so if you change the names the pom.xml file will also need to be updated.
+
+5. Build and run jmh benchmarking. In the benchmarking directory:
+ mvn clean install
+ java -jar target/benchmarks.jar
+
+ To get JSON output instead use:
+ java -jar target/benchmarks.jar -rf json
+
+ JSON output can be viewed quickly by drag-dropping on http://jmh.morethan.io/
\ No newline at end of file
--- /dev/null
+<!--
+Copyright (c) 2014, Oracle America, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Oracle nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.jalview</groupId>
+ <artifactId>benchmarking</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>JMH benchmark sample: Java</name>
+
+ <!--
+ This is the demo/sample template build script for building Java benchmarks with JMH.
+ Edit as needed.
+ -->
+
+ <repositories>
+ <repository>
+ <id>lib</id>
+ <url>file://${project.basedir}/lib</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-core</artifactId>
+ <version>${jmh.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-generator-annprocess</artifactId>
+ <version>${jmh.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>jalview.org</groupId>
+ <artifactId>jalview</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+ <!--
+ JMH version to use with this project.
+ -->
+ <jmh.version>1.19</jmh.version>
+
+ <!--
+ Java source/target to use for compilation.
+ -->
+ <javac.target>1.8</javac.target>
+
+ <!--
+ Name of the benchmark Uber-JAR to generate.
+ -->
+ <uberjar.name>benchmarks</uberjar.name>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <compilerVersion>${javac.target}</compilerVersion>
+ <source>${javac.target}</source>
+ <target>${javac.target}</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <finalName>${uberjar.name}</finalName>
+ <transformers>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.openjdk.jmh.Main</mainClass>
+ </transformer>
+ </transformers>
+ <filters>
+ <filter>
+ <!--
+ Shading signed JARs will fail without this.
+ http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
+ -->
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.8.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.5.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.17</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+</project>
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+
+package org.jalview;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Param;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+
+/*
+ * A class to benchmark hidden columns performance
+ */
+@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
+public class HiddenColumnsBenchmark
+{
+ /*
+ * State with multiple hidden columns and a start position set
+ */
+ @State(Scope.Thread)
+ public static class HiddenColsAndStartState
+ {
+ @Param({"300", "10000", "100000"})
+ public int maxcols;
+
+ @Param({"1", "50", "90"})
+ public int startpcnt; // position as percentage of maxcols
+
+ @Param({"1","15","100"})
+ public int hide;
+
+ HiddenColumns h = new HiddenColumns();
+ Random rand = new Random();
+
+ public int hiddenColumn;
+ public int visibleColumn;
+
+ @Setup
+ public void setup()
+ {
+ rand.setSeed(1234);
+ int lastcol = 0;
+ while (lastcol < maxcols)
+ {
+ int count = rand.nextInt(100);
+ lastcol += count;
+ h.hideColumns(lastcol, lastcol+hide);
+ lastcol+=hide;
+ }
+
+ // make sure column at start is hidden
+ hiddenColumn = (int)(maxcols * startpcnt/100.0);
+ h.hideColumns(hiddenColumn, hiddenColumn);
+
+ // and column <hide> after start is visible
+ ColumnSelection sel = new ColumnSelection();
+ h.revealHiddenColumns(hiddenColumn+hide, sel);
+ visibleColumn = hiddenColumn+hide;
+
+ System.out.println("Maxcols: " + maxcols + " HiddenCol: " + hiddenColumn + " Hide: " + hide);
+ System.out.println("Number of hidden columns: " + h.getSize());
+ }
+ }
+
+ /* Convention: functions in alphabetical order */
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public int benchAdjustForHiddenColumns(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.adjustForHiddenColumns(tstate.visibleColumn);
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public int benchFindColumnPosition(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.findColumnPosition(tstate.visibleColumn);
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public List<Integer> benchFindHiddenRegionPositions(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.findHiddenRegionPositions();
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public ArrayList<int[]> benchGetHiddenColumnsCopy(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.getHiddenColumnsCopy();
+ }
+
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public int benchGetSize(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.getSize();
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public HiddenColumns benchHideCols(HiddenColsAndStartState tstate)
+ {
+ tstate.h.hideColumns(tstate.visibleColumn,
+ tstate.visibleColumn+2000);
+ return tstate.h;
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public boolean benchIsVisible(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.isVisible(tstate.hiddenColumn);
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public HiddenColumns benchReveal(HiddenColsAndStartState tstate)
+ {
+ ColumnSelection sel = new ColumnSelection();
+ tstate.h.revealHiddenColumns(tstate.hiddenColumn, sel);
+ return tstate.h;
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public HiddenColumns benchRevealAll(HiddenColsAndStartState tstate)
+ {
+ ColumnSelection sel = new ColumnSelection();
+ tstate.h.revealAllHiddenColumns(sel);
+ return tstate.h;
+ }
+
+
+}
\ No newline at end of file
<offline_allowed />
</information>
<resources>
- <j2se version="9+" />
+ <j2se version="1.7+" />
<jar main="true" href="jalview.jar"/>
<fileset dir="${packageDir}">
<exclude name="jalview.jar" />
</presetdef>
<jnlpf toFile="${jnlpFile}" />
- <!-- add a j2se entry for java 9 -->
- <replace file="${jnlpFile}" value="j2se version="7+" initial-heap-size="${inih}" max-heap-size="${maxh}" java-vm-args="--add-modules=java.se.ee"">
- <replacetoken>j2se version="9+"</replacetoken>
+ <!-- add the add-modules j2se attribute for java 9 -->
+ <replace file="${jnlpFile}" value="j2se version="1.7+" initial-heap-size="${inih}" max-heap-size="${maxh}" java-vm-args="--add-modules=java.se.ee"">
+ <replacetoken>j2se version="1.7+"</replacetoken>
</replace>
</target>
<mapID target="home" url="html/index.html" />
<mapID target="new" url="html/whatsNew.html"/>
- <mapID target="release" url="html/releases.html#Jalview.2.10.2b1"/>
+ <mapID target="release" url="html/releases.html#Jalview.2.10.3"/>
<mapID target="alannotation" url="html/features/annotation.html"/>
<mapID target="keys" url="html/keys.html"/>
<mapID target="newkeys" url="html/features/newkeystrokes.html"/>
<mapID target="printSetupIcon" url="icons/setup.png" />
<mapID target="overview" url="html/features/overview.html" />
+ <mapID target="overviewprefs" url="html/features/preferences.html#overview" />
</map>
<tocitem text="Groovy Features Counter example" target="groovy.featurescounter"/>
<tocitem text="Custom Colourschemes in Groovy" target="groovy.colours"/>
<tocitem text="Omit hidden regions in Overview" target="overview"/>
+ <tocitem text="Show gaps as grey in overview" target="overviewprefs"/>
<tocitem text="identifers.org for URL Links" target="linksprefs" />
<tocitem text="New features in Split Frame View" target="splitframe.mirrorfonts" />
</tocitem>
<strong>View→Overview window</strong>
</p>
<p>Select the overview window menu item to get a navigable image
- of the whole alignment.</p>
+ of the whole alignment. By default, gaps are shown as dark grey, in
+ the overview (since 2.10.2b1).</p>
<p>The red box indicates the currently viewed region of the
alignment, this may be moved by clicking and dragging with the
mouse.</p>
<p>Click anywhere else in the overview to centre the view on that
position</p>
- <p></p>
+ <p></p>
<p>
<strong>Hiding hidden regions in the overview</strong>
</p>
Hidden sequences and columns are by default shown as dark-grey rows
and columns in the overview. Hidden regions can also be omitted
entirely (to make the Overview 'WYSIWIG') by <strong>Right-clicking</strong>
- (or CMD-Clicking) to open the overview's popup menu.<br />
- <br /> <em>The option to include/exclude hidden regions in the
+ (or CMD-Clicking) to open the overview's popup menu.<br /> <br />
+ <em>The option to include/exclude hidden regions in the
overview was introduced in Jalview 2.10.2</em>.
<p>
- <img src="overview.gif" width="407" height="137">
+ <img src="overview.png" width="800" height="196" alt="1hdc.pfam example alignment">
</p>
<p> </p>
+ <em>Previous to 2.10.2b1, gaps were white, and sequences shown as
+ dark grey unless coloured.</em>
</body>
</html>
Preferences</a> tab allows you to configure default colourschemes
for a new alignment window.
</li>
+ <li>The <a href="#overview"><strong>"Overview"</strong>
+ Preferences</a> tab configures defaults for the overview window.
+ </li>
<li>The <a href="#structure"><strong>"Structure"</strong>
Preferences</a> tab allows you to configure options for obtaining
and displaying structure information.
by Annotation...</a> is selected from the alignment window's colours
menu.
</p>
+ <p>
+ <a name="overview"><strong>"Overview"
+ Preferences tab</strong>
+ </p>
+ <p>
+ <em>Use legacy gap colouring (gaps are white)</em> - when enabled,
+ Jalview's overview shows gaps as white, and sequences with no
+ colourscheme applied as grey.
+ </p>
+ <p>
+ <em>Show Hidden regions when opening overview</em> - default setting
+ for inclusion of hidden regions.
+ </p>
+ <p>
+ <em>Gap Colour</em> - When legacy gap colouring is not enabled, this
+ configures the default colour for gaps in the overview.
+ </p>
+ <p>
+ <em>Hidden Colour</em> - colour used to highlight regions in the
+ overview that are hidden in the alignment.
+ </p>
+ <p>
+ <em>Gap Colour</em> - The default colour scheme for a new alignment
+ window. If the chosen option is "User Defined" then the
+ last User Defined Colour loaded or saved via the User Defined
+ Colours panel will be loaded.
+ </p>
<p>
<a name="structure"><strong>"Structure"
Preferences tab</strong></a><em> added in Jalview 2.8.2</em>
<tr>
<td width="60" nowrap>
<div align="center">
+ <strong><a name="Jalview.2.10.3">2.10.3</a><br />
+ <em>10/10/2017</em></strong>
+ </div>
+ </td>
+ <td><div align="left">
+ <em></em>
+ <ul>
+ <li>
+ <!-- JAL-2446 -->Faster and more efficient management and
+ rendering of sequence features
+ </li>
+ </ul>
+ </td>
+ <td><div align="left">
+ <em></em>
+ <ul>
+ <li><!-- JAL-2728 -->Protein annotation panel too high in CDS/Protein view
+ </li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <td width="60" nowrap>
+ <div align="center">
+ <strong><a name="Jalview.2.10.2b2">2.10.2b2</a><br />
+ <em>2/10/2017</em></strong>
+ </div>
+ </td>
+ <td><div align="left">
+ <em>New features in Jalview Desktop</em>
+ <ul>
+ <li>
+ <!-- JAL-2748 -->Uniprot Sequence Fetcher now uses web API at uniprot.org
+ </li>
+ <li> <!-- JAL-2745 -->HTTPS used for all connections to ebi.ac.uk
+ </li>
+ </ul>
+ </div></td>
+ <td><div align="left">
+ </div></td>
+ </tr>
+ <tr>
+ <td width="60" nowrap>
+ <div align="center">
<strong><a name="Jalview.2.10.2b1">2.10.2b1</a><br />
- <em>TBA</em></strong>
+ <em>7/9/2017</em></strong>
</div>
</td>
<td><div align="left">
<em></em>
<ul>
+ <li>
+ <!-- JAL-2588 -->Show gaps in overview window by colouring
+ in grey (sequences used to be coloured grey, and gaps were
+ white)
+ </li>
+ <li>
+ <!-- JAL-2588,JAL-2527 -->Overview tab in Jalview Desktop
+ Preferences
+ </li>
+ <li>
+ <!-- JAL-2587 -->Overview updates immediately on increase
+ in size and progress bar shown as higher resolution
+ overview is recalculated
+ </li>
+
</ul>
</div></td>
<td><div align="left">
<em></em>
<ul>
+ <li>
+ <!-- JAL-2664 -->Overview window redraws every hidden
+ column region row by row
+ </li>
+ <li>
+ <!-- JAL-2681 -->duplicate protein sequences shown after
+ retrieving Ensembl crossrefs for sequences from Uniprot
+ </li>
+ <li>
+ <!-- JAL-2603 -->Overview window throws NPE if show boxes
+ format setting is unticked
+ </li>
+ <li>
+ <!-- JAL-2610 -->Groups are coloured wrongly in overview
+ if group has show boxes format setting unticked
+ </li>
+ <li>
+ <!-- JAL-2672,JAL-2665 -->Redraw problems when
+ autoscrolling whilst dragging current selection group to
+ include sequences and columns not currently displayed
+ </li>
+ <li>
+ <!-- JAL-2691 -->Not all chains are mapped when multimeric
+ assemblies are imported via CIF file
+ </li>
+ <li>
+ <!-- JAL-2704 -->Gap colour in custom colourscheme is not
+ displayed when threshold or conservation colouring is also
+ enabled.
+ </li>
+ <li>
+ <!-- JAL-2549 -->JABAWS 2.2 services report wrong JABAWS
+ server version
+ </li>
+ <li>
+ <!-- JAL-2673 -->Jalview continues to scroll after
+ dragging a selected region off the visible region of the
+ alignment
+ </li>
+ <li>
+ <!-- JAL-2724 -->Cannot apply annotation based
+ colourscheme to all groups in a view
+ </li>
+ <li>
+ <!-- JAL-2511 -->IDs don't line up with sequences
+ initially after font size change using the Font chooser or
+ middle-mouse zoom
+ </li>
</ul>
</div></td>
-
+ </tr>
<tr>
<td width="60" nowrap>
<div align="center">
</head>
<body>
<p>
- <strong>Jalview 2.10.2b1 bugfix release</strong>
+ <strong>What's new in Jalview 2.10.3 ?</strong>
</p>
<p>
- This is patch release for 2.10.2. See the <a
- href="releases.html#Jalview2.10.2b1">release notes</a>.
- </p>
- <p>
- <strong>What's new in Jalview 2.10.2 ?</strong>
- </p>
- <p>
- Version 2.10.2 was released in August 2017, and introduced new user
- interface features, improved and more extensible tree and PCA
- analysis, more robust 3D structure viewing with UCSF Chimera and an
- updated service client for JABAWS. The full list of bug fixes and
- new features can be found in the <a
- href="releases.html#Jalview.2.10.2"> 2.10.2 Release Notes</a>, but
+ Version 2.10.3 is due for release in October 2017. The full list of
+ bug fixes and new features can be found in the <a
+ href="releases.html#Jalview.2.10.3"> 2.10.3 Release Notes</a>, but
the highlights are below.
</p>
- <ul>
- <li><strong>New dialog and faster and more
- configurable Tree and PCA calculations</strong><br> Menu entries for
- calculating PCA and different types of tree have been replaced by
- a single <a href="calculations/calculations.html"><em>Calculations</em>
- dialog box</a>. The underlying implementation for the PCA and tree
- calculations have been made faster and more memory efficient.</li>
- <li><strong>Extensible score models</strong><br />A new
- framework has also been created for the score models used to
- calculate distances between sequences and shade alignments. This
- framework allows import of substitution matrices in NCBI and
- AAIndex format.<br /> <strong>PCA Bug Fixes</strong>. Jalview's
- implementation of PCA differed in its treatment of gaps and
- non-standard residues. The BLOSUM62 matrix also included a typo
- that affected results. See the <a
- href="releases.html#2102scoremodelbugs">2.10.2 release note
- about score model bugs</a> for details and how to reinstate legacy
- behaviour.</li>
- <li><strong>Update to JABAWS 2.2</strong><br />Jalview's
- alignment, protein conservation analysis, and protein disorder and
- RNA secondary structure prediction services are now provided by <a
- href="http://www.compbio.dundee.ac.uk/jabaws">JABAWS 2.2</a>.
- Several of the programs provided as JABAWS 2.2 services have been
- updated, so their options and parameters have changed.</li>
- <li><strong>URL linkouts to other bioinformatics
- databases</strong><br />New preferences for <a
- href="webServices/urllinks.html">opening web pages for
- database cross-references</a> via the UK Elixir's EMBL-EBI's MIRIAM
- database and identifiers.org services.</li>
- <li><strong>Showing and hiding regions</strong> <br /> <a
- href="menus/popupMenu.html#hideinserts">Hide insertions</a> in the
- PopUp menu has changed its behaviour. Prior to 2.10.2, columns
- were only shown or hidden according to gaps in the sequence under
- the popup menu. Now, only columns that are gapped in all selected
- sequences as well as the sequence under the popup menu are hidden,
- and column visibility outside the selected region is left as is.
- This makes it easy to filter insertions from the alignment view
- (just select the region containing insertions to remove) without
- affecting the rest of the hidden columns.</li>
- <li><strong>Gap count - a.k.a. the Occupancy
- Annotation Row</strong><br /> Another way to filter columns according to
- the presence of gaps is to enable the <strong>Occupancy
- Annotation</strong> row via Jalview's Preferences. This annotation row
- shows a histogram of the number of aligned residues at each
- column. The <a href="features/columnFilterByAnnotation.html">Select
- By Annotation</a> dialog now also includes a percentage threshold
- mode, to make it easy to filter alignments to show only those
- columns with a particular fraction of aligned sequences.</li>
- <li><strong>Recent search history for Find, PDBe and
- Uniprot</strong><br />Easily repeat a previous search for <a
- href="features/search.html#queryhistory">Find</a> and the free
- text search system (for querying Uniprot and the PDBe).</li>
- <li><strong>Improved Overview Window</strong><br />The <a
- href="features/overview.html">alignment overview</a> is now easier
- to use when working with alignments of more than 5000 rows and
- columns, and features a new pop-up menu that allows hidden regions
- to be excluded from the overview. It also works with CDS/Protein
- alignments and MSA views in wrapped mode.</li>
- <li><strong>3D Structure</strong><br />Jalview's communication
- with UCSF Chimera has been made more robust, particularly when
- working with many structures and long sequences. Regions in
- structures that correspond to hidden regions in an alignment view
- are now left un-coloured, making it easier to highlight specific
- features in 3D. See below for <a href="#experimental">experimental
- features for exchanging annotation between Chimera and Jalview.</a></li>
- </ul>
- <p>
- <strong>Scripting</strong><br />New <a
- href="http://www.jalview.org/examples/groovy">groovy examples</a>
- demonstrate Jalview 2.10.2 APIs for creation of data-driven
- colourschemes, and custom alignment file handlers. The <a
- href="groovy/featuresCounter.html">FeatureAnnotationWorker</a>
- introduced in Jalview 2.10 has also been refactored to allow
- efficient counting across multiple feature types. Please be aware
- that feature counter scripts created for earlier versions will not
- execute in Jalview 2.10.2.
- </p>
<p>
<strong><a name="experimental">Experimental Features</a></strong>
</p>
label.urltooltip = Only one url, which must use a sequence id, can be selected for the 'On Click' option
label.edit_sequence_url_link = Edit sequence URL link
warn.name_cannot_be_duplicate = User-defined URL names must be unique and cannot be MIRIAM ids
-label.invalid_name = Invalid Name !
label.output_seq_details = Output Sequence Details to list all database references
label.urllinks = Links
label.default_cache_size = Default Cache Size
label.show_experimental = Enable experimental features
label.show_experimental_tip = Enable any new and currently 'experimental' features (see Latest Release Notes for details)
label.warning_hidden = Warning: {0} {1} is currently hidden
+label.overview_settings = Overview settings
+label.ov_legacy_gap = Use legacy gap colouring (gaps are white)
+label.gap_colour = Gap colour:
+label.ov_show_hide_default = Show hidden regions when opening overview
+label.hidden_colour = Hidden colour:
+label.select_gap_colour = Select gap colour
+label.select_hidden_colour = Select hidden colour
+label.overview = Overview
+label.reset_to_defaults = Reset to defaults
+label.oview_calc = Recalculating overview...
label.urltooltip = Sólo una url, que debe usar una id de secuencia, puede ser seleccionada en la opción 'On Click'
label.edit_sequence_url_link = Editar link de secuencia URL
warn.name_cannot_be_duplicate = Los nombres URL definidos por el usuario deben ser únicos y no pueden ser ids de MIRIAM
-label.invalid_name = Nombre inválido !
label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
label.urllinks = Enlaces
label.default_cache_size = Tamaño del caché por defecto
label.show_experimental = Habilitar funciones experimentales
label.show_experimental_tip = Habilitar funciones nuevas y experimentales (ver Latest Release Notes para más detalles)
label.warning_hidden = Advertencia: {0} {1} está actualmente oculto
+label.overview_settings = Ajustes para la ventana resumen
+label.ov_legacy_gap = <html>Utilizar el color heredado de huecos<br>(los huecos son blancos)
+label.gap_colour = Color de huecos:
+label.ov_show_hide_default = Mostrar regiones ocultas al abrir el resumen
+label.hidden_colour = Color de las regiones ocultas:
+label.select_gap_colour = Seleccionar color de huecos
+label.select_hidden_colour = Seleccionar color de las regiones ocultas
+label.overview = Resumen
+label.reset_to_defaults = Restablecen a los predeterminados
+label.oview_calc = Recalculando resumen
* @return true if the column at the position is hidden
*/
public boolean isHidden(int c);
+
+ /**
+ * Answers if any column in this collection is hidden
+ *
+ * @return true if there is at least 1 hidden column
+ */
+ public boolean hasHidden();
}
public boolean isHidden(int r);
/**
+ * Answers if any row in this collection is hidden
+ *
+ * @return true if there is at least 1 hidden row
+ */
+ public boolean hasHidden();
+
+ /**
* Answers the sequence at the given position in the alignment
*
* @param r
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.api;
+
+import java.beans.PropertyChangeListener;
+
+public interface RendererListenerI extends PropertyChangeListener
+{
+
+}
package jalview.appletgui;
import jalview.renderer.OverviewRenderer;
+import jalview.renderer.OverviewResColourFinder;
import jalview.viewmodel.OverviewDimensions;
import java.awt.Color;
private AlignViewport av;
- // Can set different properties in this seqCanvas than
- // main visible SeqCanvas
- private SequenceRenderer sr;
-
private jalview.renderer.seqfeatures.FeatureRenderer fr;
private Frame nullFrame;
nullFrame = new Frame();
nullFrame.addNotify();
- sr = new SequenceRenderer(av);
- sr.graphics = nullFrame.getGraphics();
- sr.renderGaps = false;
- sr.forOverview = true;
fr = new jalview.renderer.seqfeatures.FeatureRenderer(av);
}
setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
- or = new OverviewRenderer(sr, fr, od);
+ or = new OverviewRenderer(fr, od, av.getAlignment(),
+ av.getResidueShading(), new OverviewResColourFinder());
miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
}
else
{
+ // don't do anything if the mouse press is in the overview's box
+ // (wait to see if it's a drag instead)
+ // otherwise update the viewport
if (!od.isPositionInBox(evt.getX(), evt.getY()))
- {
- // don't do anything if the mouse press is in the overview's box
- // (wait to see if it's a drag instead)
- // otherwise update the viewport
+ {
+ draggingBox = false;
od.updateViewportFromMouse(evt.getX(), evt.getY(),
av.getAlignment().getHiddenSequences(),
av.getAlignment().getHiddenColumns());
@Override
public void mouseReleased(MouseEvent evt)
{
- if (draggingBox)
- {
- draggingBox = false;
- }
}
@Override
{
if (scrollThread != null)
{
- scrollThread.running = false;
+ scrollThread.threadRunning = false;
scrollThread = null;
}
mouseExited(evt);
}
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
scrollThread.setEvent(evt);
}
oldSeq = 0;
}
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
scrollThread = null;
}
}
{
if (evt == null)
{
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
scrollThread = null;
}
mouseDragging = false;
{
MouseEvent evt;
- boolean running = false;
+ private volatile boolean threadRunning = true;
public ScrollThread()
{
public void stopScrolling()
{
- running = false;
+ threadRunning = false;
+ }
+
+ public boolean isRunning()
+ {
+ return threadRunning;
}
@Override
public void run()
{
- running = true;
- while (running)
+ while (threadRunning)
{
if (evt != null)
if (mouseDragging && evt.getY() < 0
&& av.getRanges().getStartSeq() > 0)
{
- running = av.getRanges().scrollUp(true);
+ av.getRanges().scrollUp(true);
}
if (mouseDragging && evt.getY() >= getSize().height && av
.getAlignment().getHeight() > av.getRanges().getEndSeq())
{
- running = av.getRanges().scrollUp(false);
+ av.getRanges().scrollUp(false);
}
if (mouseDragging && evt.getX() < 0)
{
- running = av.getRanges().scrollRight(false);
+ av.getRanges().scrollRight(false);
}
else if (mouseDragging && evt.getX() >= getSize().width)
{
- running = av.getRanges().scrollRight(true);
+ av.getRanges().scrollRight(true);
}
}
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
-import jalview.renderer.ResidueShaderI;
+import jalview.renderer.ResidueColourFinder;
import jalview.renderer.seqfeatures.FeatureColourFinder;
import java.awt.Color;
boolean renderGaps = true;
- SequenceGroup currentSequenceGroup = null;
-
SequenceGroup[] allGroups = null;
Color resBoxColour;
Graphics graphics;
- boolean forOverview = false;
+ ResidueColourFinder resColourFinder;
public SequenceRenderer(AlignViewport av)
{
this.av = av;
+ resColourFinder = new ResidueColourFinder();
}
/**
this.renderGaps = renderGaps;
}
- protected Color getResidueBoxColour(SequenceI seq, int i)
- {
- allGroups = av.getAlignment().findAllGroups(seq);
-
- if (inCurrentSequenceGroup(i))
- {
- if (currentSequenceGroup.getDisplayBoxes())
- {
- getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
- }
- }
- else if (av.getShowBoxes())
- {
- getBoxColour(av.getResidueShading(), seq, i);
- }
-
- return resBoxColour;
- }
-
/**
* Get the residue colour at the given sequence position - as determined by
* the sequence group colour (if any), else the colour scheme, possibly
{
// TODO replace 8 or so code duplications with calls to this method
// (refactored as needed)
- Color col = getResidueBoxColour(seq, position);
-
- if (finder != null)
- {
- col = finder.findFeatureColour(col, seq, position);
- }
- return col;
- }
-
- void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
- {
- if (shader.getColourScheme() != null)
- {
- resBoxColour = shader.findColour(seq.getCharAt(i), i, seq);
- }
- else if (forOverview
- && !jalview.util.Comparison.isGap(seq.getCharAt(i)))
- {
- resBoxColour = Color.lightGray;
- }
- else
- {
- resBoxColour = Color.white;
- }
-
+ return resColourFinder.getResidueColour(av.getShowBoxes(),
+ av.getResidueShading(),
+ allGroups, seq, position, finder);
}
public Color findSequenceColour(SequenceI seq, int i)
int curWidth = av.getCharWidth(), avCharWidth = av.getCharWidth(),
avCharHeight = av.getCharHeight();
+ Color resBoxColour = Color.white;
Color tempColour = null;
while (i <= end)
{
resBoxColour = Color.white;
if (i < length)
{
- if (inCurrentSequenceGroup(i))
+ SequenceGroup currentSequenceGroup = resColourFinder
+ .getCurrentSequenceGroup(allGroups, i);
+ if (currentSequenceGroup != null)
{
if (currentSequenceGroup.getDisplayBoxes())
{
- getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+ resBoxColour = resColourFinder.getBoxColour(
+ currentSequenceGroup.getGroupColourScheme(), seq,
i);
}
}
else if (av.getShowBoxes())
{
- getBoxColour(av.getResidueShading(), seq, i);
+ resBoxColour = resColourFinder
+ .getBoxColour(av.getResidueShading(), seq, i);
}
}
continue;
}
- if (inCurrentSequenceGroup(i))
+ SequenceGroup currentSequenceGroup = resColourFinder
+ .getCurrentSequenceGroup(allGroups, i);
+ if (currentSequenceGroup != null)
{
if (!currentSequenceGroup.getDisplayText())
{
if (currentSequenceGroup.getColourText())
{
- getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
+ resBoxColour = resColourFinder.getBoxColour(
+ currentSequenceGroup.getGroupColourScheme(), seq, i);
graphics.setColor(resBoxColour.darker());
}
if (currentSequenceGroup.getShowNonconserved())
if (av.getColourText())
{
- getBoxColour(av.getResidueShading(), seq, i);
+ resBoxColour = resColourFinder
+ .getBoxColour(av.getResidueShading(), seq, i);
if (av.getShowBoxes())
{
graphics.setColor(resBoxColour.darker());
return sequenceChar;
}
- boolean inCurrentSequenceGroup(int res)
- {
- if (allGroups == null)
- {
- return false;
- }
-
- for (int i = 0; i < allGroups.length; i++)
- {
- if (allGroups[i].getStartRes() <= res
- && allGroups[i].getEndRes() >= res)
- {
- currentSequenceGroup = allGroups[i];
- return true;
- }
- }
-
- return false;
- }
-
- public void drawHighlightedText(SequenceI seq, int start, int end, int x1,
- int y1)
+ public void drawHighlightedText(SequenceI seq, int start, int end,
+ int x1, int y1)
{
int avCharWidth = av.getCharWidth(), avCharHeight = av.getCharHeight();
int pady = avCharHeight / 5;
*/
package jalview.commands;
-/*
- * 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
- */
-
import jalview.datamodel.AlignmentI;
import jalview.datamodel.SequenceI;
performEdit(0, null);
}
+ @Override
public int getSize()
{
// We're interested in the number of columns deleted,
*/
package jalview.commands;
-/*
- * 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
- */
-
import jalview.datamodel.AlignmentI;
import jalview.datamodel.SequenceI;
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General License
+ * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General License for more details.
+ * PURPOSE. See the GNU General Public License for more details.
*
- * You should have received a copy of the GNU General License
+ * You should have received a copy of the GNU General Public License
* along with Jalview. If not, see <http://www.gnu.org/licenses/>.
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
{
return !hidden.isVisible(c);
}
+
+ @Override
+ public boolean hasHidden()
+ {
+ return hidden.hasHiddenColumns();
+ }
}
{
return alignment.getSequenceAtAbsoluteIndex(seq);
}
+
+ @Override
+ public boolean hasHidden()
+ {
+ return (hidden.getSize() > 0);
+ }
}
*/
int index = -1;
- private SequenceFeatures sequenceFeatureStore;
+ private SequenceFeaturesI sequenceFeatureStore;
/*
* A cursor holding the approximate current view position to the sequence,
import jalview.schemes.ColourSchemeI;
import java.awt.Color;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
*/
public class SequenceGroup implements AnnotatedCollectionI
{
+ // TODO ideally this event notification functionality should be separated into
+ // a
+ // subclass of ViewportProperties similarly to ViewportRanges. Done here as
+ // quick fix for JAL-2665
+ public static final String SEQ_GROUP_CHANGED = "Sequence group changed";
+
+ protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+ this);
+
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
+ // end of event notification functionality initialisation
+
String groupName;
String description;
if (s != null && !sequences.contains(s))
{
sequences.add(s);
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+ sequences.size() - 1, sequences.size());
}
if (recalc)
synchronized (sequences)
{
sequences.remove(s);
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+ sequences.size() + 1, sequences.size());
if (recalc)
{
*/
public void setStartRes(int i)
{
+ int before = startRes;
startRes = i;
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, startRes);
}
/**
*/
public void setEndRes(int i)
{
+ int before = endRes;
endRes = i;
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, endRes);
}
/**
{
synchronized (sequences)
{
+ int before = sequences.size();
sequences.clear();
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before,
+ sequences.size());
}
}
return false;
}
+ @Override
+ public boolean hasHidden()
+ {
+ return false;
+ }
+
}
{
return alignment.getSequenceAtAbsoluteIndex(seq);
}
+
+ @Override
+ public boolean hasHidden()
+ {
+ return false;
+ }
}
}
Set<String> featureTypes = getFeatureTypes(ontologyTerm);
+ if (featureTypes.isEmpty())
+ {
+ /*
+ * no features of the specified type or any sub-type
+ */
+ return new ArrayList<>();
+ }
+
return getAllFeatures(featureTypes.toArray(new String[featureTypes
.size()]));
}
String translation = null;
String proteinName = "";
String proteinId = null;
- Map<String, String> vals = new Hashtable<String, String>();
+ Map<String, String> vals = new Hashtable<>();
/*
* codon_start 1/2/3 in EMBL corresponds to phase 0/1/2 in CDS
/**
* Returns a list of the transcript features on the sequence whose Parent is
* the gene for the accession id.
+ * <p>
+ * Transcript features are those of type "transcript", or any of its sub-types
+ * in the Sequence Ontology e.g. "mRNA", "processed_transcript". We also
+ * include "NMD_transcript_variant", because this type behaves like a
+ * transcript identifier in Ensembl, although strictly speaking it is not in
+ * the SO.
*
* @param accId
* @param geneSequence
List<SequenceFeature> transcriptFeatures = new ArrayList<SequenceFeature>();
String parentIdentifier = GENE_PREFIX + accId;
- // todo optimise here by transcript type!
+
List<SequenceFeature> sfs = geneSequence.getFeatures()
- .getPositionalFeatures();
+ .getFeaturesByOntology(SequenceOntologyI.TRANSCRIPT);
+ sfs.addAll(geneSequence.getFeatures().getPositionalFeatures(
+ SequenceOntologyI.NMD_TRANSCRIPT_VARIANT));
for (SequenceFeature sf : sfs)
{
- if (isTranscript(sf.getType()))
+ String parent = (String) sf.getValue(PARENT);
+ if (parentIdentifier.equals(parent))
{
- String parent = (String) sf.getValue(PARENT);
- if (parentIdentifier.equals(parent))
- {
- transcriptFeatures.add(sf);
- }
+ transcriptFeatures.add(sf);
}
}
return false;
}
- long start = System.currentTimeMillis();
- // SequenceFeature[] sfs = sourceSequence.getSequenceFeatures();
+// long start = System.currentTimeMillis();
List<SequenceFeature> sfs = sourceSequence.getFeatures()
.getPositionalFeatures();
MapList mapping = getGenomicRangesFromFeatures(sourceSequence,
boolean result = transferFeatures(sfs, targetSequence, mapping,
accessionId);
- System.out.println("transferFeatures (" + (sfs.size()) + " --> "
- + targetSequence.getFeatures().getFeatureCount(true) + ") to "
- + targetSequence.getName() + " took "
- + (System.currentTimeMillis() - start) + "ms");
+// System.out.println("transferFeatures (" + (sfs.size()) + " --> "
+// + targetSequence.getFeatures().getFeatureCount(true) + ") to "
+// + targetSequence.getName() + " took "
+// + (System.currentTimeMillis() - start) + "ms");
return result;
}
private static FTSRestClientI instance = null;
- public static final String PDB_SEARCH_ENDPOINT = "http://www.ebi.ac.uk/pdbe/search/pdb/select?";
+ public static final String PDB_SEARCH_ENDPOINT = "https://www.ebi.ac.uk/pdbe/search/pdb/select?";
protected PDBFTSRestClient()
{
// Java's Transferable for native dnd
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
Transferable t = evt.getTransferable();
- List<String> files = new ArrayList<>();
+ final AlignFrame thisaf = this;
+ final List<String> files = new ArrayList<>();
List<DataSourceType> protocols = new ArrayList<>();
try
}
if (files != null)
{
- try
+ new Thread(new Runnable()
{
- // check to see if any of these files have names matching sequences in
- // the alignment
- SequenceIdMatcher idm = new SequenceIdMatcher(
- viewport.getAlignment().getSequencesArray());
- /**
- * Object[] { String,SequenceI}
- */
- ArrayList<Object[]> filesmatched = new ArrayList<>();
- ArrayList<String> filesnotmatched = new ArrayList<>();
- for (int i = 0; i < files.size(); i++)
+ @Override
+ public void run()
{
- String file = files.get(i).toString();
- String pdbfn = "";
- DataSourceType protocol = FormatAdapter.checkProtocol(file);
- if (protocol == DataSourceType.FILE)
- {
- File fl = new File(file);
- pdbfn = fl.getName();
- }
- else if (protocol == DataSourceType.URL)
- {
- URL url = new URL(file);
- pdbfn = url.getFile();
- }
- if (pdbfn.length() > 0)
+ try
{
- // attempt to find a match in the alignment
- SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
- int l = 0, c = pdbfn.indexOf(".");
- while (mtch == null && c != -1)
+ // check to see if any of these files have names matching sequences
+ // in
+ // the alignment
+ SequenceIdMatcher idm = new SequenceIdMatcher(
+ viewport.getAlignment().getSequencesArray());
+ /**
+ * Object[] { String,SequenceI}
+ */
+ ArrayList<Object[]> filesmatched = new ArrayList<>();
+ ArrayList<String> filesnotmatched = new ArrayList<>();
+ for (int i = 0; i < files.size(); i++)
{
- do
+ String file = files.get(i).toString();
+ String pdbfn = "";
+ DataSourceType protocol = FormatAdapter.checkProtocol(file);
+ if (protocol == DataSourceType.FILE)
{
- l = c;
- } while ((c = pdbfn.indexOf(".", l)) > l);
- if (l > -1)
- {
- pdbfn = pdbfn.substring(0, l);
+ File fl = new File(file);
+ pdbfn = fl.getName();
}
- mtch = idm.findAllIdMatches(pdbfn);
- }
- if (mtch != null)
- {
- FileFormatI type = null;
- try
+ else if (protocol == DataSourceType.URL)
{
- type = new IdentifyFile().identify(file, protocol);
- } catch (Exception ex)
- {
- type = null;
+ URL url = new URL(file);
+ pdbfn = url.getFile();
}
- if (type != null && type.isStructureFile())
+ if (pdbfn.length() > 0)
{
- filesmatched.add(new Object[] { file, protocol, mtch });
- continue;
+ // attempt to find a match in the alignment
+ SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
+ int l = 0, c = pdbfn.indexOf(".");
+ while (mtch == null && c != -1)
+ {
+ do
+ {
+ l = c;
+ } while ((c = pdbfn.indexOf(".", l)) > l);
+ if (l > -1)
+ {
+ pdbfn = pdbfn.substring(0, l);
+ }
+ mtch = idm.findAllIdMatches(pdbfn);
+ }
+ if (mtch != null)
+ {
+ FileFormatI type = null;
+ try
+ {
+ type = new IdentifyFile().identify(file, protocol);
+ } catch (Exception ex)
+ {
+ type = null;
+ }
+ if (type != null && type.isStructureFile())
+ {
+ filesmatched.add(new Object[] { file, protocol, mtch });
+ continue;
+ }
+ }
+ // File wasn't named like one of the sequences or wasn't a PDB
+ // file.
+ filesnotmatched.add(file);
}
}
- // File wasn't named like one of the sequences or wasn't a PDB file.
- filesnotmatched.add(file);
- }
- }
- int assocfiles = 0;
- if (filesmatched.size() > 0)
- {
- if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false)
- || JvOptionPane.showConfirmDialog(this,
- MessageManager.formatMessage(
- "label.automatically_associate_structure_files_with_sequences_same_name",
- new Object[]
- { Integer.valueOf(filesmatched.size())
- .toString() }),
- MessageManager.getString(
- "label.automatically_associate_structure_files_by_name"),
- JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION)
-
- {
- for (Object[] fm : filesmatched)
+ int assocfiles = 0;
+ if (filesmatched.size() > 0)
{
- // try and associate
- // TODO: may want to set a standard ID naming formalism for
- // associating PDB files which have no IDs.
- for (SequenceI toassoc : (SequenceI[]) fm[2])
+ if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false)
+ || JvOptionPane.showConfirmDialog(thisaf,
+ MessageManager.formatMessage(
+ "label.automatically_associate_structure_files_with_sequences_same_name",
+ new Object[]
+ { Integer.valueOf(filesmatched.size())
+ .toString() }),
+ MessageManager.getString(
+ "label.automatically_associate_structure_files_by_name"),
+ JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION)
+
{
- PDBEntry pe = new AssociatePdbFileWithSeq()
- .associatePdbWithSeq((String) fm[0],
- (DataSourceType) fm[1], toassoc, false,
- Desktop.instance);
- if (pe != null)
+ for (Object[] fm : filesmatched)
{
- System.err.println("Associated file : " + ((String) fm[0])
- + " with " + toassoc.getDisplayId(true));
- assocfiles++;
+ // try and associate
+ // TODO: may want to set a standard ID naming formalism for
+ // associating PDB files which have no IDs.
+ for (SequenceI toassoc : (SequenceI[]) fm[2])
+ {
+ PDBEntry pe = new AssociatePdbFileWithSeq()
+ .associatePdbWithSeq((String) fm[0],
+ (DataSourceType) fm[1], toassoc, false,
+ Desktop.instance);
+ if (pe != null)
+ {
+ System.err.println("Associated file : "
+ + ((String) fm[0]) + " with "
+ + toassoc.getDisplayId(true));
+ assocfiles++;
+ }
+ }
+ alignPanel.paintAlignment(true);
}
}
- alignPanel.paintAlignment(true);
}
- }
- }
- if (filesnotmatched.size() > 0)
- {
- if (assocfiles > 0 && (Cache.getDefault(
- "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
- || JvOptionPane.showConfirmDialog(this,
- "<html>" + MessageManager.formatMessage(
- "label.ignore_unmatched_dropped_files_info",
- new Object[]
- { Integer.valueOf(filesnotmatched.size())
- .toString() })
- + "</html>",
- MessageManager.getString(
- "label.ignore_unmatched_dropped_files"),
- JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
- {
- return;
- }
- for (String fn : filesnotmatched)
+ if (filesnotmatched.size() > 0)
+ {
+ if (assocfiles > 0 && (Cache.getDefault(
+ "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
+ || JvOptionPane.showConfirmDialog(thisaf,
+ "<html>" + MessageManager.formatMessage(
+ "label.ignore_unmatched_dropped_files_info",
+ new Object[]
+ { Integer.valueOf(
+ filesnotmatched.size())
+ .toString() })
+ + "</html>",
+ MessageManager.getString(
+ "label.ignore_unmatched_dropped_files"),
+ JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
+ {
+ return;
+ }
+ for (String fn : filesnotmatched)
+ {
+ loadJalviewDataFile(fn, null, null, null);
+ }
+
+ }
+ } catch (Exception ex)
{
- loadJalviewDataFile(fn, null, null, null);
+ ex.printStackTrace();
}
-
}
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
+ }).start();
}
}
new Dimension(10, av.getCharHeight() + fm.getDescent()));
idSpaceFillerPanel1.setPreferredSize(
new Dimension(10, av.getCharHeight() + fm.getDescent()));
-
+ idwidthAdjuster.invalidate();
+ scalePanelHolder.invalidate();
getIdPanel().getIdCanvas().gg = null;
getSeqPanel().seqCanvas.img = null;
getAnnotationPanel().adjustPanelHeight();
getIdPanel().getIdCanvas().setPreferredSize(d);
hscrollFillerPanel.setPreferredSize(d);
- if (this.alignFrame.getSplitViewContainer() != null)
- {
- ((SplitFrame) this.alignFrame.getSplitViewContainer()).adjustLayout();
- }
-
repaint();
}
* single graphics context), then reset to (0, scale height)
*/
alignmentGraphics.translate(alignmentGraphicsOffset, scaleHeight);
- getSeqPanel().seqCanvas.drawPanel(alignmentGraphics, startRes, endRes,
- startSeq, endSeq, 0);
+ getSeqPanel().seqCanvas.drawPanelForPrinting(alignmentGraphics, startRes,
+ endRes, startSeq, endSeq);
alignmentGraphics.translate(-alignmentGraphicsOffset, 0);
if (av.isShowAnnotation() && (endSeq == alignmentHeight))
pg.translate(idWidth, 0);
- getSeqPanel().seqCanvas.drawWrappedPanel(pg, pwidth - idWidth,
+ getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(pg, pwidth - idWidth,
totalHeight, 0);
if ((pi * pheight) < totalHeight)
{
continue;
}
-
- if (useOriginalColours.isSelected())
- {
- sg.setColourScheme(new AnnotationColourGradient(currentAnn,
- sg.getColourScheme(), selectedThresholdOption));
- ((AnnotationColourGradient) sg.cs)
- .setSeqAssociated(seqAssociated.isSelected());
- }
- else
- {
- sg.setColourScheme(new AnnotationColourGradient(currentAnn,
- minColour.getBackground(), maxColour.getBackground(),
- selectedThresholdOption));
- ((AnnotationColourGradient) sg.cs)
- .setSeqAssociated(seqAssociated.isSelected());
- }
+ sg.setColourScheme(
+ acg.getInstance(sg, ap.av.getHiddenRepSequences()));
}
}
return false;
String linkedTitle = MessageManager
.getString("label.linked_view_title");
Desktop.addInternalFrame(sf, linkedTitle, -1, -1);
- sf.adjustDivider();
+ sf.adjustInitialLayout();
// finally add the top, then bottom frame to the view list
xrefViews.add(dna ? copyThis.alignPanel : newFrame.alignPanel);
public void endDraggingFrame(JComponent f)
{
delegate.endDraggingFrame(f);
+ desktop.repaint();
}
@Override
public void endResizingFrame(JComponent f)
{
delegate.endResizingFrame(f);
+ desktop.repaint();
}
@Override
boolean showjconsole = jalview.bin.Cache.getDefault("SHOW_JAVA_CONSOLE",
false);
desktop = new MyDesktopPane(selmemusage);
- if (Platform.isAMac())
- {
- desktop.setDoubleBuffered(false);
- }
showMemusage.setSelected(selmemusage);
desktop.setBackground(Color.white);
getContentPane().setLayout(new BorderLayout());
// This line prevents Windows Look&Feel resizing all new windows to maximum
// if previous window was maximised
desktop.setDesktopManager(
- new MyDesktopManager(new DefaultDesktopManager()));
+ new MyDesktopManager(
+ (Platform.isWindows() ? new DefaultDesktopManager()
+ : desktop.getDesktopManager())));
Rectangle dims = getLastKnownDimensions("");
if (dims != null)
frame.setResizable(resizable);
frame.setMaximizable(resizable);
frame.setIconifiable(resizable);
- if (Platform.isAMac())
- {
- frame.setIconifiable(false);
- frame.setFrameIcon(null);
- // frame.setDesktopIcon(null);
- frame.setDoubleBuffered(false);
- }
+
if (frame.getX() < 1 && frame.getY() < 1)
{
frame.setLocation(xOffset * openFrameCount,
// Java's Transferable for native dnd
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
Transferable t = evt.getTransferable();
- List<String> files = new ArrayList<String>();
- List<DataSourceType> protocols = new ArrayList<DataSourceType>();
+ List<String> files = new ArrayList<>();
+ List<DataSourceType> protocols = new ArrayList<>();
try
{
JPanel progressPanel;
- ArrayList<JPanel> fileLoadingPanels = new ArrayList<JPanel>();
+ ArrayList<JPanel> fileLoadingPanels = new ArrayList<>();
public void startLoading(final String fileName)
{
// TODO: verify that frames are recoverable when in headless mode
return null;
}
- List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>();
+ List<AlignmentPanel> aps = new ArrayList<>();
AlignFrame[] frames = getAlignFrames();
if (frames == null)
{
*/
public static AlignmentViewport[] getViewports(String sequenceSetId)
{
- List<AlignmentViewport> viewp = new ArrayList<AlignmentViewport>();
+ List<AlignmentViewport> viewp = new ArrayList<>();
if (desktop != null)
{
AlignFrame[] frames = Desktop.getAlignFrames();
// SEQUENCE_ID which is not the default EMBL_EBI link
ListIterator<String> li = links.listIterator();
boolean check = false;
- List<JLabel> urls = new ArrayList<JLabel>();
+ List<JLabel> urls = new ArrayList<>();
while (li.hasNext())
{
String link = li.next();
Thread worker = new Thread(this);
worker.start();
}
+ repaint();
}
public boolean isShowMemoryUsage()
{
return null;
}
- List<AlignFrame> avp = new ArrayList<AlignFrame>();
+ List<AlignFrame> avp = new ArrayList<>();
// REVERSE ORDER
for (int i = frames.length - 1; i > -1; i--)
{
{
return null;
}
- List<GStructureViewer> avp = new ArrayList<GStructureViewer>();
+ List<GStructureViewer> avp = new ArrayList<>();
// REVERSE ORDER
for (int i = frames.length - 1; i > -1; i--)
{
{
if (progressBars == null)
{
- progressBars = new Hashtable<Long, JPanel>();
- progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
+ progressBars = new Hashtable<>();
+ progressBarHandlers = new Hashtable<>();
}
if (progressBars.get(new Long(id)) != null)
final String grp = group;
final JCheckBox check = new JCheckBox(group, visible);
check.setFont(new Font("Serif", Font.BOLD, 12));
+ check.setToolTipText(group);
check.addItemListener(new ItemListener()
{
@Override
ap.fontChanged();
/*
- * adjust other half of split frame if any, if either same
- * font, or proportionate scaling, is selected
+ * adjust other half of split frame if present, whether or not same font or
+ * scale to cDNA is selected, because a font change may affect character
+ * width, and this is kept the same in both panels
*/
- if (fontAsCdna.isEnabled())
+ if (fontAsCdna.isVisible())
{
if (fontAsCdna.isSelected())
{
- /*
- * copy the font
- */
ap.av.getCodingComplement().setFont(newFont, true);
}
- /*
- * adjust layout for font change / reset / sizing
- */
SplitFrame splitFrame = (SplitFrame) ap.alignFrame
.getSplitViewContainer();
splitFrame.adjustLayout();
jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
af = loadJalviewAlign(jprovider);
+ af.setMenusForViewport();
} catch (MalformedURLException e)
{
package jalview.gui;
import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
import jalview.renderer.OverviewRenderer;
+import jalview.renderer.OverviewResColourFinder;
import jalview.viewmodel.OverviewDimensions;
import java.awt.Color;
private volatile boolean updaterunning = false;
+ private boolean dispose = false;
+
private BufferedImage miniMe;
private BufferedImage lastMiniMe = null;
private AlignViewportI av;
+ private OverviewResColourFinder cf;
+
+ private ProgressPanel progressPanel;
+
public OverviewCanvas(OverviewDimensions overviewDims,
- AlignViewportI alignvp)
+ AlignViewportI alignvp, ProgressPanel pp)
{
od = overviewDims;
av = alignvp;
+ progressPanel = pp;
sr = new SequenceRenderer(av);
sr.renderGaps = false;
- sr.forOverview = true;
fr = new jalview.renderer.seqfeatures.FeatureRenderer(av);
+
+ boolean useLegacy = Cache.getDefault(Preferences.USE_LEGACY_GAP, false);
+ Color gapCol = Cache.getDefaultColour(Preferences.GAP_COLOUR,
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
+ Color hiddenCol = Cache.getDefaultColour(Preferences.HIDDEN_COLOUR,
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
+ cf = new OverviewResColourFinder(useLegacy, gapCol, hiddenCol);
+
+ setSize(od.getWidth(), od.getHeight());
}
/**
setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
- or = new OverviewRenderer(sr, fr, od);
+ or = new OverviewRenderer(fr, od, av.getAlignment(),
+ av.getResidueShading(), cf);
+
+ or.addPropertyChangeListener(progressPanel);
+
miniMe = or.draw(od.getRows(av.getAlignment()),
od.getColumns(av.getAlignment()));
}
System.gc();
+ or.removePropertyChangeListener(progressPanel);
+ or = null;
if (restart)
{
restart = false;
- draw(showSequenceFeatures, showAnnotation, transferRenderer);
+ if (!dispose)
+ {
+ draw(showSequenceFeatures, showAnnotation, transferRenderer);
+ }
}
else
{
}
else if (lastMiniMe != null)
{
- g.drawImage(lastMiniMe, 0, 0, this);
- if (lastMiniMe != miniMe)
+ // is this a resize?
+ if ((getWidth() > 0) && (getHeight() > 0)
+ && ((getWidth() != od.getWidth())
+ || (getHeight() != od.getHeight())))
{
- g.setColor(TRANS_GREY);
- g.fillRect(0, 0, getWidth(), getHeight());
+ // if there is annotation, scale the alignment and annotation separately
+ if (od.getGraphHeight() > 0)
+ {
+ BufferedImage topImage = lastMiniMe.getSubimage(0, 0,
+ od.getWidth(), od.getSequencesHeight());
+ BufferedImage bottomImage = lastMiniMe.getSubimage(0,
+ od.getSequencesHeight(), od.getWidth(),
+ od.getGraphHeight());
+
+ // must be done at this point as we rely on using old width/height
+ // above, and new width/height below
+ od.setWidth(getWidth());
+ od.setHeight(getHeight());
+
+ // stick the images back together so lastMiniMe is consistent in the
+ // event of a repaint - BUT probably not thread safe
+ lastMiniMe = new BufferedImage(od.getWidth(), od.getHeight(),
+ BufferedImage.TYPE_INT_RGB);
+ Graphics lg = lastMiniMe.getGraphics();
+ lg.drawImage(topImage, 0, 0, od.getWidth(),
+ od.getSequencesHeight(), null);
+ lg.drawImage(bottomImage, 0, od.getSequencesHeight(),
+ od.getWidth(), od.getGraphHeight(), this);
+ lg.dispose();
+ }
+ else
+ {
+ od.setWidth(getWidth());
+ od.setHeight(getHeight());
+ }
+
+ // scale lastMiniMe to the new size
+ g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
+
+ // make sure the box is in the right place
+ od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
+ else // not a resize
+ {
+ // fall back to normal behaviour
+ g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
}
}
+ // draw the box
g.setColor(Color.red);
od.drawBox(g);
}
+ public void dispose()
+ {
+ dispose = true;
+ synchronized (this)
+ {
+ restart = true;
+ if (or != null)
+ {
+ or.setRedraw(true);
+ }
+ }
+ }
}
*/
package jalview.gui;
+import jalview.bin.Cache;
+import jalview.renderer.OverviewRenderer;
import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.viewmodel.OverviewDimensions;
private boolean draggingBox = false;
+ private ProgressPanel progressPanel;
+
/**
* Creates a new OverviewPanel object.
*
this.av = alPanel.av;
this.ap = alPanel;
- od = new OverviewDimensionsShowHidden(av.getRanges(),
+ showHidden = Cache.getDefault(Preferences.SHOW_OV_HIDDEN_AT_START,
+ true);
+ if (showHidden)
+ {
+ od = new OverviewDimensionsShowHidden(av.getRanges(),
(av.isShowAnnotation()
&& av.getAlignmentConservationAnnotation() != null));
+ }
+ else
+ {
+ od = new OverviewDimensionsHideHidden(av.getRanges(),
+ (av.isShowAnnotation()
+ && av.getAlignmentConservationAnnotation() != null));
+ }
- setSize(od.getWidth(), od.getHeight());
-
- oviewCanvas = new OverviewCanvas(od, av);
setLayout(new BorderLayout());
+ progressPanel = new ProgressPanel(OverviewRenderer.UPDATE,
+ MessageManager.getString("label.oview_calc"), getWidth());
+ this.add(progressPanel, BorderLayout.SOUTH);
+ oviewCanvas = new OverviewCanvas(od, av, progressPanel);
+
add(oviewCanvas, BorderLayout.CENTER);
av.getRanges().addPropertyChangeListener(this);
+ // without this the overview window does not size to fit the overview canvas
+ setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
+
addComponentListener(new ComponentAdapter()
{
@Override
public void componentResized(ComponentEvent evt)
{
- if ((getWidth() != od.getWidth())
- || (getHeight() != (od.getHeight())))
+ // Resize is called on the initial display of the overview.
+ // This code adjusts sizes to account for the progress bar if it has not
+ // already been accounted for, which triggers another resize call for
+ // the correct sizing, at which point the overview image is updated.
+ // (This avoids a double recalculation of the image.)
+ if (getWidth() == od.getWidth() && getHeight() == od.getHeight()
+ + progressPanel.getHeight())
{
updateOverviewImage();
- setBoxPosition();
+ }
+ else
+ {
+ if ((getWidth() > 0) && (getHeight() > 0))
+ {
+ od.setWidth(getWidth());
+ od.setHeight(getHeight() - progressPanel.getHeight());
+ }
+
+ setPreferredSize(new Dimension(od.getWidth(),
+ od.getHeight() + progressPanel.getHeight()));
}
}
+
});
addMouseMotionListener(new MouseMotionAdapter()
}
}
else
- // if (!av.getWrapAlignment())
{
+ // don't do anything if the mouse press is in the overview's box
+ // (wait to see if it's a drag instead)
+ // otherwise update the viewport
if (!od.isPositionInBox(evt.getX(), evt.getY()))
{
- // don't do anything if the mouse press is in the overview's box
- // (wait to see if it's a drag instead)
- // otherwise update the viewport
+ draggingBox = false;
od.updateViewportFromMouse(evt.getX(), evt.getY(),
av.getAlignment().getHiddenSequences(),
av.getAlignment().getHiddenColumns());
}
@Override
- public void mouseReleased(MouseEvent evt)
- {
- if (draggingBox)
- {
- draggingBox = false;
- }
- }
-
- @Override
public void mouseClicked(MouseEvent evt)
{
if (SwingUtilities.isRightMouseButton(evt))
}
}
});
-
- updateOverviewImage();
}
/*
if ((getWidth() > 0) && (getHeight() > 0))
{
od.setWidth(getWidth());
- od.setHeight(getHeight());
+ od.setHeight(getHeight() - progressPanel.getHeight());
}
-
- setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
+
+ setPreferredSize(new Dimension(od.getWidth(),
+ od.getHeight() + progressPanel.getHeight()));
if (oviewCanvas.restartDraw())
{
Thread thread = new Thread(this);
thread.start();
repaint();
+
+
}
@Override
public void run()
{
- oviewCanvas.draw(av.isShowSequenceFeatures(),
- (av.isShowAnnotation()
- && av.getAlignmentConservationAnnotation() != null),
- ap.getSeqPanel().seqCanvas.getFeatureRenderer());
- setBoxPosition();
+ if (oviewCanvas != null)
+ {
+ oviewCanvas.draw(av.isShowSequenceFeatures(),
+ (av.isShowAnnotation()
+ && av.getAlignmentConservationAnnotation() != null),
+ ap.getSeqPanel().seqCanvas.getFeatureRenderer());
+ setBoxPosition();
+ }
}
/**
*/
private void setBoxPosition()
{
- od.setBoxPosition(av.getAlignment().getHiddenSequences(),
- av.getAlignment().getHiddenColumns());
- repaint();
+ if (od != null)
+ {
+ od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ repaint();
+ }
}
@Override
try
{
av.getRanges().removePropertyChangeListener(this);
+ oviewCanvas.dispose();
} finally
{
+ progressPanel = null;
av = null;
oviewCanvas = null;
ap = null;
buildGroupURLMenu(sg, groupLinks);
}
// Add a 'show all structures' for the current selection
- Hashtable<String, PDBEntry> pdbe = new Hashtable<String, PDBEntry>(),
- reppdb = new Hashtable<String, PDBEntry>();
+ Hashtable<String, PDBEntry> pdbe = new Hashtable<>(), reppdb = new Hashtable<>();
+
SequenceI sqass = null;
for (SequenceI sq : ap.av.getSequenceSelection())
{
void addFeatureLinks(final SequenceI seq, List<String> links)
{
JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
- Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+ Map<String, List<String>> linkset = new LinkedHashMap<>();
for (String link : links)
{
* the insertion order, which is the order of the annotations on the
* alignment.
*/
- Map<String, List<List<String>>> shownTypes = new LinkedHashMap<String, List<List<String>>>();
- Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<String, List<List<String>>>();
+ Map<String, List<List<String>>> shownTypes = new LinkedHashMap<>();
+ Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<>();
AlignmentAnnotationUtils.getShownHiddenTypes(shownTypes, hiddenTypes,
AlignmentAnnotationUtils.asList(annotations), forSequences);
SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
String[][] idandseqs = GroupUrlLink.formStrings(seqs);
- Hashtable<String, Object[]> commonDbrefs = new Hashtable<String, Object[]>();
+ Hashtable<String, Object[]> commonDbrefs = new Hashtable<>();
for (int sq = 0; sq < seqs.length; sq++)
{
* Temporary store to hold distinct calcId / type pairs for the tooltip.
* Using TreeMap means calcIds are shown in alphabetical order.
*/
- SortedMap<String, String> tipEntries = new TreeMap<String, String>();
- final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
+ SortedMap<String, String> tipEntries = new TreeMap<>();
+ final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
AlignmentI al = this.ap.av.getAlignment();
AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries,
candidates, al);
void refresh()
{
ap.updateAnnotation();
- ap.paintAlignment(true);
+ // removed paintAlignment(true) here:
+ // updateAnnotation calls paintAlignment already, so don't need to call
+ // again
PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
}
return;
}
- List<SequenceI> seqs = new ArrayList<SequenceI>();
- List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+ List<SequenceI> seqs = new ArrayList<>();
+ List<SequenceFeature> features = new ArrayList<>();
/*
* assemble dataset sequences, and template new sequence features,
public static final String SHOW_OCCUPANCY = "SHOW_OCCUPANCY";
+ public static final String SHOW_OV_HIDDEN_AT_START = "SHOW_OV_HIDDEN_AT_START";
+
+ public static final String USE_LEGACY_GAP = "USE_LEGACY_GAP";
+
+ public static final String GAP_COLOUR = "GAP_COLOUR";
+
+ public static final String HIDDEN_COLOUR = "HIDDEN_COLOUR";
+
private static final int MIN_FONT_SIZE = 1;
private static final int MAX_FONT_SIZE = 30;
* .properties file as '|' separated strings
*/
- groupURLLinks = new ArrayList<String>();
+ groupURLLinks = new ArrayList<>();
}
JInternalFrame frame;
Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX", Color.red));
/*
+ * Set overview panel defaults
+ */
+ gapColour.setBackground(
+ Cache.getDefaultColour(GAP_COLOUR,
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP));
+ hiddenColour.setBackground(
+ Cache.getDefaultColour(HIDDEN_COLOUR,
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN));
+ useLegacyGap.setSelected(Cache.getDefault(USE_LEGACY_GAP, false));
+ gapLabel.setEnabled(!useLegacyGap.isSelected());
+ gapColour.setEnabled(!useLegacyGap.isSelected());
+ showHiddenAtStart
+ .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, true));
+
+ /*
* Set Structure tab defaults.
*/
final boolean structSelected = Cache.getDefault(STRUCT_FROM_PDB, false);
maxColour.getBackground());
/*
+ * Save Overview settings
+ */
+ Cache.setColourProperty(GAP_COLOUR, gapColour.getBackground());
+ Cache.setColourProperty(HIDDEN_COLOUR, hiddenColour.getBackground());
+ Cache.applicationProperties.setProperty(USE_LEGACY_GAP,
+ Boolean.toString(useLegacyGap.isSelected()));
+ Cache.applicationProperties.setProperty(SHOW_OV_HIDDEN_AT_START,
+ Boolean.toString(showHiddenAtStart.isSelected()));
+
+ /*
* Save Structure settings
*/
Cache.applicationProperties.setProperty(ADD_TEMPFACT_ANN,
}
@Override
+ public void gapColour_actionPerformed(JPanel gap)
+ {
+ if (!useLegacyGap.isSelected())
+ {
+ Color col = JColorChooser.showDialog(this,
+ MessageManager.getString("label.select_gap_colour"),
+ gapColour.getBackground());
+ if (col != null)
+ {
+ gap.setBackground(col);
+ }
+ gap.repaint();
+ }
+ }
+
+ @Override
+ public void hiddenColour_actionPerformed(JPanel hidden)
+ {
+ Color col = JColorChooser.showDialog(this,
+ MessageManager.getString("label.select_hidden_colour"),
+ hiddenColour.getBackground());
+ if (col != null)
+ {
+ hidden.setBackground(col);
+ }
+ hidden.repaint();
+ }
+
+ @Override
+ protected void useLegacyGaps_actionPerformed(ActionEvent e)
+ {
+ boolean enabled = useLegacyGap.isSelected();
+ if (enabled)
+ {
+ gapColour.setBackground(
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_LEGACY_GAP);
+ }
+ else
+ {
+ gapColour.setBackground(
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP);
+ }
+ gapColour.setEnabled(!enabled);
+ gapLabel.setEnabled(!enabled);
+ }
+
+ @Override
+ protected void resetOvDefaults_actionPerformed(ActionEvent e)
+ {
+ useLegacyGap.setSelected(false);
+ useLegacyGaps_actionPerformed(null);
+ showHiddenAtStart.setSelected(true);
+ hiddenColour.setBackground(
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_HIDDEN);
+ }
+
+ @Override
protected void userIdWidth_actionPerformed()
{
try
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import jalview.api.RendererListenerI;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.beans.PropertyChangeEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * A class to manage a panel containing a label and progress bar updated by an
+ * event firing
+ *
+ * @author kmourao
+ *
+ */
+public class ProgressPanel extends JPanel implements RendererListenerI
+{
+ // max value of progress bar: values expected to be %s
+ private final int MAXVALUE = 100;
+
+ private final String VISIBLE = "VISIBLE";
+
+ private final String INVISIBLE = "INVISIBLE";
+
+ // name of event property which updates the progress bar
+ private String eventName;
+
+ private JProgressBar progressBar;
+
+ private JLabel progressLabel;
+
+ private JPanel labelPanel = new JPanel();
+
+ private CardLayout labelLayout = new CardLayout();
+
+ private JPanel barPanel = new JPanel();
+
+ private CardLayout barLayout = new CardLayout();
+
+ /**
+ * Construct a JPanel containing a progress bar and a label.
+ *
+ * @param eventPropertyName
+ * The name of the event property to update the progress bar
+ * @param label
+ * The label to place next to the progress bar
+ */
+ public ProgressPanel(String eventPropertyName, String label, int maxwidth)
+ {
+ super(new BorderLayout(10, 0));
+ setBorder(new EmptyBorder(0, 3, 0, 0));
+
+ eventName = eventPropertyName;
+ String labelText = label;
+
+ final int w = maxwidth;
+
+ progressBar = new JProgressBar()
+ {
+ @Override
+ public Dimension getMaximumSize()
+ {
+ return new Dimension(w, 1);
+ }
+ };
+ progressBar.setMinimum(0);
+ progressBar.setPreferredSize(progressBar.getMaximumSize());
+ progressLabel = new JLabel(labelText);
+ progressLabel.setFont(new java.awt.Font("Verdana", 0, 11));
+
+ // Use a CardLayout to stop the progress bar panel moving around when
+ // changing visibility
+ labelPanel.setLayout(labelLayout);
+ barPanel.setLayout(barLayout);
+
+ labelPanel.add(progressLabel, VISIBLE);
+ labelPanel.add(new JPanel(), INVISIBLE);
+ barPanel.add(progressBar, VISIBLE);
+ barPanel.add(new JPanel(), INVISIBLE);
+
+ labelLayout.show(labelPanel, VISIBLE);
+ barLayout.show(barPanel, VISIBLE);
+
+ add(labelPanel, BorderLayout.WEST);
+ add(barPanel, BorderLayout.CENTER);
+ add(new JLabel(" "), BorderLayout.EAST);
+
+ setBorder(BorderFactory.createLineBorder(Color.black));
+ // setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
+ }
+
+ @Override
+ /**
+ * Update the progress bar in response to the event. Expects the value
+ * supplied by the event to be in the range 0-100 i.e. a percentage
+ */
+ public void propertyChange(PropertyChangeEvent evt)
+ {
+ if (evt.getPropertyName().equals(eventName))
+ {
+ int progress = (int) evt.getNewValue();
+ progressBar.setValue(progress);
+
+ // switch progress bar to visible if it is not visible and current
+ // progress is less than MAXVALUE
+ // switch progress bar to invisible if it is visible and we reached
+ // MAXVALUE
+ if (progress < MAXVALUE && !progressBar.isVisible())
+ {
+ labelLayout.show(labelPanel, VISIBLE);
+ barLayout.show(barPanel, VISIBLE);
+ }
+ if (progress >= MAXVALUE)
+ {
+ labelLayout.show(labelPanel, INVISIBLE);
+ barLayout.show(barPanel, INVISIBLE);
+ }
+ }
+ }
+}
import jalview.viewmodel.ViewportListenerI;
import jalview.viewmodel.ViewportRanges;
+import java.awt.AlphaComposite; // ok
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
final FeatureRenderer fr;
- final SequenceRenderer sr;
+ final SequenceRenderer seqRdr; //ok
BufferedImage img;
{
this.av = ap.av;
fr = new FeatureRenderer(ap);
- sr = new SequenceRenderer(av);
+ seqRdr = new SequenceRenderer(av); //ok
setLayout(new BorderLayout());
PaintRefresher.Register(this, av.getSequenceSetId());
setBackground(Color.white);
public SequenceRenderer getSequenceRenderer()
{
- return sr;
+ return seqRdr; //ok
}
public FeatureRenderer getFeatureRenderer()
}
}
+ //ok
/**
* Does a fast paint of an alignment in response to a scroll. Most of the
* visible region is simply copied and shifted, and then any newly visible
*/
public void fastPaint(int horizontal, int vertical)
{
- if (fastpainting || gg == null)
+ if (fastpainting || gg == null || img == null) //ok
{
return;
}
{
int charHeight = av.getCharHeight();
int charWidth = av.getCharWidth();
-
+
ViewportRanges ranges = av.getRanges();
int startRes = ranges.getStartRes();
int endRes = ranges.getEndRes();
int transX = 0;
int transY = 0;
- gg.copyArea(horizontal * charWidth, vertical * charHeight, imgWidth,
- imgHeight, -horizontal * charWidth, -vertical * charHeight);
+ gg.copyArea(horizontal * charWidth, vertical * charHeight,
+ img.getWidth(), img.getHeight(), -horizontal * charWidth,
+ -vertical * charHeight);
- if (horizontal > 0) // scrollbar pulled right, image to the left
- {
- transX = (endRes - startRes - horizontal) * charWidth;
- startRes = endRes - horizontal;
+ if (horizontal > 0) // scrollbar pulled right, image to the left
+ {
+ transX = (endRes - startRes - horizontal) * charWidth;
+ startRes = endRes - horizontal;
+ }
+ else if (horizontal < 0)
+ {
+ endRes = startRes - horizontal;
+ }
+ else if (vertical > 0) // scroll down
+ {
+ startSeq = endSeq - vertical;
+
+ if (startSeq < ranges.getStartSeq())
+ { // ie scrolling too fast, more than a page at a time
+ startSeq = ranges.getStartSeq();
}
- else if (horizontal < 0)
+ else
{
- endRes = startRes - horizontal;
+ transY = img.getHeight() - ((vertical + 1) * charHeight);
}
- else if (vertical > 0) // scroll down
- {
- startSeq = endSeq - vertical;
+ }
+ else if (vertical < 0)
+ {
+ endSeq = startSeq - vertical;
- if (startSeq < ranges.getStartSeq())
- { // ie scrolling too fast, more than a page at a time
- startSeq = ranges.getStartSeq();
- }
- else
- {
- transY = imgHeight - ((vertical + 1) * charHeight);
- }
- }
- else if (vertical < 0)
+ if (endSeq > ranges.getEndSeq())
{
- endSeq = startSeq - vertical;
-
- if (endSeq > ranges.getEndSeq())
- {
- endSeq = ranges.getEndSeq();
- }
+ endSeq = ranges.getEndSeq();
}
+ }
- gg.translate(transX, transY);
- drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
- gg.translate(-transX, -transY);
+ gg.translate(transX, transY);
+ drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
+ gg.translate(-transX, -transY);
- repaint();
+ repaint();
} finally
{
fastpainting = false;
}
}
+ //ok
+ //ok
@Override
public void paintComponent(Graphics g)
{
+ super.paintComponent(g);
+
int charHeight = av.getCharHeight();
int charWidth = av.getCharWidth();
- BufferedImage lcimg = img; // take reference since other threads may null
- // img and call later.
- super.paintComponent(g);
- if (lcimg != null && (fastPaint
+ ViewportRanges ranges = av.getRanges();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ width -= (width % charWidth);
+ height -= (height % charHeight);
+
+ // selectImage is the selection group outline image
+ BufferedImage selectImage = drawSelectionGroup(
+ ranges.getStartRes(), ranges.getEndRes(),
+ ranges.getStartSeq(), ranges.getEndSeq());
+
+ if ((img != null) && (fastPaint
|| (getVisibleRect().width != g.getClipBounds().width)
|| (getVisibleRect().height != g.getClipBounds().height)))
{
+ BufferedImage lcimg = buildLocalImage(selectImage);
g.drawImage(lcimg, 0, 0, this);
fastPaint = false;
- return;
}
+ else if ((width > 0) && (height > 0))
+ {
+ // img is a cached version of the last view we drew, if any
+ // if we have no img or the size has changed, make a new one
+ if (img == null || width != img.getWidth()
+ || height != img.getHeight())
+ {
+ img = setupImage();
+ if (img == null)
+ {
+ return;
+ }
+ gg = (Graphics2D) img.getGraphics();
+ gg.setFont(av.getFont());
+ }
- // this draws the whole of the alignment
- imgWidth = getWidth();
- imgHeight = getHeight();
+ if (av.antiAlias)
+ {
+ gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ }
- imgWidth -= (imgWidth % charWidth);
- imgHeight -= (imgHeight % charHeight);
+ gg.setColor(Color.white);
+ gg.fillRect(0, 0, img.getWidth(), img.getHeight());
+
+ if (av.getWrapAlignment())
+ {
+ drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
+ }
+ else
+ {
+ drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
+ ranges.getStartSeq(), ranges.getEndSeq(), 0);
+ }
+
+ // lcimg is a local *copy* of img which we'll draw selectImage on top of
+ BufferedImage lcimg = buildLocalImage(selectImage);
+ g.drawImage(lcimg, 0, 0, this);
+ }
+ }
+//ok
+
+ /**
+ * Draw an alignment panel for printing
+ *
+ * @param g1
+ * Graphics object to draw with
+ * @param startRes
+ * start residue of print area
+ * @param endRes
+ * end residue of print area
+ * @param startSeq
+ * start sequence of print area
+ * @param endSeq
+ * end sequence of print area
+ */
+ public void drawPanelForPrinting(Graphics g1, int startRes, int endRes,
+ int startSeq, int endSeq)
+ {
+ drawPanel(g1, startRes, endRes, startSeq, endSeq, 0);
- if ((imgWidth < 1) || (imgHeight < 1))
+ BufferedImage selectImage = drawSelectionGroup(startRes, endRes,
+ startSeq, endSeq);
+ if (selectImage != null)
{
- return;
+ ((Graphics2D) g1).setComposite(AlphaComposite
+ .getInstance(AlphaComposite.SRC_OVER));
+ g1.drawImage(selectImage, 0, 0, this);
}
+ }
+
+ /**
+ * Draw a wrapped alignment panel for printing
+ *
+ * @param g
+ * Graphics object to draw with
+ * @param canvasWidth
+ * width of drawing area
+ * @param canvasHeight
+ * height of drawing area
+ * @param startRes
+ * start residue of print area
+ */
+ public void drawWrappedPanelForPrinting(Graphics g, int canvasWidth,
+ int canvasHeight, int startRes)
+ {
+ SequenceGroup group = av.getSelectionGroup();
+
+ drawWrappedPanel(g, canvasWidth, canvasHeight, startRes);
- if (lcimg == null || imgWidth != lcimg.getWidth()
- || imgHeight != lcimg.getHeight())
+ if (group != null)
{
+ BufferedImage selectImage = null;
try
{
- lcimg = img = new BufferedImage(imgWidth, imgHeight,
- BufferedImage.TYPE_INT_RGB);
- gg = (Graphics2D) img.getGraphics();
- gg.setFont(av.getFont());
+ selectImage = new BufferedImage(canvasWidth, canvasHeight,
+ BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
} catch (OutOfMemoryError er)
{
System.gc();
- System.err.println("SeqCanvas OutOfMemory Redraw Error.\n" + er);
- new OOMWarning("Creating alignment image for display", er);
-
- return;
+ System.err.println("Print image OutOfMemory Error.\n" + er);
+ new OOMWarning("Creating wrapped alignment image for printing", er);
+ }
+ if (selectImage != null)
+ {
+ Graphics2D g2 = selectImage.createGraphics();
+ setupSelectionGroup(g2, selectImage);
+ drawWrappedSelection(g2, group, canvasWidth, canvasHeight,
+ startRes);
+
+ g2.setComposite(
+ AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+ g.drawImage(selectImage, 0, 0, this);
+ g2.dispose();
}
}
+ }
- if (av.antiAlias)
+ /*
+ * Make a local image by combining the cached image img
+ * with any selection
+ */
+ private BufferedImage buildLocalImage(BufferedImage selectImage)
+ {
+ // clone the cached image
+ BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
+ img.getType());
+ Graphics2D g2d = lcimg.createGraphics();
+ g2d.drawImage(img, 0, 0, null);
+
+ // overlay selection group on lcimg
+ if (selectImage != null)
{
- gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setComposite(
+ AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+ g2d.drawImage(selectImage, 0, 0, this);
}
+ g2d.dispose();
- gg.setColor(Color.white);
- gg.fillRect(0, 0, imgWidth, imgHeight);
+ return lcimg;
+ }
- ViewportRanges ranges = av.getRanges();
- if (av.getWrapAlignment())
+ /*
+ * Set up a buffered image of the correct height and size for the sequence canvas
+ */
+ private BufferedImage setupImage()
+ {
+ BufferedImage lcimg = null;
+
+ int charWidth = av.getCharWidth();
+ int charHeight = av.getCharHeight();
+
+ int width = getWidth();
+ int height = getHeight();
+
+ width -= (width % charWidth);
+ height -= (height % charHeight);
+
+ if ((width < 1) || (height < 1))
{
- drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
+ return null;
}
- else
+
+ try
{
- drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
- ranges.getStartSeq(), ranges.getEndSeq(), 0);
- }
+ lcimg = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
+ } catch (OutOfMemoryError er)
+ {
+ System.gc();
+ System.err.println(
+ "Group image OutOfMemory Redraw Error.\n" + er);
+ new OOMWarning("Creating alignment image for display", er);
- g.drawImage(lcimg, 0, 0, this);
+ return null;
+ }
+ return lcimg;
}
/**
*/
wrappedRepeatHeightPx = wrappedSpaceAboveAlignment;
// add sequences
- wrappedRepeatHeightPx += av.getRanges().getViewportHeight() * charHeight;
+ wrappedRepeatHeightPx += av.getRanges().getViewportHeight()
+ * charHeight;
// add annotations panel height if shown
wrappedRepeatHeightPx += getAnnotationHeight();
* this is just canvas width less scale left and right (if shown),
* as a whole multiple of character widths
*/
- int wrappedWidthInResidues = (canvasWidth - labelWidthEast - labelWidthWest)
- / charWidth;
+ int wrappedWidthInResidues = (canvasWidth - labelWidthEast
+ - labelWidthWest) / charWidth;
/*
* number of visible widths (the last one may be part height),
* @param endColumn
* @param canvasHeight
*/
- protected void drawWrappedWidth(Graphics g, int ypos,
- int startColumn, int endColumn, int canvasHeight)
+ protected void drawWrappedWidth(Graphics g, int ypos, int startColumn,
+ int endColumn, int canvasHeight)
{
int charHeight = av.getCharHeight();
int charWidth = av.getCharWidth();
}
}
+ /*
+ * Draw a selection group over a wrapped alignment
+ */
+ private void drawWrappedSelection(Graphics2D g, SequenceGroup group,
+ int canvasWidth,
+ int canvasHeight, int startRes)
+ {
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
+ // height gap above each panel
+ int hgap = charHeight;
+ if (av.getScaleAboveWrapped())
+ {
+ hgap += charHeight;
+ }
+
+ int cWidth = (canvasWidth - labelWidthEast - labelWidthWest)
+ / charWidth;
+ int cHeight = av.getAlignment().getHeight() * charHeight;
+
+ int startx = startRes;
+ int endx;
+ int ypos = hgap; // vertical offset
+ int maxwidth = av.getAlignment().getWidth();
+
+ if (av.hasHiddenColumns())
+ {
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth);
+ }
+
+ // chop the wrapped alignment extent up into panel-sized blocks and treat
+ // each block as if it were a block from an unwrapped alignment
+ while ((ypos <= canvasHeight) && (startx < maxwidth))
+ {
+ // set end value to be start + width, or maxwidth, whichever is smaller
+ endx = startx + cWidth - 1;
+
+ if (endx > maxwidth)
+ {
+ endx = maxwidth;
+ }
+
+ g.translate(labelWidthWest, 0);
+
+ drawUnwrappedSelection(g, group, startx, endx, 0,
+ av.getAlignment().getHeight() - 1,
+ ypos);
+
+ g.translate(-labelWidthWest, 0);
+
+ // update vertical offset
+ ypos += cHeight + getAnnotationHeight() + hgap;
+
+ // update horizontal offset
+ startx += cWidth;
+ }
+ }
+
int getAnnotationHeight()
{
if (!av.isShowAnnotation())
int charWidth = av.getCharWidth();
g.setFont(av.getFont());
- sr.prepare(g, av.isRenderGaps());
+ seqRdr.prepare(g, av.isRenderGaps());
SequenceI nextSeq;
// empty
continue;
}
- sr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),
+ seqRdr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),
startRes, endRes, offset + ((i - startSeq) * charHeight));
if (av.isShowSequenceFeatures())
{
for (int r = 0; r < visibleResults.length; r += 2)
{
- sr.drawHighlightedText(nextSeq, visibleResults[r],
- visibleResults[r + 1],
- (visibleResults[r] - startRes) * charWidth,
- offset + ((i - startSeq) * charHeight));
+ seqRdr.drawHighlightedText(nextSeq, visibleResults[r],
+ visibleResults[r + 1], (visibleResults[r] - startRes)
+ * charWidth, offset
+ + ((i - startSeq) * charHeight));
}
}
}
if (av.cursorMode && cursorY == i && cursorX >= startRes
&& cursorX <= endRes)
{
- sr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth,
+ seqRdr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth,
offset + ((i - startSeq) * charHeight));
}
}
void drawGroupsBoundaries(Graphics g1, int startRes, int endRes,
int startSeq, int endSeq, int offset)
{
- int charHeight = av.getCharHeight();
- int charWidth = av.getCharWidth();
-
Graphics2D g = (Graphics2D) g1;
//
// ///////////////////////////////////
// Now outline any areas if necessary
// ///////////////////////////////////
- SequenceGroup group = av.getSelectionGroup();
- int sx = -1;
- int sy = -1;
- int ex = -1;
+ SequenceGroup group = null;
int groupIndex = -1;
- int visWidth = (endRes - startRes + 1) * charWidth;
- if ((group == null) && (av.getAlignment().getGroups().size() > 0))
+ if (av.getAlignment().getGroups().size() > 0)
{
group = av.getAlignment().getGroups().get(0);
groupIndex = 0;
if (group != null)
{
+ g.setStroke(new BasicStroke());
+ g.setColor(group.getOutlineColour());
+
do
{
- int oldY = -1;
- int i = 0;
- boolean inGroup = false;
- int top = -1;
- int bottom = -1;
+ drawPartialGroupOutline(g, group, startRes, endRes, startSeq,
+ endSeq, offset);
+
+ groupIndex++;
+
+ g.setStroke(new BasicStroke());
- for (i = startSeq; i <= endSeq; i++)
+ if (groupIndex >= av.getAlignment().getGroups().size())
{
- sx = (group.getStartRes() - startRes) * charWidth;
- sy = offset + ((i - startSeq) * charHeight);
- ex = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth)
- - 1;
+ break;
+ }
- if (sx + ex < 0 || sx > visWidth)
- {
- continue;
- }
+ group = av.getAlignment().getGroups().get(groupIndex);
- if ((sx <= (endRes - startRes) * charWidth)
- && group.getSequences(null)
- .contains(av.getAlignment().getSequenceAt(i)))
- {
- if ((bottom == -1) && !group.getSequences(null)
- .contains(av.getAlignment().getSequenceAt(i + 1)))
- {
- bottom = sy + charHeight;
- }
+ } while (groupIndex < av.getAlignment().getGroups().size());
- if (!inGroup)
- {
- if (((top == -1) && (i == 0)) || !group.getSequences(null)
- .contains(av.getAlignment().getSequenceAt(i - 1)))
- {
- top = sy;
- }
+ }
- oldY = sy;
- inGroup = true;
+ }
- if (group == av.getSelectionGroup())
- {
- g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
- BasicStroke.JOIN_ROUND, 3f, new float[]
- { 5f, 3f }, 0f));
- g.setColor(Color.RED);
- }
- else
- {
- g.setStroke(new BasicStroke());
- g.setColor(group.getOutlineColour());
- }
- }
- }
- else
- {
- if (inGroup)
- {
- if (sx >= 0 && sx < visWidth)
- {
- g.drawLine(sx, oldY, sx, sy);
- }
- if (sx + ex < visWidth)
- {
- g.drawLine(sx + ex, oldY, sx + ex, sy);
- }
+ /*
+ * Draw the selection group as a separate image and overlay
+ */
+ private BufferedImage drawSelectionGroup(int startRes, int endRes,
+ int startSeq, int endSeq)
+ {
+ // get a new image of the correct size
+ BufferedImage selectionImage = setupImage();
- if (sx < 0)
- {
- ex += sx;
- sx = 0;
- }
+ if (selectionImage == null)
+ {
+ return null;
+ }
- if (sx + ex > visWidth)
- {
- ex = visWidth;
- }
+ SequenceGroup group = av.getSelectionGroup();
+ if (group == null)
+ {
+ // nothing to draw
+ return null;
+ }
- else if (sx + ex >= (endRes - startRes + 1) * charWidth)
- {
- ex = (endRes - startRes + 1) * charWidth;
- }
+ // set up drawing colour
+ Graphics2D g = (Graphics2D) selectionImage.getGraphics();
- if (top != -1)
- {
- g.drawLine(sx, top, sx + ex, top);
- top = -1;
- }
+ setupSelectionGroup(g, selectionImage);
- if (bottom != -1)
- {
- g.drawLine(sx, bottom, sx + ex, bottom);
- bottom = -1;
- }
+ if (!av.getWrapAlignment())
+ {
+ drawUnwrappedSelection(g, group, startRes, endRes, startSeq, endSeq,
+ 0);
+ }
+ else
+ {
+ drawWrappedSelection(g, group, getWidth(), getHeight(),
+ av.getRanges().getStartRes());
+ }
- inGroup = false;
- }
- }
+ g.dispose();
+ return selectionImage;
+ }
+
+ /*
+ * Set up graphics for selection group
+ */
+ private void setupSelectionGroup(Graphics2D g,
+ BufferedImage selectionImage)
+ {
+ // set background to transparent
+ g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
+ g.fillRect(0, 0, selectionImage.getWidth(), selectionImage.getHeight());
+
+ // set up foreground to draw red dashed line
+ g.setComposite(AlphaComposite.Src);
+ g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_ROUND, 3f, new float[]
+ { 5f, 3f }, 0f));
+ g.setColor(Color.RED);
+ }
+
+ /*
+ * Draw a selection group over an unwrapped alignment
+ * @param g graphics object to draw with
+ * @param group selection group
+ * @param startRes start residue of area to draw
+ * @param endRes end residue of area to draw
+ * @param startSeq start sequence of area to draw
+ * @param endSeq end sequence of area to draw
+ * @param offset vertical offset (used when called from wrapped alignment code)
+ */
+ private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
+ int startRes, int endRes, int startSeq, int endSeq, int offset)
+ {
+ int charWidth = av.getCharWidth();
+
+ if (!av.hasHiddenColumns())
+ {
+ drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
+ offset);
+ }
+ else
+ {
+ // package into blocks of visible columns
+ int screenY = 0;
+ int blockStart = startRes;
+ int blockEnd = endRes;
+
+ for (int[] region : av.getAlignment().getHiddenColumns()
+ .getHiddenColumnsCopy())
+ {
+ int hideStart = region[0];
+ int hideEnd = region[1];
+
+ if (hideStart <= blockStart)
+ {
+ blockStart += (hideEnd - hideStart) + 1;
+ continue;
+ }
+
+ blockEnd = hideStart - 1;
+
+ g.translate(screenY * charWidth, 0);
+ drawPartialGroupOutline(g, group,
+ blockStart, blockEnd, startSeq, endSeq, offset);
+
+ g.translate(-screenY * charWidth, 0);
+ screenY += blockEnd - blockStart + 1;
+ blockStart = hideEnd + 1;
+
+ if (screenY > (endRes - startRes))
+ {
+ // already rendered last block
+ break;
}
+ }
+
+ if (screenY <= (endRes - startRes))
+ {
+ // remaining visible region to render
+ blockEnd = blockStart + (endRes - startRes) - screenY;
+ g.translate(screenY * charWidth, 0);
+ drawPartialGroupOutline(g, group,
+ blockStart, blockEnd, startSeq, endSeq, offset);
+
+ g.translate(-screenY * charWidth, 0);
+ }
+ }
+ }
+ /*
+ * Draw the selection group as a separate image and overlay
+ */
+ private void drawPartialGroupOutline(Graphics2D g, SequenceGroup group,
+ int startRes, int endRes, int startSeq, int endSeq,
+ int verticalOffset)
+ {
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
+ int visWidth = (endRes - startRes + 1) * charWidth;
+
+ int oldY = -1;
+ int i = 0;
+ boolean inGroup = false;
+ int top = -1;
+ int bottom = -1;
+
+ int sx = -1;
+ int sy = -1;
+ int xwidth = -1;
+
+ for (i = startSeq; i <= endSeq; i++)
+ {
+ // position of start residue of group relative to startRes, in pixels
+ sx = (group.getStartRes() - startRes) * charWidth;
+
+ // width of group in pixels
+ xwidth = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth)
+ - 1;
+
+ sy = verticalOffset + (i - startSeq) * charHeight;
+
+ if (sx + xwidth < 0 || sx > visWidth)
+ {
+ continue;
+ }
+
+ if ((sx <= (endRes - startRes) * charWidth)
+ && group.getSequences(null)
+ .contains(av.getAlignment().getSequenceAt(i)))
+ {
+ if ((bottom == -1) && !group.getSequences(null)
+ .contains(av.getAlignment().getSequenceAt(i + 1)))
+ {
+ bottom = sy + charHeight;
+ }
+
+ if (!inGroup)
+ {
+ if (((top == -1) && (i == 0)) || !group.getSequences(null)
+ .contains(av.getAlignment().getSequenceAt(i - 1)))
+ {
+ top = sy;
+ }
+
+ oldY = sy;
+ inGroup = true;
+ }
+ }
+ else
+ {
if (inGroup)
{
- sy = offset + ((i - startSeq) * charHeight);
+ // if start position is visible, draw vertical line to left of
+ // group
if (sx >= 0 && sx < visWidth)
{
g.drawLine(sx, oldY, sx, sy);
}
- if (sx + ex < visWidth)
+ // if end position is visible, draw vertical line to right of
+ // group
+ if (sx + xwidth < visWidth)
{
- g.drawLine(sx + ex, oldY, sx + ex, sy);
+ g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
}
if (sx < 0)
{
- ex += sx;
+ xwidth += sx;
sx = 0;
}
- if (sx + ex > visWidth)
+ // don't let width extend beyond current block, or group extent
+ // fixes JAL-2672
+ if (sx + xwidth >= (endRes - startRes + 1) * charWidth)
{
- ex = visWidth;
+ xwidth = (endRes - startRes + 1) * charWidth - sx;
}
- else if (sx + ex >= (endRes - startRes + 1) * charWidth)
- {
- ex = (endRes - startRes + 1) * charWidth;
- }
-
+
+ // draw horizontal line at top of group
if (top != -1)
{
- g.drawLine(sx, top, sx + ex, top);
+ g.drawLine(sx, top, sx + xwidth, top);
top = -1;
}
+ // draw horizontal line at bottom of group
if (bottom != -1)
{
- g.drawLine(sx, bottom - 1, sx + ex, bottom - 1);
+ g.drawLine(sx, bottom, sx + xwidth, bottom);
bottom = -1;
}
inGroup = false;
}
+ }
+ }
- groupIndex++;
+ if (inGroup)
+ {
+ sy = verticalOffset + ((i - startSeq) * charHeight);
+ if (sx >= 0 && sx < visWidth)
+ {
+ g.drawLine(sx, oldY, sx, sy);
+ }
- g.setStroke(new BasicStroke());
+ if (sx + xwidth < visWidth)
+ {
+ g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
+ }
- if (groupIndex >= av.getAlignment().getGroups().size())
- {
- break;
- }
+ if (sx < 0)
+ {
+ xwidth += sx;
+ sx = 0;
+ }
- group = av.getAlignment().getGroups().get(groupIndex);
+ if (sx + xwidth > visWidth)
+ {
+ xwidth = visWidth;
+ }
+ else if (sx + xwidth >= (endRes - startRes + 1) * charWidth)
+ {
+ xwidth = (endRes - startRes + 1) * charWidth;
+ }
- } while (groupIndex < av.getAlignment().getGroups().size());
+ if (top != -1)
+ {
+ g.drawLine(sx, top, sx + xwidth, top);
+ top = -1;
+ }
- }
+ if (bottom != -1)
+ {
+ g.drawLine(sx, bottom - 1, sx + xwidth, bottom - 1);
+ bottom = -1;
+ }
+ inGroup = false;
+ }
}
-
+
/**
* Highlights search results in the visible region by rendering as white text
* on a black background. Any previous highlighting is removed. Answers true
{
String eventName = evt.getPropertyName();
- int scrollX = 0;
- if (eventName.equals(ViewportRanges.STARTRES))
+ if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED))
{
- // Make sure we're not trying to draw a panel
- // larger than the visible window
- ViewportRanges vpRanges = av.getRanges();
- scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
- int range = vpRanges.getEndRes() - vpRanges.getStartRes();
- if (scrollX > range)
- {
- scrollX = range;
- }
- else if (scrollX < -range)
- {
- scrollX = -range;
- }
+ fastPaint = true;
+ repaint();
}
-
- // Both scrolling and resizing change viewport ranges: scrolling changes
- // both start and end points, but resize only changes end values.
- // Here we only want to fastpaint on a scroll, with resize using a normal
- // paint, so scroll events are identified as changes to the horizontal or
- // vertical start value.
- if (eventName.equals(ViewportRanges.STARTRES))
+ else if (eventName.equals(ViewportRanges.STARTRES))
{
- // scroll - startres and endres both change
- if (av.getWrapAlignment())
+ int scrollX = 0;
+ if (eventName.equals(ViewportRanges.STARTRES))
{
- fastPaintWrapped(scrollX);
+ // Make sure we're not trying to draw a panel
+ // larger than the visible window
+ ViewportRanges vpRanges = av.getRanges();
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ int range = vpRanges.getEndRes() - vpRanges.getStartRes();
+ if (scrollX > range)
+ {
+ scrollX = range;
+ }
+ else if (scrollX < -range)
+ {
+ scrollX = -range;
+ }
+
+ // Both scrolling and resizing change viewport ranges: scrolling changes
+ // both start and end points, but resize only changes end values.
+ // Here we only want to fastpaint on a scroll, with resize using a normal
+ // paint, so scroll events are identified as changes to the horizontal or
+ // vertical start value.
+
+ // scroll - startres and endres both change
+ if (av.getWrapAlignment())
+ {
+ fastPaintWrapped(scrollX);
+ }
+ else
+ {
+ fastPaint(scrollX, 0);
+ }
}
- else
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
{
- fastPaint(scrollX, 0);
+ // scroll
+ fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
}
- else if (eventName.equals(ViewportRanges.STARTSEQ))
- {
- fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
- }
}
/**
}
}
+
/**
* Redraws any positions in the search results in the visible region of a
* wrapped alignment. Any highlights are drawn depending on the search results
}
mouseDragging = true;
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
scrollThread.setEvent(evt);
}
oldSeq = 0;
}
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
scrollThread = null;
}
}
return;
}
- if (mouseDragging)
+ if (mouseDragging && scrollThread == null)
{
scrollThread = new ScrollThread();
}
if (stretchGroup == null)
{
- // Only if left mouse button do we want to change group sizes
+ createStretchGroup(res, sequence);
+ }
- // define a new group here
- SequenceGroup sg = new SequenceGroup();
- sg.setStartRes(res);
- sg.setEndRes(res);
- sg.addSequence(sequence, false);
- av.setSelectionGroup(sg);
- stretchGroup = sg;
+ if (stretchGroup != null)
+ {
+ stretchGroup.addPropertyChangeListener(seqCanvas);
+ }
- if (av.getConservationSelected())
- {
- SliderPanel.setConservationSlider(ap, av.getResidueShading(),
- ap.getViewName());
- }
+ seqCanvas.repaint();
+ }
- if (av.getAbovePIDThreshold())
- {
- SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
- ap.getViewName());
- }
- // TODO: stretchGroup will always be not null. Is this a merge error ?
- if ((stretchGroup != null) && (stretchGroup.getEndRes() == res))
- {
- // Edit end res position of selected group
- changeEndRes = true;
- }
- else if ((stretchGroup != null)
- && (stretchGroup.getStartRes() == res))
- {
- // Edit end res position of selected group
- changeStartRes = true;
- }
- stretchGroup.getWidth();
+ private void createStretchGroup(int res, SequenceI sequence)
+ {
+ // Only if left mouse button do we want to change group sizes
+ // define a new group here
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(res);
+ sg.setEndRes(res);
+ sg.addSequence(sequence, false);
+ av.setSelectionGroup(sg);
+ stretchGroup = sg;
+
+ if (av.getConservationSelected())
+ {
+ SliderPanel.setConservationSlider(ap, av.getResidueShading(),
+ ap.getViewName());
}
- seqCanvas.repaint();
+ if (av.getAbovePIDThreshold())
+ {
+ SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
+ ap.getViewName());
+ }
+ // TODO: stretchGroup will always be not null. Is this a merge error ?
+ // or is there a threading issue here?
+ if ((stretchGroup != null) && (stretchGroup.getEndRes() == res))
+ {
+ // Edit end res position of selected group
+ changeEndRes = true;
+ }
+ else if ((stretchGroup != null) && (stretchGroup.getStartRes() == res))
+ {
+ // Edit end res position of selected group
+ changeStartRes = true;
+ }
+ stretchGroup.getWidth();
+
}
/**
{
return;
}
+
+ stretchGroup.removePropertyChangeListener(seqCanvas);
+
// always do this - annotation has own state
// but defer colourscheme update until hidden sequences are passed in
boolean vischange = stretchGroup.recalcConservation(true);
mouseDragging = true;
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
scrollThread.setEvent(evt);
}
-
- seqCanvas.repaint();
}
void scrollCanvas(MouseEvent evt)
{
if (evt == null)
{
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
scrollThread = null;
}
mouseDragging = false;
{
MouseEvent evt;
- boolean running = false;
+ private volatile boolean threadRunning = true;
public ScrollThread()
{
public void stopScrolling()
{
- running = false;
+ threadRunning = false;
+ }
+
+ public boolean isRunning()
+ {
+ return threadRunning;
}
@Override
public void run()
{
- running = true;
-
- while (running)
+ while (threadRunning)
{
if (evt != null)
{
if (mouseDragging && (evt.getY() < 0)
&& (av.getRanges().getStartSeq() > 0))
{
- running = av.getRanges().scrollUp(true);
+ av.getRanges().scrollUp(true);
}
if (mouseDragging && (evt.getY() >= getHeight()) && (av
.getAlignment().getHeight() > av.getRanges().getEndSeq()))
{
- running = av.getRanges().scrollUp(false);
+ av.getRanges().scrollUp(false);
}
if (mouseDragging && (evt.getX() < 0))
{
- running = av.getRanges().scrollRight(false);
+ av.getRanges().scrollRight(false);
}
else if (mouseDragging && (evt.getX() >= getWidth()))
{
- running = av.getRanges().scrollRight(true);
+ av.getRanges().scrollRight(true);
}
}
import jalview.api.AlignViewportI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
-import jalview.renderer.ResidueShaderI;
+import jalview.renderer.ResidueColourFinder;
import jalview.renderer.seqfeatures.FeatureColourFinder;
-import jalview.util.Comparison;
import java.awt.Color;
import java.awt.FontMetrics;
boolean renderGaps = true;
- SequenceGroup currentSequenceGroup = null;
-
SequenceGroup[] allGroups = null;
- Color resBoxColour;
+ // Color resBoxColour;
Graphics graphics;
boolean monospacedFont;
- boolean forOverview = false;
+ ResidueColourFinder resColourFinder;
/**
* Creates a new SequenceRenderer object
public SequenceRenderer(AlignViewportI viewport)
{
this.av = viewport;
+ resColourFinder = new ResidueColourFinder();
}
/**
this.renderGaps = renderGaps;
}
- protected Color getResidueBoxColour(SequenceI seq, int i)
- {
- // rate limiting step when rendering overview for lots of groups
- allGroups = av.getAlignment().findAllGroups(seq);
-
- if (inCurrentSequenceGroup(i))
- {
- if (currentSequenceGroup.getDisplayBoxes())
- {
- getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq, i);
- }
- }
- else if (av.getShowBoxes())
- {
- getBoxColour(av.getResidueShading(), seq, i);
- }
-
- return resBoxColour;
- }
-
/**
* Get the residue colour at the given sequence position - as determined by
* the sequence group colour (if any), else the colour scheme, possibly
public Color getResidueColour(final SequenceI seq, int position,
FeatureColourFinder finder)
{
- Color col = getResidueBoxColour(seq, position);
-
- if (finder != null)
- {
- col = finder.findFeatureColour(col, seq, position);
- }
- return col;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param shader
- * DOCUMENT ME!
- * @param seq
- * DOCUMENT ME!
- * @param i
- * DOCUMENT ME!
- */
- void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
- {
- if (shader.getColourScheme() != null)
- {
- resBoxColour = shader.findColour(seq.getCharAt(i), i, seq);
- }
- else if (forOverview && !Comparison.isGap(seq.getCharAt(i)))
- {
- resBoxColour = Color.lightGray;
- }
- else
- {
- resBoxColour = Color.white;
- }
+ allGroups = av.getAlignment().findAllGroups(seq);
+ return resColourFinder.getResidueColour(av.getShowBoxes(),
+ av.getResidueShading(),
+ allGroups, seq, position,
+ finder);
}
/**
public synchronized void drawBoxes(SequenceI seq, int start, int end,
int y1)
{
+ Color resBoxColour = Color.white;
+
if (seq == null)
{
return; // fix for racecondition
if (i < length)
{
- if (inCurrentSequenceGroup(i))
+ SequenceGroup currentSequenceGroup = resColourFinder
+ .getCurrentSequenceGroup(
+ allGroups, i);
+ if (currentSequenceGroup != null)
{
if (currentSequenceGroup.getDisplayBoxes())
{
- getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+ resBoxColour = resColourFinder.getBoxColour(
+ currentSequenceGroup.getGroupColourScheme(), seq,
i);
}
}
else if (av.getShowBoxes())
{
- getBoxColour(av.getResidueShading(), seq, i);
+ resBoxColour = resColourFinder
+ .getBoxColour(av.getResidueShading(), seq, i);
}
}
boolean srep = av.isDisplayReferenceSeq();
boolean getboxColour = false;
boolean isarep = av.getAlignment().getSeqrep() == seq;
- boolean isgrep = currentSequenceGroup != null
- ? currentSequenceGroup.getSeqrep() == seq
- : false;
- char sr_c;
+ Color resBoxColour = Color.white;
+
for (int i = start; i <= end; i++)
{
continue;
}
- if (inCurrentSequenceGroup(i))
+ SequenceGroup currentSequenceGroup = resColourFinder
+ .getCurrentSequenceGroup(
+ allGroups, i);
+ if (currentSequenceGroup != null)
{
if (!currentSequenceGroup.getDisplayText())
{
|| currentSequenceGroup.getColourText())
{
getboxColour = true;
- getBoxColour(currentSequenceGroup.getGroupColourScheme(), seq,
+ resBoxColour = resColourFinder.getBoxColour(
+ currentSequenceGroup.getGroupColourScheme(), seq,
i);
if (currentSequenceGroup.getColourText())
{
graphics.setColor(currentSequenceGroup.textColour);
}
+ boolean isgrep = currentSequenceGroup != null
+ ? currentSequenceGroup.getSeqrep() == seq : false;
if (!isarep && !isgrep
&& currentSequenceGroup.getShowNonconserved()) // todo
// optimize
if (av.getColourText())
{
getboxColour = true;
- getBoxColour(av.getResidueShading(), seq, i);
+ resBoxColour = resColourFinder
+ .getBoxColour(av.getResidueShading(), seq, i);
if (av.getShowBoxes())
{
{
if (!getboxColour)
{
- getBoxColour(av.getResidueShading(), seq, i);
+ resBoxColour = resColourFinder
+ .getBoxColour(av.getResidueShading(), seq, i);
}
if (resBoxColour.getRed() + resBoxColour.getBlue()
/**
* DOCUMENT ME!
*
- * @param res
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- boolean inCurrentSequenceGroup(int res)
- {
- if (allGroups == null)
- {
- return false;
- }
-
- for (int i = 0; i < allGroups.length; i++)
- {
- if ((allGroups[i].getStartRes() <= res)
- && (allGroups[i].getEndRes() >= res))
- {
- currentSequenceGroup = allGroups[i];
-
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * DOCUMENT ME!
- *
* @param seq
* DOCUMENT ME!
* @param start
}
/**
- * Adjust the divider for a sensible split of the real estate (for example,
+ * Adjusts the divider for a sensible split of the real estate (for example,
* when many transcripts are shown with a single protein). This should only be
* called after the split pane has been laid out (made visible) so it has a
- * height.
+ * height. The aim is to avoid unnecessary vertical scroll bars, while
+ * ensuring that at least 2 sequences are visible in each panel.
+ * <p>
+ * Once laid out, the user may choose to customise as they wish, so this
+ * method is not called again after the initial layout.
*/
- protected void adjustDivider()
+ protected void adjustInitialLayout()
{
- final AlignViewport topViewport = ((AlignFrame) getTopFrame()).viewport;
- final AlignViewport bottomViewport = ((AlignFrame) getBottomFrame()).viewport;
+ AlignFrame topFrame = (AlignFrame) getTopFrame();
+ AlignFrame bottomFrame = (AlignFrame) getBottomFrame();
+
+ /*
+ * recompute layout of top and bottom panels to reflect their
+ * actual (rather than requested) height
+ */
+ topFrame.alignPanel.adjustAnnotationHeight();
+ bottomFrame.alignPanel.adjustAnnotationHeight();
+
+ final AlignViewport topViewport = topFrame.viewport;
+ final AlignViewport bottomViewport = bottomFrame.viewport;
final AlignmentI topAlignment = topViewport.getAlignment();
final AlignmentI bottomAlignment = bottomViewport.getAlignment();
boolean topAnnotations = topViewport.isShowAnnotation();
int bottomCharHeight = bottomViewport.getViewStyle().getCharHeight();
/*
+ * calculate the minimum ratio that leaves at least the height
+ * of two sequences (after rounding) visible in the top panel
+ */
+ int topPanelHeight = topFrame.getHeight();
+ int bottomPanelHeight = bottomFrame.getHeight();
+ int topSequencesHeight = topFrame.alignPanel.getSeqPanel().seqCanvas
+ .getHeight();
+ int topPanelMinHeight = topPanelHeight
+ - Math.max(0, topSequencesHeight - 3 * topCharHeight);
+ double totalHeight = (double) topPanelHeight + bottomPanelHeight;
+ double minRatio = topPanelMinHeight / totalHeight;
+
+ /*
+ * calculate the maximum ratio that leaves at least the height
+ * of two sequences (after rounding) visible in the bottom panel
+ */
+ int bottomSequencesHeight = bottomFrame.alignPanel.getSeqPanel().seqCanvas
+ .getHeight();
+ int bottomPanelMinHeight = bottomPanelHeight
+ - Math.max(0, bottomSequencesHeight - 3 * bottomCharHeight);
+ double maxRatio = (totalHeight - bottomPanelMinHeight) / totalHeight;
+
+ /*
* estimate ratio of (topFrameContent / bottomFrameContent)
*/
int insets = Platform.isAMac() ? MAC_INSETS_HEIGHT
+ (topAnnotations ? topViewport.calcPanelHeight() : 0);
int bottomHeight = insets + (3 + bottomCount) * bottomCharHeight
+ (bottomAnnotations ? bottomViewport.calcPanelHeight() : 0);
- double ratio = ((double) topHeight) / (topHeight + bottomHeight);
+ double ratio = ((double) topHeight)
+ / (double) (topHeight + bottomHeight);
/*
- * limit to 0.2 <= ratio <= 0.8 to avoid concealing all sequences
+ * limit ratio to avoid concealing all sequences
*/
- ratio = Math.min(ratio, 0.8d);
- ratio = Math.max(ratio, 0.2d);
+ ratio = Math.min(ratio, maxRatio);
+ ratio = Math.max(ratio, minRatio);
setRelativeDividerLocation(ratio);
}
protected JCheckBox rightAlign = new JCheckBox();
- protected JComboBox<String> fontSizeCB = new JComboBox<String>();
+ protected JComboBox<String> fontSizeCB = new JComboBox<>();
- protected JComboBox<String> fontStyleCB = new JComboBox<String>();
+ protected JComboBox<String> fontStyleCB = new JComboBox<>();
- protected JComboBox<String> fontNameCB = new JComboBox<String>();
+ protected JComboBox<String> fontNameCB = new JComboBox<>();
protected JCheckBox showOccupancy = new JCheckBox();
protected JCheckBox scaleProteinToCdna = new JCheckBox();
- protected JComboBox<String> gapSymbolCB = new JComboBox<String>();
+ protected JComboBox<String> gapSymbolCB = new JComboBox<>();
protected JCheckBox wrap = new JCheckBox();
- protected JComboBox<String> sortby = new JComboBox<String>();
+ protected JComboBox<String> sortby = new JComboBox<>();
- protected JComboBox<String> sortAnnBy = new JComboBox<String>();
+ protected JComboBox<String> sortAnnBy = new JComboBox<>();
- protected JComboBox<String> sortAutocalc = new JComboBox<String>();
+ protected JComboBox<String> sortAutocalc = new JComboBox<>();
protected JCheckBox startupCheckbox = new JCheckBox();
protected JCheckBox addTempFactor = new JCheckBox();
- protected JComboBox<String> structViewer = new JComboBox<String>();
+ protected JComboBox<String> structViewer = new JComboBox<>();
protected JTextField chimeraPath = new JTextField();
protected JPanel maxColour = new JPanel();
- protected JComboBox<String> protColour = new JComboBox<String>();
+ protected JComboBox<String> protColour = new JComboBox<>();
- protected JComboBox<String> nucColour = new JComboBox<String>();
+ protected JComboBox<String> nucColour = new JComboBox<>();
+
+ /*
+ * Overview tab components
+ */
+ protected JPanel gapColour = new JPanel();
+
+ protected JPanel hiddenColour = new JPanel();
+
+ protected JCheckBox useLegacyGap;
+
+ protected JCheckBox showHiddenAtStart;
+
+ protected JLabel gapLabel;
/*
* Connections tab components
/*
* Output tab components
*/
- protected JComboBox<Object> epsRendering = new JComboBox<Object>();
+ protected JComboBox<Object> epsRendering = new JComboBox<>();
protected JLabel userIdWidthlabel = new JLabel();
tabbedPane.add(initColoursTab(),
MessageManager.getString("label.colours"));
+ tabbedPane.add(initOverviewTab(),
+ MessageManager.getString("label.overview"));
+
tabbedPane.add(initStructureTab(),
MessageManager.getString("label.structure"));
}
/**
+ * Initialises the Overview tabbed panel.
+ *
+ * @return
+ */
+ private JPanel initOverviewTab()
+ {
+ JPanel overviewPanel = new JPanel();
+ overviewPanel.setBorder(new TitledBorder(
+ MessageManager.getString("label.overview_settings")));
+
+ gapColour.setFont(LABEL_FONT);
+ // fixing the border colours stops apparent colour bleed from the panel
+ gapColour.setBorder(
+ BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
+ gapColour.setPreferredSize(new Dimension(40, 20));
+ gapColour.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mousePressed(MouseEvent e)
+ {
+ gapColour_actionPerformed(gapColour);
+ }
+ });
+
+ hiddenColour.setFont(LABEL_FONT);
+ // fixing the border colours stops apparent colour bleed from the panel
+ hiddenColour.setBorder(
+ BorderFactory.createEtchedBorder(Color.white, Color.lightGray));
+ hiddenColour.setPreferredSize(new Dimension(40, 20));
+ hiddenColour.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mousePressed(MouseEvent e)
+ {
+ hiddenColour_actionPerformed(hiddenColour);
+ }
+ });
+
+ useLegacyGap = new JCheckBox(
+ MessageManager.getString("label.ov_legacy_gap"));
+ useLegacyGap.setFont(LABEL_FONT);
+ useLegacyGap.setHorizontalAlignment(SwingConstants.LEFT);
+ useLegacyGap.setVerticalTextPosition(SwingConstants.TOP);
+ gapLabel = new JLabel(
+ MessageManager.getString("label.gap_colour"));
+ gapLabel.setFont(LABEL_FONT);
+ gapLabel.setHorizontalAlignment(SwingConstants.LEFT);
+ gapLabel.setVerticalTextPosition(SwingConstants.TOP);
+ showHiddenAtStart = new JCheckBox(
+ MessageManager.getString("label.ov_show_hide_default"));
+ showHiddenAtStart.setFont(LABEL_FONT);
+ showHiddenAtStart.setHorizontalAlignment(SwingConstants.LEFT);
+ showHiddenAtStart.setVerticalTextPosition(SwingConstants.TOP);
+ JLabel hiddenLabel = new JLabel(
+ MessageManager.getString("label.hidden_colour"));
+ hiddenLabel.setFont(LABEL_FONT);
+ hiddenLabel.setHorizontalAlignment(SwingConstants.LEFT);
+ hiddenLabel.setVerticalTextPosition(SwingConstants.TOP);
+
+ useLegacyGap.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ useLegacyGaps_actionPerformed(e);
+ }
+ });
+
+ overviewPanel.setLayout(new GridBagLayout());
+ GridBagConstraints c1 = new GridBagConstraints();
+
+ c1.fill = GridBagConstraints.HORIZONTAL;
+ c1.gridx = 0;
+ c1.gridy = 0;
+ c1.weightx = 1;
+ c1.ipady = 20;
+ c1.anchor = GridBagConstraints.FIRST_LINE_START;
+ overviewPanel.add(useLegacyGap, c1);
+
+ GridBagConstraints c2 = new GridBagConstraints();
+ c2.fill = GridBagConstraints.HORIZONTAL;
+ c2.gridx = 1;
+ c2.gridy = 0;
+ c2.insets = new Insets(0, 15, 0, 10);
+ overviewPanel.add(gapLabel, c2);
+
+ GridBagConstraints c3 = new GridBagConstraints();
+ c3.fill = GridBagConstraints.HORIZONTAL;
+ c3.gridx = 2;
+ c3.gridy = 0;
+ c3.insets = new Insets(0, 0, 0, 15);
+ overviewPanel.add(gapColour, c3);
+
+ GridBagConstraints c4 = new GridBagConstraints();
+ c4.fill = GridBagConstraints.HORIZONTAL;
+ c4.gridx = 0;
+ c4.gridy = 1;
+ c4.weightx = 1;
+ overviewPanel.add(showHiddenAtStart, c4);
+
+ GridBagConstraints c5 = new GridBagConstraints();
+ c5.fill = GridBagConstraints.HORIZONTAL;
+ c5.gridx = 1;
+ c5.gridy = 1;
+ c5.insets = new Insets(0, 15, 0, 10);
+ overviewPanel.add(hiddenLabel, c5);
+
+ GridBagConstraints c6 = new GridBagConstraints();
+ c6.fill = GridBagConstraints.HORIZONTAL;
+ c6.gridx = 2;
+ c6.gridy = 1;
+ c6.insets = new Insets(0, 0, 0, 15);
+ overviewPanel.add(hiddenColour, c6);
+
+ JButton resetButton = new JButton(
+ MessageManager.getString("label.reset_to_defaults"));
+
+ resetButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ resetOvDefaults_actionPerformed(e);
+ }
+ });
+
+ GridBagConstraints c7 = new GridBagConstraints();
+ c7.fill = GridBagConstraints.NONE;
+ c7.gridx = 0;
+ c7.gridy = 2;
+ c7.insets = new Insets(10, 0, 0, 0);
+ c7.anchor = GridBagConstraints.WEST;
+ overviewPanel.add(resetButton, c7);
+
+ // Add padding so the panel doesn't look ridiculous
+ JPanel spacePanel = new JPanel();
+ overviewPanel.add(spacePanel,
+ new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.BOTH,
+ new Insets(0, 0, 0, 5), 0, 0));
+
+ return overviewPanel;
+ }
+
+ /**
* Initialises the Structure tabbed panel.
*
* @return
{
}
+ protected void gapColour_actionPerformed(JPanel panel)
+ {
+ }
+
+ protected void hiddenColour_actionPerformed(JPanel panel)
+ {
+ }
+
protected void showunconserved_actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
}
+ protected void useLegacyGaps_actionPerformed(ActionEvent e)
+ {
+ }
+
+ protected void resetOvDefaults_actionPerformed(ActionEvent e)
+ {
+ }
+
/**
* DOCUMENT ME!
*
protected static final String VIEWS_ENTER_ID = "VIEWS_ENTER_ID";
+ /**
+ * 'cached' structure view
+ */
protected static final String VIEWS_LOCAL_PDB = "VIEWS_LOCAL_PDB";
protected JTable tbl_local_pdb = new JTable();
import jalview.api.AlignmentColsCollectionI;
import jalview.api.AlignmentRowsCollectionI;
+import jalview.api.RendererListenerI;
import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.renderer.seqfeatures.FeatureRenderer;
import jalview.viewmodel.OverviewDimensions;
+import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
+import java.beans.PropertyChangeSupport;
public class OverviewRenderer
{
- private FeatureColourFinder finder;
+ // transparency of hidden cols/seqs overlay
+ private final float TRANSPARENCY = 0.5f;
+
+ private final Color HIDDEN_COLOUR = Color.DARK_GRAY.darker();
+
+ public static final String UPDATE = "OverviewUpdate";
+
+ private static final int MAX_PROGRESS = 100;
- private jalview.api.SequenceRenderer sr;
+ private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+ this);
+
+ private FeatureColourFinder finder;
// image to render on
private BufferedImage miniMe;
// raw number of pixels to allocate to each row
private float pixelsPerSeq;
+ // height in pixels of graph
+ private int graphHeight;
+
// flag to indicate whether to halt drawing
private volatile boolean redraw = false;
- public OverviewRenderer(jalview.api.SequenceRenderer seqRenderer,
- FeatureRenderer fr, OverviewDimensions od)
+ // reference to alignment, needed to get sequence groups
+ private AlignmentI al;
+
+ private ResidueShaderI shader;
+
+ private OverviewResColourFinder resColFinder;
+
+ public OverviewRenderer(FeatureRenderer fr, OverviewDimensions od,
+ AlignmentI alignment,
+ ResidueShaderI resshader, OverviewResColourFinder colFinder)
{
- sr = seqRenderer;
finder = new FeatureColourFinder(fr);
+ resColFinder = colFinder;
+
+ al = alignment;
+ shader = resshader;
pixelsPerCol = od.getPixelsPerCol();
pixelsPerSeq = od.getPixelsPerSeq();
+ graphHeight = od.getGraphHeight();
miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
BufferedImage.TYPE_INT_RGB);
}
int rgbcolor = Color.white.getRGB();
int seqIndex = 0;
int pixelRow = 0;
+ int alignmentHeight = miniMe.getHeight() - graphHeight;
+ int totalPixels = miniMe.getWidth() * alignmentHeight;
+
+ int lastRowUpdate = 0;
+ int lastUpdate = 0;
+ changeSupport.firePropertyChange(UPDATE, -1, 0);
for (int alignmentRow : rows)
{
{
break;
}
-
+
// get details of this alignment row
- boolean hidden = rows.isHidden(alignmentRow);
SequenceI seq = rows.getSequence(alignmentRow);
+ // rate limiting step when rendering overview for lots of groups
+ SequenceGroup[] allGroups = al.findAllGroups(seq);
+
// calculate where this row extends to in pixels
int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
miniMe.getHeight() - 1);
-
+
int colIndex = 0;
int pixelCol = 0;
for (int alignmentCol : cols)
{
break;
}
-
+
// calculate where this column extends to in pixels
int endCol = Math.min(Math.round((colIndex + 1) * pixelsPerCol) - 1,
miniMe.getWidth() - 1);
-
+
// don't do expensive colour determination if we're not going to use it
// NB this is important to avoid performance issues in the overview
// panel
if (pixelCol <= endCol)
{
- // determine the colour based on the sequence and column position
- rgbcolor = getColumnColourFromSequence(seq,
- hidden || cols.isHidden(alignmentCol), alignmentCol,
- finder);
-
+ rgbcolor = getColumnColourFromSequence(allGroups, seq,
+ alignmentCol, finder);
+
// fill in the appropriate number of pixels
for (int row = pixelRow; row <= endRow; ++row)
{
}
}
+ // store last update value
+ lastUpdate = sendProgressUpdate(
+ (pixelCol + 1) * (endRow - pixelRow), totalPixels,
+ lastRowUpdate, lastUpdate);
+
pixelCol = endCol + 1;
}
colIndex++;
}
- pixelRow = endRow + 1;
+
+ if (pixelRow != endRow + 1)
+ {
+ // store row offset and last update value
+ lastRowUpdate = sendProgressUpdate(endRow + 1, alignmentHeight, 0,
+ lastUpdate);
+ lastUpdate = lastRowUpdate;
+ pixelRow = endRow + 1;
+ }
seqIndex++;
}
+
+ overlayHiddenRegions(rows, cols);
+ // final update to progress bar if present
+ if (redraw)
+ {
+ sendProgressUpdate(pixelRow - 1, alignmentHeight, 0, 0);
+ }
+ else
+ {
+ sendProgressUpdate(alignmentHeight, miniMe.getHeight(), 0, 0);
+ }
return miniMe;
}
/*
+ * Calculate progress update value and fire event
+ * @param rowOffset number of rows to offset calculation by
+ * @return new rowOffset - return value only to be used when at end of a row
+ */
+ private int sendProgressUpdate(int position, int maximum, int rowOffset,
+ int lastUpdate)
+ {
+ int newUpdate = rowOffset
+ + Math.round(MAX_PROGRESS * ((float) position / maximum));
+ if (newUpdate > lastUpdate)
+ {
+ changeSupport.firePropertyChange(UPDATE, rowOffset, newUpdate);
+ return newUpdate;
+ }
+ return newUpdate;
+ }
+
+ /*
* Find the colour of a sequence at a specified column position
+ *
+ * @param seq
+ * sequence to get colour for
+ * @param lastcol
+ * column position to get colour for
+ * @param fcfinder
+ * FeatureColourFinder to use
+ * @return colour of sequence at this position, as RGB
*/
- private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
- boolean isHidden, int lastcol, FeatureColourFinder fcfinder)
+ private int getColumnColourFromSequence(SequenceGroup[] allGroups,
+ jalview.datamodel.SequenceI seq,
+ int lastcol, FeatureColourFinder fcfinder)
{
Color color = Color.white;
if ((seq != null) && (seq.getLength() > lastcol))
{
- color = sr.getResidueColour(seq, lastcol, fcfinder);
+ color = resColFinder.getResidueColour(true, shader, allGroups, seq,
+ lastcol,
+ fcfinder);
}
- if (isHidden)
+ return color.getRGB();
+ }
+
+ /**
+ * Overlay the hidden regions on the overview image
+ *
+ * @param rows
+ * collection of rows the overview is built over
+ * @param cols
+ * collection of columns the overview is built over
+ */
+ private void overlayHiddenRegions(AlignmentRowsCollectionI rows,
+ AlignmentColsCollectionI cols)
+ {
+ if (cols.hasHidden() || rows.hasHidden())
{
- color = color.darker().darker();
+ BufferedImage mask = buildHiddenImage(rows, cols, miniMe.getWidth(),
+ miniMe.getHeight());
+
+ Graphics2D g = (Graphics2D) miniMe.getGraphics();
+ g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+ TRANSPARENCY));
+ g.drawImage(mask, 0, 0, miniMe.getWidth(), miniMe.getHeight(), null);
}
+ }
- return color.getRGB();
+ /**
+ * Build a masking image of hidden columns and rows to be applied on top of
+ * the main overview image.
+ *
+ * @param rows
+ * collection of rows the overview is built over
+ * @param cols
+ * collection of columns the overview is built over
+ * @param width
+ * width of overview in pixels
+ * @param height
+ * height of overview in pixels
+ * @return BufferedImage containing mask of hidden regions
+ */
+ private BufferedImage buildHiddenImage(AlignmentRowsCollectionI rows,
+ AlignmentColsCollectionI cols, int width, int height)
+ {
+ // new masking image
+ BufferedImage hiddenImage = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+
+ int colIndex = 0;
+ int pixelCol = 0;
+
+ Color hidden = resColFinder.getHiddenColour();
+
+ Graphics2D g2d = (Graphics2D) hiddenImage.getGraphics();
+
+ // set background to transparent
+ g2d.setComposite(AlphaComposite.Clear);
+ g2d.fillRect(0, 0, width, height);
+
+ // set next colour to opaque
+ g2d.setComposite(AlphaComposite.Src);
+
+ for (int alignmentCol : cols)
+ {
+ if (redraw)
+ {
+ break;
+ }
+
+ // calculate where this column extends to in pixels
+ int endCol = Math.min(Math.round((colIndex + 1) * pixelsPerCol) - 1,
+ hiddenImage.getWidth() - 1);
+
+ if (pixelCol <= endCol)
+ {
+ // determine the colour based on the sequence and column position
+ if (cols.isHidden(alignmentCol))
+ {
+ g2d.setColor(hidden);
+ g2d.fillRect(pixelCol, 0, endCol - pixelCol + 1, height);
+ }
+
+ pixelCol = endCol + 1;
+ }
+ colIndex++;
+
+ }
+
+ int seqIndex = 0;
+ int pixelRow = 0;
+ for (int alignmentRow : rows)
+ {
+ if (redraw)
+ {
+ break;
+ }
+
+ // calculate where this row extends to in pixels
+ int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
+ miniMe.getHeight() - 1);
+
+ // get details of this alignment row
+ if (rows.isHidden(alignmentRow))
+ {
+ g2d.setColor(hidden);
+ g2d.fillRect(0, pixelRow, width, endRow - pixelRow + 1);
+ }
+ pixelRow = endRow + 1;
+ seqIndex++;
+ }
+
+ return hiddenImage;
}
/**
{
if (redraw)
{
+ changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1, 0);
break;
}
+
if (alignmentCol >= annotations.length)
{
break; // no more annotations to draw here
g.fillRect(pixelCol, y - height, endCol - pixelCol + 1, height);
}
+
pixelCol = endCol + 1;
colIndex++;
}
}
+ changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1,
+ MAX_PROGRESS);
}
+ /**
+ * Allows redraw flag to be set
+ *
+ * @param b
+ * value to set redraw to: true = redraw is occurring, false = no
+ * redraw
+ */
public void setRedraw(boolean b)
{
synchronized (this)
redraw = b;
}
}
+
+ public void addPropertyChangeListener(RendererListenerI listener)
+ {
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(RendererListenerI listener)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
+
+import java.awt.Color;
+
+public class OverviewResColourFinder extends ResidueColourFinder
+{
+ final Color GAP_COLOUR; // default colour to use at gaps
+
+ final Color RESIDUE_COLOUR; // default colour to use at residues
+
+ final Color HIDDEN_COLOUR; // colour for hidden regions
+
+ boolean useLegacy = false;
+
+ public static final Color OVERVIEW_DEFAULT_GAP = Color.lightGray;
+
+ public static final Color OVERVIEW_DEFAULT_LEGACY_GAP = Color.white;
+
+ public static final Color OVERVIEW_DEFAULT_HIDDEN = Color.darkGray
+ .darker();
+
+ /**
+ * Constructor without colour settings (used by applet)
+ */
+ public OverviewResColourFinder()
+ {
+ this(false, OVERVIEW_DEFAULT_GAP, OVERVIEW_DEFAULT_HIDDEN);
+ }
+
+ /**
+ * Constructor with colour settings
+ *
+ * @param useLegacyColouring
+ * whether to use legacy gap colouring (white gaps, grey residues)
+ * @param gapCol
+ * gap colour if not legacy
+ * @param hiddenCol
+ * hidden region colour (transparency applied by rendering code)
+ */
+ public OverviewResColourFinder(boolean useLegacyColouring, Color gapCol,
+ Color hiddenCol)
+ {
+ if (useLegacyColouring)
+ {
+ GAP_COLOUR = Color.white;
+ RESIDUE_COLOUR = Color.lightGray;
+ HIDDEN_COLOUR = hiddenCol;
+ }
+ else
+ {
+ GAP_COLOUR = gapCol;
+ RESIDUE_COLOUR = Color.white;
+ HIDDEN_COLOUR = hiddenCol;
+ }
+ }
+
+ @Override
+ public Color getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
+ {
+ Color resBoxColour = RESIDUE_COLOUR;
+ char currentChar = seq.getCharAt(i);
+
+ // In the overview window, gaps are coloured grey, unless the colour scheme
+ // specifies a gap colour, in which case gaps honour the colour scheme
+ // settings
+ if (shader.getColourScheme() != null)
+ {
+ if (Comparison.isGap(currentChar)
+ && (!shader.getColourScheme().hasGapColour()))
+ {
+ resBoxColour = GAP_COLOUR;
+ }
+ else
+ {
+ resBoxColour = shader.findColour(currentChar, i, seq);
+ }
+ }
+ else if (Comparison.isGap(currentChar))
+ {
+ resBoxColour = GAP_COLOUR;
+ }
+
+ return resBoxColour;
+ }
+
+ /**
+ * {@inheritDoc} In the overview, the showBoxes setting is ignored, as the
+ * overview displays the colours regardless.
+ */
+ @Override
+ protected Color getResidueBoxColour(boolean showBoxes,
+ ResidueShaderI shader,
+ SequenceGroup[] allGroups, SequenceI seq, int i)
+ {
+ ResidueShaderI currentShader;
+ SequenceGroup currentSequenceGroup = getCurrentSequenceGroup(allGroups,
+ i);
+ if (currentSequenceGroup != null)
+ {
+ currentShader = currentSequenceGroup.getGroupColourScheme();
+ }
+ else
+ {
+ currentShader = shader;
+ }
+
+ return getBoxColour(currentShader, seq, i);
+ }
+
+ /**
+ * Supply hidden colour
+ *
+ * @return colour of hidden regions
+ */
+ protected Color getHiddenColour()
+ {
+ return HIDDEN_COLOUR;
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
+
+import java.awt.Color;
+
+public class ResidueColourFinder
+{
+ public ResidueColourFinder()
+ {
+ }
+
+ /**
+ * Get the colour of a residue in a sequence
+ *
+ * @param showBoxes
+ * true if the viewport's Show Boxes setting is true
+ * @param shader
+ * the viewport's colour scheme
+ * @param allGroups
+ * all the groups which seq participates in
+ * @param seq
+ * the sequence containing the residue
+ * @param position
+ * the position of the residue in the sequence
+ * @param finder
+ * FeatureColourFinder for the viewport
+ * @return colour of the residue
+ */
+ public Color getResidueColour(boolean showBoxes, ResidueShaderI shader,
+ SequenceGroup[] allGroups,
+ final SequenceI seq, int position, FeatureColourFinder finder)
+ {
+ Color col = getResidueBoxColour(showBoxes, shader, allGroups, seq,
+ position);
+
+ // if there's a FeatureColourFinder we might override the residue colour
+ // here with feature colouring
+ if (finder != null)
+ {
+ col = finder.findFeatureColour(col, seq, position);
+ }
+ return col;
+ }
+
+ /**
+ * Get the residue colour without accounting for any features
+ *
+ * @param showBoxes
+ * true if the viewport's Show Boxes setting is true
+ * @param shader
+ * the viewport's colour scheme
+ * @param allGroups
+ * all the groups which seq participates in
+ * @param seq
+ * the sequence containing the residue
+ * @param i
+ * the position of the residue in the sequence
+ * @return
+ */
+ protected Color getResidueBoxColour(boolean showBoxes,
+ ResidueShaderI shader,
+ SequenceGroup[] allGroups,
+ SequenceI seq, int i)
+ {
+ SequenceGroup currentSequenceGroup = getCurrentSequenceGroup(allGroups,
+ i);
+ if (currentSequenceGroup != null)
+ {
+ if (currentSequenceGroup.getDisplayBoxes())
+ {
+ return getBoxColour(currentSequenceGroup.getGroupColourScheme(),
+ seq, i);
+ }
+ }
+ else if (showBoxes)
+ {
+ return getBoxColour(shader, seq, i);
+ }
+
+ return Color.white;
+ }
+
+ /**
+ * Search all the groups for a sequence to find the one which a given res
+ * falls into
+ *
+ * @param allGroups
+ * all the groups a sequence participates in
+ * @param res
+ * the residue to search for
+ * @return a sequence group for res, or null if no sequence group applies
+ */
+ public SequenceGroup getCurrentSequenceGroup(SequenceGroup[] allGroups,
+ int res)
+ {
+ if (allGroups == null)
+ {
+ return null;
+ }
+
+ for (int i = 0; i < allGroups.length; i++)
+ {
+ if ((allGroups[i].getStartRes() <= res)
+ && (allGroups[i].getEndRes() >= res))
+ {
+ return (allGroups[i]);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param shader
+ * the viewport's colour scheme
+ * @param seq
+ * the sequence containing the residue
+ * @param i
+ * the position of the residue in the sequence
+ */
+ public Color getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
+ {
+ Color resBoxColour = Color.white;
+ if (shader.getColourScheme() != null)
+ {
+ resBoxColour = shader.findColour(seq.getCharAt(i), i, seq);
+ }
+ return resBoxColour;
+ }
+
+}
@Override
public Color findColour(char symbol, int position, SequenceI seq)
{
+ if (colourScheme == null)
+ {
+ return Color.white; // Colour is 'None'
+ }
+
/*
* get 'base' colour
*/
: profile.getModalResidue();
float pid = profile == null ? 0f
: profile.getPercentageIdentity(ignoreGaps);
- Color colour = colourScheme == null ? Color.white
- : colourScheme.findColour(symbol, position, seq, modalResidue,
- pid);
+ Color colour = colourScheme.findColour(symbol, position, seq,
+ modalResidue, pid);
/*
* apply PID threshold and consensus fading if in force
*/
- colour = adjustColour(symbol, position, colour);
+ if (!Comparison.isGap(symbol))
+ {
+ colour = adjustColour(symbol, position, colour);
+ }
return colour;
}
}
/**
-<<<<<<< HEAD
-=======
- * Answers true if the feature belongs to a feature group which is not
- * currently displayed, else false
- *
- * @param sequenceFeature
- * @return
- */
- @Override
- protected boolean featureGroupNotShown(
- final SequenceFeature sequenceFeature)
- {
- return featureGroups != null && sequenceFeature.featureGroup != null
- && sequenceFeature.featureGroup.length() != 0
- && featureGroups.containsKey(sequenceFeature.featureGroup)
- && !featureGroups.get(sequenceFeature.featureGroup)
- .booleanValue();
- }
-
- /**
->>>>>>> refs/heads/develop
* Called when alignment in associated view has new/modified features to
* discover and display.
*
* @return
*/
boolean isSimple();
+
+ /**
+ * Answers true if the colour scheme has a colour specified for gaps.
+ *
+ * @return
+ */
+ boolean hasGapColour();
}
{
return true;
}
+
+ /**
+ * Default method returns false. Override this to return true in colour
+ * schemes that have a colour associated with gap residues.
+ */
+ @Override
+ public boolean hasGapColour()
+ {
+ return false;
+ }
}
/*
* step 1: build a map from colours to the symbol(s) that have the colour
*/
- Map<Color, List<String>> colours = new HashMap<Color, List<String>>();
+ Map<Color, List<String>> colours = new HashMap<>();
for (char symbol = 'A'; symbol <= 'Z'; symbol++)
{
/*
* step 2: make a list of { A,G,R=12f9d6 } residues/colour specs
*/
- List<String> residueColours = new ArrayList<String>();
+ List<String> residueColours = new ArrayList<>();
for (Entry<Color, List<String>> cols : colours.entrySet())
{
boolean first = true;
Collections.sort(residueColours);
return StringUtils.listToDelimitedString(residueColours, ";");
}
+
+ @Override
+ public boolean hasGapColour()
+ {
+ return (findColour(' ') != null);
+ }
}
* - one or more sequences to be mapped to pdbFile
* @param targetChainIds
* - optional chain specification for mapping each sequence to pdb
- * (may be nill, individual elements may be nill)
+ * (may be nill, individual elements may be nill) - JBPNote: JAL-2693
+ * - this should be List<List<String>>, empty lists indicate no
+ * predefined mappings
* @param pdbFile
* - structure data resource
* @param sourceType
* @param ssm
* @param pdbentry
* @param sequenceIs
- * @param chains
* @param protocol
*/
public AAStructureBindingModel(StructureSelectionManager ssm,
this.nucleotide = Comparison.isNucleotide(sequenceIs);
this.pdbEntry = pdbentry;
this.protocol = protocol;
+ resolveChains();
}
+ private boolean resolveChains()
+ {
+ /**
+ * final count of chain mappings discovered
+ */
+ int chainmaps = 0;
+ // JBPNote: JAL-2693 - this should be a list of chain mappings per
+ // [pdbentry][sequence]
+ String[][] newchains = new String[pdbEntry.length][];
+ int pe = 0;
+ for (PDBEntry pdb : pdbEntry)
+ {
+ SequenceI[] seqsForPdb = sequence[pe];
+ if (seqsForPdb != null)
+ {
+ newchains[pe] = new String[seqsForPdb.length];
+ int se = 0;
+ for (SequenceI asq : seqsForPdb)
+ {
+ String chain = (chains != null && chains[pe] != null)
+ ? chains[pe][se]
+ : null;
+ SequenceI sq = (asq.getDatasetSequence() == null) ? asq
+ : asq.getDatasetSequence();
+ if (sq.getAllPDBEntries() != null)
+ {
+ for (PDBEntry pdbentry : sq.getAllPDBEntries())
+ {
+ if (pdb.getFile() != null && pdbentry.getFile() != null
+ && pdb.getFile().equals(pdbentry.getFile()))
+ {
+ String chaincode = pdbentry.getChainCode();
+ if (chaincode != null && chaincode.length() > 0)
+ {
+ chain = chaincode;
+ chainmaps++;
+ break;
+ }
+ }
+ }
+ }
+ newchains[pe][se] = chain;
+ se++;
+ }
+ pe++;
+ }
+ }
+
+ chains = newchains;
+ return chainmaps > 0;
+ }
public StructureSelectionManager getSsm()
{
return ssm;
*/
public class Platform
{
- private static Boolean isAMac = null;
+ private static Boolean isAMac = null, isWindows = null;
private static Boolean isHeadless = null;
{
isAMac = System.getProperty("os.name").indexOf("Mac") > -1;
}
+
return isAMac.booleanValue();
}
+ /**
+ * Check if we are on a Microsoft plaform...
+ *
+ * @return true if we have to cope with another platform variation
+ */
+ public static boolean isWindows()
+ {
+ if (isWindows == null)
+ {
+ isWindows = System.getProperty("os.name").indexOf("Win") > -1;
+ }
+ return isWindows.booleanValue();
+ }
+
+ /**
+ *
+ * @return true if we are running in non-interactive no UI mode
+ */
public static boolean isHeadless()
{
if (isHeadless == null)
* Default sequence URL link string for EMBL-EBI search
*/
public static final String DEFAULT_STRING = DEFAULT_LABEL
- + "|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$";
+ + "|https://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$";
/*
* not instantiable
File reply) throws Exception
{
EmblFile efile = null;
- List<SequenceI> seqs = new ArrayList<SequenceI>();
+ List<SequenceI> seqs = new ArrayList<>();
if (reply != null && reply.exists())
{
* EmbFile reads something like (e.g.) this ungrammatical phrase
* Entry: <acc> display type is either not supported or entry is not found.
*/
- List<SequenceI> peptides = new ArrayList<SequenceI>();
+ List<SequenceI> peptides = new ArrayList<>();
if (efile != null && efile.getEntries() != null)
{
for (EmblEntry entry : efile.getEntries())
import jalview.datamodel.xdb.uniprot.UniprotEntry;
import jalview.datamodel.xdb.uniprot.UniprotFeature;
import jalview.datamodel.xdb.uniprot.UniprotFile;
-import jalview.ws.ebi.EBIFetchClient;
import jalview.ws.seqfetcher.DbSourceProxyImpl;
-import java.io.File;
-import java.io.FileReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
+import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Vector;
queries = queries.toUpperCase().replaceAll(
"(UNIPROT\\|?|UNIPROT_|UNIREF\\d+_|UNIREF\\d+\\|?)", "");
AlignmentI al = null;
- EBIFetchClient ebi = new EBIFetchClient();
- // uniprotxml parameter required since december 2007
- // uniprotkb dbname changed introduced december 2008
- File file = ebi.fetchDataAsFile("uniprotkb:" + queries, "uniprotxml",
- "xml");
+
+ String downloadstring = "http://www.uniprot.org/uniprot/" + queries
+ + ".xml";
+ URL url = null;
+ URLConnection urlconn = null;
+
+ url = new URL(downloadstring);
+ urlconn = url.openConnection();
+ InputStream istr = urlconn.getInputStream();
Vector<UniprotEntry> entries = getUniprotEntries(
- new FileReader(file));
+ new InputStreamReader(istr, "UTF-8"));
if (entries != null)
{
- ArrayList<SequenceI> seqs = new ArrayList<SequenceI>();
+ ArrayList<SequenceI> seqs = new ArrayList<>();
for (UniprotEntry entry : entries)
{
seqs.add(uniprotEntryToSequenceI(entry));
return al;
} catch (Exception e)
{
- stopQuery();
throw (e);
+ } finally
+ {
+ stopQuery();
}
}
sequence.setDescription(getUniprotEntryDescription(entry));
final String dbVersion = getDbVersion();
- ArrayList<DBRefEntry> dbRefs = new ArrayList<DBRefEntry>();
+ ArrayList<DBRefEntry> dbRefs = new ArrayList<>();
for (String accessionId : entry.getAccession())
{
DBRefEntry dbRef = new DBRefEntry(DBRefSource.UNIPROT, dbVersion,
dbRefs.add(dbRef);
}
- Vector<PDBEntry> onlyPdbEntries = new Vector<PDBEntry>();
+ Vector<PDBEntry> onlyPdbEntries = new Vector<>();
for (PDBEntry pdb : entry.getDbReference())
{
DBRefEntry dbr = new DBRefEntry();
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
{
URL rcall = new URL(url);
- InputStream is = new BufferedInputStream(rcall.openStream());
+ HttpURLConnection conn = (HttpURLConnection) rcall.openConnection();
+ int responseCode = conn.getResponseCode();
+ if (responseCode != 200)
+ {
+ System.err.println("Warning: response code " + responseCode
+ + " for " + url);
+ }
+ InputStream is = new BufferedInputStream(conn.getInputStream());
if (outFile != null)
{
FileOutputStream fio = new FileOutputStream(outFile);
if (database.equalsIgnoreCase(DBRefSource.EMBL)
|| database.equalsIgnoreCase(DBRefSource.EMBLCDS))
{
- url = "http://www.ebi.ac.uk/ena/data/view/" + ids.toLowerCase()
+ url = "https://www.ebi.ac.uk/ena/data/view/" + ids.toLowerCase()
+ (format != null ? "&" + format : "");
}
else
{
- url = "http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/"
+ url = "https://www.ebi.ac.uk/Tools/dbfetch/dbfetch/"
+ database.toLowerCase() + "/" + ids.toLowerCase()
+ (format != null ? "/" + format : "");
}
*/
public SequenceI[] getSequences(List<DBRefEntry> refs, boolean dna)
{
- Vector<SequenceI> rseqs = new Vector<SequenceI>();
- Hashtable<String, List<String>> queries = new Hashtable<String, List<String>>();
+ Vector<SequenceI> rseqs = new Vector<>();
+ Hashtable<String, List<String>> queries = new Hashtable<>();
for (DBRefEntry ref : refs)
{
- if (!queries.containsKey(ref.getSource()))
+ String canonical = DBRefUtils.getCanonicalName(ref.getSource());
+ if (!queries.containsKey(canonical))
{
- queries.put(ref.getSource(), new ArrayList<String>());
+ queries.put(canonical, new ArrayList<String>());
}
- List<String> qset = queries.get(ref.getSource());
+ List<String> qset = queries.get(canonical);
if (!qset.contains(ref.getAccessionId()))
{
qset.add(ref.getAccessionId());
continue;
}
- Stack<String> queriesLeft = new Stack<String>();
+ Stack<String> queriesLeft = new Stack<>();
queriesLeft.addAll(query);
List<DbSourceProxy> proxies = getSourceProxy(db);
for (DbSourceProxy fetcher : proxies)
{
- List<String> queriesMade = new ArrayList<String>();
- HashSet<String> queriesFound = new HashSet<String>();
+ List<String> queriesMade = new ArrayList<>();
+ HashSet<String> queriesFound = new HashSet<>();
try
{
if (fetcher.isDnaCoding() != dna)
Map<String, DbSourceProxy> dblist = fetchableDbs.get(db);
if (dblist == null)
{
- return new ArrayList<DbSourceProxy>();
+ return new ArrayList<>();
}
/*
* sort so that primary sources precede secondary
*/
- List<DbSourceProxy> dbs = new ArrayList<DbSourceProxy>(dblist.values());
+ List<DbSourceProxy> dbs = new ArrayList<>(dblist.values());
Collections.sort(dbs, proxyComparator);
return dbs;
}
{
if (fetchableDbs == null)
{
- fetchableDbs = new Hashtable<String, Map<String, DbSourceProxy>>();
+ fetchableDbs = new Hashtable<>();
}
Map<String, DbSourceProxy> slist = fetchableDbs
.get(proxy.getDbSource());
if (slist == null)
{
fetchableDbs.put(proxy.getDbSource(),
- slist = new Hashtable<String, DbSourceProxy>());
+ slist = new Hashtable<>());
}
slist.put(proxy.getDbName(), proxy);
}
return null;
}
String[] sources = null;
- Vector<String> src = new Vector<String>();
+ Vector<String> src = new Vector<>();
Enumeration<String> dbs = fetchableDbs.keys();
while (dbs.hasMoreElements())
{
public DbSourceProxy[] getDbSourceProxyInstances(Class class1)
{
- List<DbSourceProxy> prlist = new ArrayList<DbSourceProxy>();
+ List<DbSourceProxy> prlist = new ArrayList<>();
for (String fetchable : getSupportedDb())
{
for (DbSourceProxy pr : getSourceProxy(fetchable))
SequenceFeature sfContactFG = new SequenceFeature("Disulfide Bond",
"desc", 13, 14, 2f, null);
sq.addSequenceFeature(sfContactFG);
+ // add single position feature at [I]
+ SequenceFeature sfI = new SequenceFeature("Disulfide Bond",
+ "desc", 16, 16, null);
+ sq.addSequenceFeature(sfI);
// no features in columns 1-2 (-A)
List<SequenceFeature> found = sq.findFeatures(1, 2);
// columns 10-11 (--) should find nothing
found = sq.findFeatures(10, 11);
assertEquals(0, found.size());
+
+ // columns 14-14 (I) should find variant feature
+ found = sq.findFeatures(14, 14);
+ assertEquals(1, found.size());
+ assertTrue(found.contains(sfI));
}
@Test(groups = { "Functional" })
assertEquals(features.size(), 2);
assertTrue(features.contains(sf2));
assertTrue(features.contains(sf3));
+
+ features = store.getFeaturesByOntology("sequence_variant");
+ assertTrue(features.isEmpty());
}
@Test(groups = "Functional")
*/
package jalview.gui;
-import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.Assert.assertEquals;
+import jalview.bin.Jalview;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
+import jalview.renderer.ResidueShader;
+import jalview.renderer.ResidueShaderI;
import jalview.schemes.ZappoColourScheme;
import java.awt.Color;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class SequenceRendererTest
{
+ AlignmentI al;
+ AlignViewport av;
+
+ SequenceI seq1;
@BeforeClass(alwaysRun = true)
- public void setUpJvOptionPane()
+ public static void setUpBeforeClass() throws Exception
{
- JvOptionPane.setInteractiveMode(false);
- JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+ Jalview.main(
+ new String[]
+ { "-nonews", "-props", "test/jalview/testProps.jvprops" });
}
- @Test(groups = { "Functional" })
- public void testGetResidueBoxColour_zappo()
+ @BeforeMethod(alwaysRun = true)
+ public void setUp()
{
- SequenceI seq = new Sequence("name", "MATVLGSPRAPAFF"); // FER1_MAIZE...
- AlignmentI al = new Alignment(new SequenceI[] { seq });
- final AlignViewport av = new AlignViewport(al);
- SequenceRenderer sr = new SequenceRenderer(av);
- av.setGlobalColourScheme(new ZappoColourScheme());
-
- // @see ResidueProperties.zappo
- assertEquals(Color.pink, sr.getResidueBoxColour(seq, 0)); // M
- assertEquals(Color.green, sr.getResidueBoxColour(seq, 2)); // T
- assertEquals(Color.magenta, sr.getResidueBoxColour(seq, 5)); // G
- assertEquals(Color.orange, sr.getResidueBoxColour(seq, 12)); // F
+ seq1 = new Sequence("Seq1", "ABCEEEABCABC");
+ SequenceI seq2 = new Sequence("Seq2", "ABCABCABCABC");
+ SequenceI seq3 = new Sequence("Seq3", "ABCABCABCABC");
+ SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3 };
+ al = new Alignment(seqs);
+ al.setDataset(null);
+ av = new AlignViewport(al);
}
- @Test(groups = { "Functional" })
- public void testGetResidueBoxColour_none()
+ @Test(groups = "Functional")
+ public void testGetResidueColour_WithGroup()
{
- SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
- AlignmentI al = new Alignment(new SequenceI[] { seq });
- final AlignViewport av = new AlignViewport(al);
SequenceRenderer sr = new SequenceRenderer(av);
+ SequenceGroup sg = new SequenceGroup();
+ sg.addSequence(seq1, false);
+ sg.setStartRes(3);
+ sg.setEndRes(5);
- assertEquals(Color.white, sr.getResidueBoxColour(seq, 0));
- assertEquals(Color.white, sr.getResidueBoxColour(seq, 2));
+ ResidueShaderI rs = new ResidueShader();
+ rs.setColourScheme(new ZappoColourScheme());
+ sg.setGroupColourScheme(rs);
- // set for overview
- sr.forOverview = true;
- assertEquals(Color.lightGray, sr.getResidueBoxColour(seq, 0));
- assertEquals(Color.white, sr.getResidueBoxColour(seq, 2));
- }
+ av.getAlignment().addGroup(sg);
- // TODO more tests for getResidueBoxColour covering groups, feature rendering,
- // gaps, overview...
+ // outside group residues are white
+ assertEquals(Color.white, sr.getResidueColour(seq1, 1, null));
+ // within group use Zappo scheme - E = red
+ assertEquals(Color.red, sr.getResidueColour(seq1, 3, null));
+ }
}
import jalview.gui.Desktop;
import jalview.gui.Jalview2XML;
import jalview.gui.JvOptionPane;
+import jalview.util.DBRefUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public void testRetrieveAndShowCrossref() throws Exception
{
- List<String> failedDBRetr = new ArrayList<String>();
- List<String> failedXrefMenuItems = new ArrayList<String>();
- List<String> failedProjectRecoveries = new ArrayList<String>();
-
+ List<String> failedDBRetr = new ArrayList<>();
+ List<String> failedXrefMenuItems = new ArrayList<>();
+ List<String> failedProjectRecoveries = new ArrayList<>();
+ // only search for ensembl or Uniprot crossrefs
+ List<String> limit=Arrays.asList(new String[] {
+ DBRefUtils.getCanonicalName("ENSEMBL"),
+ DBRefUtils.getCanonicalName("Uniprot")});
// for every set of db queries
// retrieve db query
// verify presence of expected xrefs
// . codonframes
//
//
- HashMap<String, String> dbtoviewBit = new HashMap<String, String>();
- List<String> keyseq = new ArrayList<String>();
- HashMap<String, File> savedProjects = new HashMap<String, File>();
+ HashMap<String, String> dbtoviewBit = new HashMap<>();
+ List<String> keyseq = new ArrayList<>();
+ HashMap<String, File> savedProjects = new HashMap<>();
- for (String[] did : new String[][] { { "ENSEMBL", "ENSG00000157764" },
- { "UNIPROT", "P01731" } })
+ for (String[] did : new String[][] { { "UNIPROT", "P00338" } })
{
// pass counters - 0 - first pass, 1 means retrieve project rather than
// perform action
ptypes = (seqs == null || seqs.length == 0) ? null : new CrossRef(
seqs, dataset).findXrefSourcesForSequences(dna);
-
+ filterDbRefs(ptypes, limit);
+
// start of pass2: retrieve each cross-ref for fetched or restored
// project.
do // first cross ref and recover crossref loop
// build next key so we an retrieve all views
String nextxref = first + " -> " + db + "{" + firstcr_ap + "}";
// perform crossref action, or retrieve stored project
- List<AlignmentViewPanel> cra_views = new ArrayList<AlignmentViewPanel>();
+ List<AlignmentViewPanel> cra_views = new ArrayList<>();
CrossRefAction cra = null;
if (pass2 == 0)
}
}
- HashMap<String, List<String>> xrptypes = new HashMap<String, List<String>>();
+ HashMap<String, List<String>> xrptypes = new HashMap<>();
// first save/verify views.
for (AlignmentViewPanel avp : cra_views)
{
nextxref = first + " -> " + db + "{" + firstcr_ap++ + "}";
for (String xrefdb : xrptypes.get(nextxref))
{
- List<AlignmentViewPanel> cra_views2 = new ArrayList<AlignmentViewPanel>();
+ List<AlignmentViewPanel> cra_views2 = new ArrayList<>();
int q = 0;
String nextnextxref = nextxref + " -> " + xrefdb + "{"
+ q + "}";
}
}
+ private void filterDbRefs(List<String> ptypes, List<String> limit)
+ {
+ if (limit != null)
+ {
+ int p = 0;
+ while (ptypes.size() > p)
+ {
+ if (!limit.contains(ptypes.get(p)))
+ {
+ ptypes.remove(p);
+ }
+ else
+ {
+ p++;
+ }
+ }
+ }
+ }
+
/**
* wrapper to trap known defect for AH002001 testcase
*
private void assertType(boolean expectProtein,
AlignmentViewPanel alignmentViewPanel, String message)
{
- List<SequenceI> nonType = new ArrayList<SequenceI>();
+ List<SequenceI> nonType = new ArrayList<>();
for (SequenceI sq : alignmentViewPanel.getAlignViewport()
.getAlignment().getSequences())
{
import jalview.datamodel.SequenceI;
import jalview.datamodel.features.SequenceFeatures;
import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
import jalview.gui.JvOptionPane;
+import jalview.structure.StructureSelectionManager;
import java.awt.Color;
import java.io.File;
import java.util.List;
import java.util.Map;
+import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class FeaturesFileTest
{
+ private static String simpleGffFile = "examples/testdata/simpleGff3.gff";
+
+ @AfterClass(alwaysRun = true)
+ public void tearDownAfterClass()
+ {
+ /*
+ * remove any sequence mappings created so they don't pollute other tests
+ */
+ StructureSelectionManager ssm = StructureSelectionManager
+ .getStructureSelectionManager(Desktop.instance);
+ ssm.resetAll();
+ }
@BeforeClass(alwaysRun = true)
public void setUpJvOptionPane()
JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
}
- private static String simpleGffFile = "examples/testdata/simpleGff3.gff";
-
@Test(groups = { "Functional" })
public void testParse() throws Exception
{
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.gui.JvOptionPane;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.UserColourScheme;
+import jalview.schemes.ZappoColourScheme;
+
+import java.awt.Color;
+import java.util.ArrayList;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class OverviewResColourFinderTest
+{
+
+ @BeforeClass(alwaysRun = true)
+ public void setUpJvOptionPane()
+ {
+ JvOptionPane.setInteractiveMode(false);
+ JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+ Cache.loadProperties("test/jalview/io/testProps.jvprops");
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetResidueBoxColour_none()
+ {
+ SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+ ResidueColourFinder rcf = new OverviewResColourFinder();
+
+ // gaps are grey, residues white
+ assertEquals(Color.white, rcf.getResidueColour(true,
+ av.getResidueShading(),
+ null, seq, 0, null));
+ assertEquals(Color.lightGray, rcf
+ .getResidueColour(true, av.getResidueShading(), null, seq, 2,
+ null));
+
+ // unaffected by showBoxes setting
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 0, null));
+ assertEquals(Color.lightGray, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 2, null));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetResidueBoxColour_zappo()
+ {
+ SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+ // gap
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+ ResidueColourFinder rcf = new OverviewResColourFinder();
+ av.setGlobalColourScheme(new ZappoColourScheme());
+
+ // @see ResidueProperties.zappo
+ assertEquals(Color.pink,
+ rcf.getResidueColour(true, av.getResidueShading(),
+ null, seq, 0, null)); // M
+ assertEquals(Color.green,
+ rcf.getResidueColour(true, av.getResidueShading(),
+ null, seq, 2, null)); // T
+ assertEquals(Color.magenta,
+ rcf.getResidueColour(true, av.getResidueShading(),
+ null, seq, 5, null)); // G
+ assertEquals(Color.orange,
+ rcf.getResidueColour(true, av.getResidueShading(),
+ null, seq, 12, null)); // F
+
+ // gap colour not specified so gaps are lightGray
+ assertEquals(Color.lightGray, rcf
+ .getResidueColour(true, av.getResidueShading(), null, seq, 3,
+ null));
+
+ // unaffected by showBoxes setting
+ assertEquals(Color.pink, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 0, null)); // M
+ assertEquals(Color.green, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 2, null)); // T
+ assertEquals(Color.magenta, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 5, null)); // G
+ assertEquals(Color.orange, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 12, null)); // F
+
+ // gap colour not specified so gaps are lightGray
+ assertEquals(Color.lightGray, rcf
+ .getResidueColour(false, av.getResidueShading(), null, seq, 3,
+ null));
+
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetResidueBoxColour_userdef()
+ {
+ SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+ // gap
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+ ResidueColourFinder rcf = new OverviewResColourFinder();
+
+ Color[] newColours = new Color[24];
+ for (int i = 0; i < 24; i++)
+ {
+ newColours[i] = null;
+ }
+
+ av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+ // gap colour not specified so gaps are lightGray
+ assertEquals(Color.lightGray, rcf
+ .getResidueColour(true, av.getResidueShading(), null, seq, 3,
+ null));
+
+ newColours[23] = Color.pink;
+ av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+ // gap colour specified as pink
+ assertEquals(Color.pink, rcf.getResidueColour(true,
+ av.getResidueShading(),
+ null, seq, 3, null));
+
+ // unaffected by showBoxes setting
+ // gap colour not specified so gaps are lightGray
+ newColours[23] = null;
+ assertEquals(Color.lightGray, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 3, null));
+
+ newColours[23] = Color.pink;
+ av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+ // gap colour specified as pink
+ assertEquals(Color.pink, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 3, null));
+ }
+
+ @Test
+ public void testGetResidueBoxColour_group()
+ {
+ SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+
+ ColourSchemeI cs = new ZappoColourScheme();
+ ArrayList<SequenceI> seqlist = new ArrayList<>();
+ seqlist.add(seq);
+ SequenceGroup sg = new SequenceGroup(seqlist, "testgroup", cs, true,
+ true, true, 5, 9);
+ al.addGroup(sg);
+ SequenceGroup[] groups = new SequenceGroup[1];
+ groups[0] = sg;
+
+ final AlignViewport av = new AlignViewport(al);
+ ResidueColourFinder rcf = new OverviewResColourFinder();
+
+ // G in group specified as magenta in Zappo
+ assertEquals(Color.magenta, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 7, null));
+
+ // Residue outside group coloured white
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 0, null));
+
+ // Gap outside group coloured lightgray
+ assertEquals(Color.lightGray, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 2, null));
+
+ // use legacy colouring
+ rcf = new OverviewResColourFinder(true, Color.blue, Color.red);
+
+ // G in group specified as magenta in Zappo
+ assertEquals(Color.magenta, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 7, null));
+
+ // Residue outside group coloured lightgray
+ assertEquals(Color.lightGray, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 0, null));
+
+ // Gap outside group coloured white
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 2, null));
+
+ // use new colouring
+ rcf = new OverviewResColourFinder(false, Color.blue, Color.red);
+
+ // G in group specified as magenta in Zappo
+ assertEquals(Color.magenta, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 7, null));
+
+ // Residue outside group coloured white
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 0, null));
+
+ // Gap outside group coloured blue
+ assertEquals(Color.blue, rcf.getResidueColour(false,
+ av.getResidueShading(), groups, seq, 2, null));
+ }
+
+ @Test
+ public void testGetBoxColour()
+ {
+ SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+ // gap
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+
+ // non-legacy colouring
+ ResidueColourFinder rcf = new OverviewResColourFinder();
+ ResidueShaderI shader = new ResidueShader();
+
+ // residues white
+ Color c = rcf.getBoxColour(shader, seq, 0);
+ assertEquals(Color.white, c);
+
+ // gaps gap colour
+ c = rcf.getBoxColour(shader, seq, 3);
+ assertEquals(
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP,
+ c);
+
+ // legacy colouring set explicitly via constructor
+ rcf = new OverviewResColourFinder(true, Color.blue, Color.red);
+ shader = new ResidueShader();
+
+ // residues light gray
+ c = rcf.getBoxColour(shader, seq, 0);
+ assertEquals(Color.lightGray, c);
+
+ // gaps white
+ c = rcf.getBoxColour(shader, seq, 3);
+ assertEquals(Color.white, c);
+
+ // legacy colouring off
+ rcf = new OverviewResColourFinder();
+ shader = new ResidueShader();
+
+ // residues white
+ c = rcf.getBoxColour(shader, seq, 0);
+ assertEquals(Color.white, c);
+
+ // gaps gap colour
+ c = rcf.getBoxColour(shader, seq, 3);
+ assertEquals(
+ jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP,
+ c);
+
+ // non legacy colouring with colour scheme
+ rcf = new OverviewResColourFinder(false, Color.blue, Color.red);
+ shader = new ResidueShader(new ZappoColourScheme());
+
+ // M residue pink
+ c = rcf.getBoxColour(shader, seq, 0);
+ assertEquals(Color.pink, c);
+
+ // gaps blue
+ c = rcf.getBoxColour(shader, seq, 3);
+ assertEquals(Color.blue, c);
+
+ // legacy colouring with colour scheme
+ rcf = new OverviewResColourFinder(true, Color.blue, Color.red);
+
+ // M residue pink
+ c = rcf.getBoxColour(shader, seq, 0);
+ assertEquals(Color.pink, c);
+
+ // gaps white
+ c = rcf.getBoxColour(shader, seq, 3);
+ assertEquals(Color.white, c);
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.gui.JvOptionPane;
+import jalview.schemes.UserColourScheme;
+import jalview.schemes.ZappoColourScheme;
+
+import java.awt.Color;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class ResidueColourFinderTest
+{
+
+ @BeforeClass(alwaysRun = true)
+ public void setUpJvOptionPane()
+ {
+ JvOptionPane.setInteractiveMode(false);
+ JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetResidueColour_zappo()
+ {
+ SequenceI seq = new Sequence("name", "MATVLGSPRAPAFF"); // FER1_MAIZE...
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+ ResidueColourFinder rcf = new ResidueColourFinder();
+ av.setGlobalColourScheme(new ZappoColourScheme());
+
+ // @see ResidueProperties.zappo
+ assertEquals(Color.pink,
+ rcf.getResidueColour(true, av.getResidueShading(), null, seq, 0,
+ null)); // M
+ assertEquals(Color.green,
+ rcf.getResidueColour(true, av.getResidueShading(), null, seq, 2,
+ null)); // T
+ assertEquals(Color.magenta,
+ rcf.getResidueColour(true, av.getResidueShading(), null, seq, 5,
+ null)); // G
+ assertEquals(Color.orange,
+ rcf.getResidueColour(true, av.getResidueShading(), null, seq,
+ 12,
+ null)); // F
+
+ // everything is white if showBoxes is false
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 0, null)); // M
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 2, null)); // T
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 5, null)); // G
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 12, null)); // F
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetResidueColour_none()
+ {
+ SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+ ResidueColourFinder rcf = new ResidueColourFinder();
+
+ assertEquals(Color.white,
+ rcf.getResidueColour(true, av.getResidueShading(),
+ null, seq, 0, null));
+ assertEquals(Color.white,
+ rcf.getResidueColour(true, av.getResidueShading(),
+ null, seq, 2, null));
+
+ // no change if showBoxes is false
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 0, null));
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 2, null));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetResidueColour_userdef()
+ {
+ SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
+ // gap
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+ ResidueColourFinder rcf = new ResidueColourFinder();
+
+ Color[] newColours = new Color[24];
+ for (int i = 0; i < 24; i++)
+ {
+ newColours[i] = null;
+ }
+
+ av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+ // gap colour not specified so gap colour is null
+ // this is consistent with previous behaviour, but may not be correct?
+ assertEquals(null, rcf.getResidueColour(true, av.getResidueShading(),
+ null, seq, 3, null));
+
+ newColours[23] = Color.pink;
+ av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+ // gap colour specified as pink
+ assertEquals(Color.pink, rcf.getResidueColour(true,
+ av.getResidueShading(),
+ null, seq, 3, null));
+
+ // everything is white if showBoxes is false
+ newColours[23] = null;
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(),
+ null, seq, 3, null));
+
+ newColours[23] = Color.pink;
+ av.setGlobalColourScheme(new UserColourScheme(newColours));
+
+ // gap colour specified as pink
+ assertEquals(Color.white, rcf.getResidueColour(false,
+ av.getResidueShading(), null, seq, 3, null));
+ }
+
+ // TODO more tests for getResidueColour covering groups, feature rendering...
+}
import jalview.datamodel.Profile;
import jalview.datamodel.ProfileI;
import jalview.datamodel.Profiles;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.ResidueCount;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
+import jalview.schemes.ColourSchemeI;
import jalview.schemes.PIDColourScheme;
+import jalview.schemes.ResidueProperties;
+import jalview.schemes.UserColourScheme;
+import jalview.schemes.ZappoColourScheme;
import java.awt.Color;
import java.util.Collections;
assertEquals(Color.WHITE, ccs.applyConservation(colour, 12));
}
+ @Test(groups = "Functional")
+ public void testFindColour_gapColour()
+ {
+ /*
+ * normally, a gap is coloured white
+ */
+ ResidueShader rs = new ResidueShader(new ZappoColourScheme());
+ assertEquals(Color.white, rs.findColour(' ', 7, null));
+
+ /*
+ * a User Colour Scheme may specify a bespoke gap colour
+ */
+ Color[] colours = new Color[ResidueProperties.maxProteinIndex + 1];
+ colours[5] = Color.blue; // Q colour
+ colours[23] = Color.red; // gap colour
+ ColourSchemeI cs = new UserColourScheme(colours);
+ rs = new ResidueShader(cs);
+
+ assertEquals(Color.red, rs.findColour(' ', 7, null));
+ assertEquals(Color.blue, rs.findColour('Q', 7, null));
+
+ /*
+ * stub Conservation to return a given consensus string
+ */
+ final String consSequence = "0123456789+*-";
+ Conservation cons = new Conservation(null,
+ Collections.<SequenceI> emptyList(), 0, 0)
+ {
+ @Override
+ public SequenceI getConsSequence()
+ {
+ return new Sequence("seq", consSequence);
+ }
+ };
+ rs.setConservation(cons);
+
+ /*
+ * with 0% threshold, there should be no fading
+ */
+ rs.setConservationInc(0);
+ assertEquals(Color.red, rs.findColour(' ', 7, null));
+ assertEquals(Color.blue, rs.findColour('Q', 7, null));
+
+ /*
+ * with 40% threshold, 'fade factor' is
+ * (11-score)/10 * 40/20 = (11-score)/5
+ * so position 7, score 7 fades 80% of the way to white (255, 255, 255)
+ */
+ rs.setConservationInc(40);
+
+ /*
+ * gap colour is unchanged for Conservation
+ */
+ assertEquals(Color.red, rs.findColour(' ', 7, null));
+ assertEquals(Color.red, rs.findColour('-', 7, null));
+ assertEquals(Color.red, rs.findColour('.', 7, null));
+
+ /*
+ * residue colour is faded 80% of the way from
+ * blue(0, 0, 255) to white(255, 255, 255)
+ * making (204, 204, 255)
+ */
+ assertEquals(new Color(204, 204, 255), rs.findColour('Q', 7, null));
+
+ /*
+ * turn off By Conservation, apply Above Identity Threshold
+ * providing a stub Consensus that has modal residue "Q" with pid 60%
+ */
+ rs.setConservationApplied(false);
+ ProfilesI consensus = getStubConsensus("Q", 60f);
+ rs.setConsensus(consensus);
+
+ // with consensus pid (60) above threshold (50), colours are unchanged
+ rs.setThreshold(50, false);
+ assertEquals(Color.blue, rs.findColour('Q', 7, null));
+ assertEquals(Color.red, rs.findColour('-', 7, null));
+
+ // with consensus pid (60) below threshold (70),
+ // residue colour becomes white, gap colour is unchanged
+ rs.setThreshold(70, false);
+ assertEquals(Color.white, rs.findColour('Q', 7, null));
+ assertEquals(Color.red, rs.findColour('-', 7, null));
+ }
+
+ /**
+ * @param modalResidue
+ * @param pid
+ * @return
+ */
+ protected ProfilesI getStubConsensus(final String modalResidue,
+ final float pid)
+ {
+ ProfilesI consensus = new ProfilesI() {
+
+ @Override
+ public ProfileI get(int i)
+ {
+ return new ProfileI() {
+ @Override
+ public void setCounts(ResidueCount residueCounts)
+ {
+ }
+
+ @Override
+ public float getPercentageIdentity(boolean ignoreGaps)
+ {
+ return pid;
+ }
+
+ @Override
+ public ResidueCount getCounts()
+ {
+ return null;
+ }
+
+ @Override
+ public int getHeight()
+ {
+ return 0;
+ }
+
+ @Override
+ public int getGapped()
+ {
+ return 0;
+ }
+
+ @Override
+ public int getMaxCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public String getModalResidue()
+ {
+ return modalResidue;
+ }
+
+ @Override
+ public int getNonGapped()
+ {
+ return 0;
+ }};
+ }
+
+ @Override
+ public int getStartColumn()
+ {
+ return 0;
+ }
+
+ @Override
+ public int getEndColumn()
+ {
+ return 0;
+ }
+
+ };
+ return consensus;
+ }
}
*/
package jalview.structures.models;
+import static org.testng.Assert.assertFalse;
import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import jalview.api.AlignmentViewPanel;
import jalview.datamodel.SequenceI;
import jalview.gui.JvOptionPane;
import jalview.io.DataSourceType;
+import jalview.io.FileFormats;
import jalview.schemes.ColourSchemeI;
import jalview.structure.AtomSpec;
import jalview.structure.StructureMappingcommandSet;
import jalview.structures.models.AAStructureBindingModel.SuperposeData;
import java.awt.Color;
+import java.io.IOException;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
+ "ATOM 33 CA ALA A 10 26.790 4.320 3.172 1.00 11.98 C \n"
+ "ATOM 39 CA AVAL A 12 24.424 3.853 6.106 0.50 13.83 C \n";
+ /**
+ * Multichain PDB with identical sequences imported - Binding should correctly
+ * recover chain mappings for each derived sequence
+ */
+ private static final String PDB_4_MC = "HEADER HYDROLASE 09-SEP-09 3A6S \n"
+ + "ATOM 2 CA MET A 1 15.366 -11.648 24.854 1.00 32.05 C \n"
+ + "ATOM 10 CA LYS A 2 16.846 -9.215 22.340 1.00 25.68 C \n"
+ + "ATOM 19 CA LYS A 3 15.412 -6.335 20.343 1.00 19.42 C \n"
+ + "ATOM 28 CA LEU A 4 15.629 -5.719 16.616 1.00 15.49 C \n"
+ + "ATOM 36 CA GLN A 5 14.412 -2.295 15.567 1.00 12.19 C \n"
+ + "ATOM 1030 CA MET B 1 18.869 -7.572 3.432 1.00 31.52 C \n"
+ + "ATOM 1038 CA LYS B 2 19.182 -10.025 6.313 1.00 26.41 C \n"
+ + "ATOM 1047 CA LYS B 3 17.107 -12.963 7.534 1.00 19.71 C \n"
+ + "ATOM 1056 CA LEU B 4 16.142 -13.579 11.164 1.00 14.81 C \n"
+ + "ATOM 1064 CA GLN B 5 14.648 -17.005 11.785 1.00 13.38 C \n";
+
+ // TODO: JAL-2227 - import mmCIF PISA assembly & identify master/copy chains
+
+ @Test(groups= {"Functional"})
+ public void testImportPDBPreservesChainMappings() throws IOException
+ {
+ AlignmentI importedAl = new jalview.io.FormatAdapter().readFile(
+ PDB_4_MC, DataSourceType.PASTE, FileFormats.getInstance()
+ .forName(jalview.io.FileFormat.PDB.toString()));
+ // ideally, we would match on the actual data for the 'File' handle for
+ // pasted files,
+ // see JAL-623 - pasting is still not correctly handled...
+ PDBEntry importedPDB = new PDBEntry("3A6S", "", Type.PDB,
+ "Paste");
+ AAStructureBindingModel binder = new AAStructureBindingModel(
+ new StructureSelectionManager(), new PDBEntry[]
+ { importedPDB },
+ new SequenceI[][]
+ { importedAl.getSequencesArray() }, null)
+ {
+
+ @Override
+ public void updateColours(Object source)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void releaseReferences(Object svl)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String[] getStructureFiles()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String superposeStructures(AlignmentI[] alignments,
+ int[] structureIndices, HiddenColumns[] hiddenCols)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setJalviewColourScheme(ColourSchemeI cs)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setBackgroundColour(Color col)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void highlightAtoms(List<AtomSpec> atoms)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected StructureMappingcommandSet[] getColourBySequenceCommands(
+ String[] files, SequenceRenderer sr, AlignmentViewPanel avp)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List<String> getChainNames()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected void colourBySequence(
+ StructureMappingcommandSet[] colourBySequenceCommands)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void colourByCharge()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void colourByChain()
+ {
+ // TODO Auto-generated method stub
+
+ }
+ };
+ String[][] chains = binder.getChains();
+ assertFalse(chains == null || chains[0] == null,
+ "No chains discovered by binding");
+ assertEquals(2, chains[0].length);
+ assertEquals("A", chains[0][0]);
+ assertEquals("B", chains[0][1]);
+ }
AAStructureBindingModel testee;
AlignmentI al = null;
/*
* EMBL
*/
- assertEquals("http://www.ebi.ac.uk/ena/data/view/x53838&display=xml",
+ assertEquals("https://www.ebi.ac.uk/ena/data/view/x53838&display=xml",
EBIFetchClient.buildUrl("X53838", "EMBL", "display=xml"));
/*
* EMBLCDS
*/
- assertEquals("http://www.ebi.ac.uk/ena/data/view/caa37824&display=xml",
+ assertEquals("https://www.ebi.ac.uk/ena/data/view/caa37824&display=xml",
EBIFetchClient.buildUrl("CAA37824", "EMBL", "display=xml"));
/*
- * Uniprot
- */
- assertEquals(
- "http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/uniprot/p00340/uniprotxml",
- EBIFetchClient.buildUrl("P00340", "UNIPROT", "uniprotxml"));
-
- /*
* PDB / pdb
*/
- assertEquals("http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/pdb",
+ assertEquals("https://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/pdb",
EBIFetchClient.buildUrl("3A6S", "PDB", "pdb"));
/*
* PDB / mmCIF
*/
assertEquals(
- "http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/mmCIF",
+ "https://www.ebi.ac.uk/Tools/dbfetch/dbfetch/pdb/3a6s/mmCIF",
EBIFetchClient.buildUrl("3A6S", "PDB", "mmCIF"));
}
<boolean>true</boolean>
</property>
<property name="destinationName">
- <string><![CDATA[min-jabaws-client-2.1.0.jar]]></string>
+ <string><![CDATA[min-jabaws-client-2.2.0.jar]]></string>
</property>
<property name="fileSize">
<long>601804</long>
<allow pkg="javax.servlet"/>
</subpackage>
+ <subpackage name="schemes">
+ <allow pkg="org.exolab.castor"/>
+ </subpackage>
+
<subpackage name="structure">
<allow pkg="MCview"/>
</subpackage>
+
+ <subpackage name="urls">
+ <allow pkg="javax.swing" class="jalview.urls.UrlLinkTableModel"/>
+ <allow pkg="org.json"/>
+ </subpackage>
<subpackage name="util">
<allow pkg="javax.swing"/>