Merge branch 'feature/JAL-2759' into merge/JAL-2759_2104
authorJim Procter <jprocter@issues.jalview.org>
Tue, 27 Feb 2018 11:16:41 +0000 (11:16 +0000)
committerJim Procter <jprocter@issues.jalview.org>
Tue, 27 Feb 2018 11:16:41 +0000 (11:16 +0000)
69 files changed:
RELEASE
benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java [new file with mode: 0644]
build.xml
examples/testdata/4IM2_missing.pdb [new file with mode: 0644]
examples/testdata/4IM2_missing_noid.pdb [new file with mode: 0644]
examples/testdata/4IM2_nterm.pdb [new file with mode: 0644]
help/help.jhm
help/html/features/splitView.html
help/html/releases.html
help/html/whatsNew.html
resources/images/idwidth.gif [deleted file]
src/MCview/PDBChain.java
src/jalview/analysis/AlignmentUtils.java
src/jalview/api/structures/JalviewStructureDisplayI.java
src/jalview/appletgui/AnnotationLabels.java
src/jalview/appletgui/IdwidthAdjuster.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/bin/Cache.java
src/jalview/datamodel/Alignment.java
src/jalview/ext/ensembl/EnsemblGenomes.java
src/jalview/ext/ensembl/EnsemblLookup.java
src/jalview/ext/ensembl/EnsemblRestClient.java
src/jalview/ext/ensembl/EnsemblSequenceFetcher.java
src/jalview/ext/jmol/JmolCommands.java
src/jalview/fts/service/uniprot/UniProtFTSRestClient.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/AnnotationPanel.java
src/jalview/gui/Desktop.java
src/jalview/gui/IdCanvas.java
src/jalview/gui/IdwidthAdjuster.java
src/jalview/gui/OverviewCanvas.java
src/jalview/gui/OverviewPanel.java
src/jalview/gui/ScalePanel.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/StructureChooser.java
src/jalview/gui/StructureViewer.java
src/jalview/gui/StructureViewerBase.java
src/jalview/structure/StructureMapping.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/viewmodel/OverviewDimensions.java
src/jalview/viewmodel/OverviewDimensionsHideHidden.java
src/jalview/viewmodel/OverviewDimensionsShowHidden.java
src/jalview/ws/DBRefFetcher.java
src/jalview/ws/dbsources/Pfam.java
src/jalview/ws/dbsources/PfamFull.java
src/jalview/ws/dbsources/PfamSeed.java
src/jalview/ws/dbsources/Rfam.java
src/jalview/ws/dbsources/RfamFull.java
src/jalview/ws/dbsources/RfamSeed.java
src/jalview/ws/dbsources/Uniprot.java
src/jalview/ws/dbsources/Xfam.java
src/jalview/ws/sifts/SiftsClient.java
test/jalview/analysis/AlignmentUtilsTests.java
test/jalview/datamodel/AlignmentTest.java
test/jalview/ext/ensembl/EnsemblGeneTest.java
test/jalview/ext/jmol/JmolCommandsTest.java
test/jalview/io/AnnotatedPDBFileInputTest.java
test/jalview/io/Jalview2xmlBase.java
test/jalview/structure/StructureSelectionManagerTest.java
test/jalview/ws/PDBSequenceFetcherTest.java
test/jalview/ws/dbsources/PfamFullTest.java [new file with mode: 0644]
test/jalview/ws/dbsources/PfamSeedTest.java [new file with mode: 0644]
test/jalview/ws/dbsources/RfamFullTest.java [new file with mode: 0644]
test/jalview/ws/dbsources/RfamSeedTest.java [new file with mode: 0644]
test/jalview/ws/dbsources/XfamFetcherTest.java
test/jalview/ws/sifts/SiftsClientTest.java

diff --git a/RELEASE b/RELEASE
index eb9d7cd..5ad87c8 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,2 +1,2 @@
-jalview.release=releases/Release_2_10_3_Branch
-jalview.version=2.10.3b1
+jalview.release=releases/Release_2_10_4_Branch
+jalview.version=2.10.4
diff --git a/benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java b/benchmarking/src/main/java/org/jalview/SeqWidthBenchmark.java
new file mode 100644 (file)
index 0000000..a92d4f0
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.jalview.HiddenColumnsBenchmark.HiddenColsAndStartState;
+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.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+/*
+ * 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 SeqWidthBenchmark {
+
+       /*
+        * State with multiple hidden columns and a start position set
+        */
+       @State(Scope.Thread)
+       public static class AlignmentState
+       {
+               @Param({"100", "1000", "10000", "100000"})
+               public int numSeqs;
+               
+               Random rand = new Random();
+               
+               AlignmentI al;
+               
+               @Setup
+               public void setup()
+               {
+                       rand.setSeed(1234);
+                       
+                       SequenceI[] seqs = new Sequence[numSeqs];
+                   for (int i = 0; i < numSeqs; i++)
+                   {
+                     int count = rand.nextInt(10000); 
+                     StringBuilder aas = new StringBuilder();
+                     for (int j=0; j<count; j++)
+                     {
+                        aas.append("a");
+                     }
+
+                     seqs[i] = new Sequence("Sequence" + i, aas.toString());
+                   }
+                       al = new Alignment(seqs);
+               }
+       }
+       
+       
+       @Benchmark
+       @BenchmarkMode({Mode.Throughput})
+       public int benchSeqGetWidth(AlignmentState tstate)
+       {
+               return tstate.al.getWidth();
+       }
+       
+}
index 4931cfb..7303674 100755 (executable)
--- a/build.xml
+++ b/build.xml
@@ -17,7 +17,9 @@
  * 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.
 -->
-<project name="jalviewX" default="usage" basedir=".">
+<project name="jalviewX" default="usage" basedir="."
+ xmlns:if="ant:if"
+    xmlns:unless="ant:unless">
   <target name="help" depends="usage" />
   <target name="usage" depends="init">
     <echo message="~~~Jalview Ant build.xml Usage~~~~" />
 
     <!-- default TestNG groups to run -->
     <property name="testng-groups" value="Functional" />
+    <!-- Java 9 JVM args -->
+    <condition property="java9">
+      <equals arg1="${ant.java.version}" arg2="9"/>
+    </condition>
 
     <!-- Don't change anything below here unless you know what you are doing! -->
     <!-- Url path for WebStart in JNLP file -->
         <pathelement location="${testOutputDir}" />
         <path refid="test.classpath" />
       </classpath>
+      <jvmarg value="--add-modules=java.se.ee" if:set="java9"/>
+      <jvmarg value="--illegal-access=warn" if:set="java9"/>
       <classfileset dir="${testOutputDir}" includes="**/*.class" />
     </testng>
   </target>
             <exclude name="jalview.jar" />
             <include name="*.jar" />
             <include name="*_*.jar" />
-            <exclude name="*jnilib.jar" />
+            <exclude name="*quaqua*.jar" />
           </fileset>
           <property name="jalview.version" value="${JALVIEW_VERSION}" />
         </resources>
         <resources os="Mac OS X">
           <fileset dir="${packageDir}">
-            <include name="*quaqua*.jnilib.jar" />
+                <include name="quaqua-filechooser-only-8.0.jar"/>
+            <include name="*quaqua64*.jnilib.jar" />
           </fileset>
         </resources>
 
 </target>
 
 <target name="packageApplet" depends="compileApplet, buildPropertiesFile">
-  <copy file="${resourceDir}/images/idwidth.gif" toFile="${outputDir}/images/idwidth.gif" />
   <copy file="${resourceDir}/images/link.gif" toFile="${outputDir}/images/link.gif" />
   <copy todir="${outputDir}/lang">
     <fileset dir="${resourceDir}/lang">
       <include name="MCview/**" />
       <include name="jalview/**" />
       <include name=".build_properties" />
-      <include name="images/idwidth.gif" />
       <include name="images/link.gif" />
       <include name="lang/**" />
     </fileset>
diff --git a/examples/testdata/4IM2_missing.pdb b/examples/testdata/4IM2_missing.pdb
new file mode 100644 (file)
index 0000000..35f94b2
--- /dev/null
@@ -0,0 +1,525 @@
+HEADER    TRANSFERASE/TRANSFERASE INHIBITOR       01-JAN-13   4IM2              
+TITLE     STRUCTURE OF TANK-BINDING KINASE 1  (Truncated test file)
+ATOM   3510  N   LEU A 468      76.337  90.332  -7.628  1.00168.53           N  
+ANISOU 3510  N   LEU A 468    19760  15191  29082   5189   1248  -1702       N  
+ATOM   3511  CA  LEU A 468      75.576  90.788  -6.476  1.00181.60           C  
+ANISOU 3511  CA  LEU A 468    21073  16927  30998   5158   1421  -2051       C  
+ATOM   3512  C   LEU A 468      76.285  91.971  -5.836  1.00196.57           C  
+ANISOU 3512  C   LEU A 468    23029  18636  33021   5053   1667  -2229       C  
+ATOM   3513  O   LEU A 468      75.727  93.067  -5.733  1.00197.97           O  
+ANISOU 3513  O   LEU A 468    23115  18581  33523   5166   1662  -2304       O  
+ATOM   3514  CB  LEU A 468      75.409  89.671  -5.449  1.00173.72           C  
+ANISOU 3514  CB  LEU A 468    19829  16340  29836   4981   1593  -2304       C  
+ATOM   3515  CG  LEU A 468      74.099  88.882  -5.420  1.00170.58           C  
+ANISOU 3515  CG  LEU A 468    19142  16142  29529   5074   1449  -2345       C  
+ATOM   3516  CD1 LEU A 468      74.023  87.940  -6.581  1.00167.98           C  
+ANISOU 3516  CD1 LEU A 468    18951  15858  29015   5180   1156  -2025       C  
+ATOM   3517  CD2 LEU A 468      73.988  88.096  -4.145  1.00165.16           C  
+ANISOU 3517  CD2 LEU A 468    18217  15818  28720   4865   1706  -2656       C  
+ATOM   3518  N   ASP A 469      77.529  91.753  -5.429  1.00208.80           N  
+ANISOU 3518  N   ASP A 469    24731  20282  34322   4836   1875  -2296       N  
+ATOM   3519  CA  ASP A 469      78.267  92.785  -4.720  1.00223.11           C  
+ANISOU 3519  CA  ASP A 469    26577  21960  36233   4701   2123  -2500       C  
+ATOM   3520  C   ASP A 469      78.653  93.973  -5.599  1.00231.96           C  
+ANISOU 3520  C   ASP A 469    27954  22654  37525   4817   2037  -2283       C  
+ATOM   3521  O   ASP A 469      78.718  95.100  -5.118  1.00235.71           O  
+ANISOU 3521  O   ASP A 469    28377  22940  38242   4798   2175  -2449       O  
+ATOM   3522  CB  ASP A 469      79.506  92.197  -4.057  1.00224.50           C  
+ANISOU 3522  CB  ASP A 469    26841  22370  36089   4433   2350  -2633       C  
+ATOM   3523  CG  ASP A 469      79.748  92.767  -2.679  1.00229.51           C  
+ANISOU 3523  CG  ASP A 469    27303  23107  36794   4254   2637  -3018       C  
+ATOM   3524  OD1 ASP A 469      79.958  93.992  -2.564  1.00232.36           O  
+ANISOU 3524  OD1 ASP A 469    27695  23203  37387   4262   2718  -3093       O  
+ATOM   3525  OD2 ASP A 469      79.751  91.979  -1.709  1.00229.48           O  
+ANISOU 3525  OD2 ASP A 469    27145  23450  36598   4098   2779  -3242       O  
+ATOM   3526  N   PHE A 470      78.904  93.735  -6.882  1.00233.88           N  
+ANISOU 3526  N   PHE A 470    28481  22742  37641   4931   1813  -1912       N  
+ATOM   3527  CA  PHE A 470      79.292  94.831  -7.766  1.00237.73           C  
+ANISOU 3527  CA  PHE A 470    29252  22819  38256   5033   1733  -1677       C  
+ATOM   3528  C   PHE A 470      78.103  95.470  -8.467  1.00232.15           C  
+ANISOU 3528  C   PHE A 470    28512  21868  37828   5322   1470  -1512       C  
+ATOM   3529  O   PHE A 470      78.021  96.691  -8.532  1.00230.69           O  
+ANISOU 3529  O   PHE A 470    28371  21372  37909   5402   1493  -1517       O  
+ATOM   3530  CB  PHE A 470      80.344  94.379  -8.784  1.00242.99           C  
+ANISOU 3530  CB  PHE A 470    30297  23410  38616   4976   1661  -1357       C  
+ATOM   3531  CG  PHE A 470      80.663  95.388  -9.839  1.00251.53           C  
+ANISOU 3531  CG  PHE A 470    31709  24074  39788   5089   1550  -1064       C  
+ATOM   3532  CD1 PHE A 470      81.658  96.315  -9.620  1.00252.90           C  
+ANISOU 3532  CD1 PHE A 470    32021  24036  40032   4942   1771  -1133       C  
+ATOM   3533  CD2 PHE A 470      80.005  95.389 -11.059  1.00255.02           C  
+ANISOU 3533  CD2 PHE A 470    32335  24339  40221   5330   1225   -715       C  
+ATOM   3534  CE1 PHE A 470      81.981  97.242 -10.575  1.00254.75           C  
+ANISOU 3534  CE1 PHE A 470    32569  23879  40344   5028   1688   -862       C  
+ATOM   3535  CE2 PHE A 470      80.321  96.320 -12.027  1.00256.76           C  
+ANISOU 3535  CE2 PHE A 470    32894  24173  40491   5427   1126   -433       C  
+ATOM   3536  CZ  PHE A 470      81.313  97.248 -11.784  1.00256.57           C  
+ANISOU 3536  CZ  PHE A 470    33006  23929  40550   5272   1365   -504       C  
+ATOM   3537  N   CYS A 471      77.190  94.665  -8.997  1.00176.88           N  
+ANISOU 3537  N   CYS A 471    20955  21812  24441   2225  -3821  -3711       N  
+ATOM   3538  CA  CYS A 471      76.124  95.233  -9.815  1.00176.41           C  
+ANISOU 3538  CA  CYS A 471    20820  21906  24301   2124  -3576  -3614       C  
+ATOM   3539  C   CYS A 471      74.868  95.631  -9.050  1.00176.82           C  
+ANISOU 3539  C   CYS A 471    21026  22206  23952   2247  -3588  -3734       C  
+ATOM   3540  O   CYS A 471      74.632  96.811  -8.854  1.00178.66           O  
+ANISOU 3540  O   CYS A 471    21175  22393  24314   2353  -3749  -3873       O  
+ATOM   3541  CB  CYS A 471      75.805  94.346 -11.019  1.00173.95           C  
+ANISOU 3541  CB  CYS A 471    20521  21694  23877   1925  -3217  -3359       C  
+ATOM   3542  SG  CYS A 471      76.954  94.571 -12.398  1.00273.04           S  
+ANISOU 3542  SG  CYS A 471    32850  33934  36957   1863  -3075  -3146       S  
+ATOM   3543  N   ILE A 472      74.068  94.670  -8.603  1.00173.50           N  
+ANISOU 3543  N   ILE A 472    20813  22023  23085   2253  -3402  -3662       N  
+ATOM   3544  CA  ILE A 472      72.771  95.033  -8.022  1.00171.09           C  
+ANISOU 3544  CA  ILE A 472    20616  21936  22453   2374  -3307  -3694       C  
+ATOM   3545  C   ILE A 472      72.832  96.022  -6.874  1.00177.82           C  
+ANISOU 3545  C   ILE A 472    21591  22750  23222   2698  -3611  -3931       C  
+ATOM   3546  O   ILE A 472      71.992  96.914  -6.776  1.00182.92           O  
+ANISOU 3546  O   ILE A 472    22220  23491  23792   2778  -3598  -3985       O  
+ATOM   3547  CB  ILE A 472      71.979  93.843  -7.518  1.00159.41           C  
+ANISOU 3547  CB  ILE A 472    19318  20653  20599   2393  -3038  -3546       C  
+ATOM   3548  CG1 ILE A 472      70.708  93.667  -8.341  1.00147.27           C  
+ANISOU 3548  CG1 ILE A 472    17653  19253  19051   2196  -2745  -3384       C  
+ATOM   3549  CG2 ILE A 472      71.526  94.090  -6.105  1.00155.95           C  
+ANISOU 3549  CG2 ILE A 472    19129  20312  19812   2752  -3085  -3637       C  
+ATOM   3550  CD1 ILE A 472      70.927  92.915  -9.606  1.00135.92           C  
+ANISOU 3550  CD1 ILE A 472    16097  17752  17794   1929  -2643  -3254       C  
+ATOM   3551  N   ARG A 473      73.812  95.865  -5.996  1.00180.33           N  
+ANISOU 3551  N   ARG A 473    22055  22917  23544   2920  -3920  -4092       N  
+ATOM   3552  CA  ARG A 473      73.860  96.762  -4.877  1.00189.65           C  
+ANISOU 3552  CA  ARG A 473    23415  24034  24610   3307  -4283  -4357       C  
+ATOM   3553  C   ARG A 473      74.328  98.021  -5.558  1.00185.98           C  
+ANISOU 3553  C   ARG A 473    22628  23344  24692   3195  -4530  -4477       C  
+ATOM   3554  O   ARG A 473      73.519  98.885  -5.866  1.00181.76           O  
+ANISOU 3554  O   ARG A 473    22002  22904  24153   3165  -4446  -4474       O  
+ATOM   3555  CB  ARG A 473      74.803  96.287  -3.768  1.00205.24           C  
+ANISOU 3555  CB  ARG A 473    25661  25862  26460   3635  -4629  -4545       C  
+ATOM   3556  CG  ARG A 473      74.468  96.921  -2.433  1.00220.50           C  
+ANISOU 3556  CG  ARG A 473    27955  27814  28011   4171  -4923  -4787       C  
+ATOM   3557  CD  ARG A 473      75.337  96.433  -1.295  1.00232.58           C  
+ANISOU 3557  CD  ARG A 473    29837  29192  29341   4591  -5300  -5003       C  
+ATOM   3558  NE  ARG A 473      76.763  96.602  -1.549  1.00237.46           N  
+ANISOU 3558  NE  ARG A 473    30220  29440  30564   4489  -5773  -5205       N  
+ATOM   3559  CZ  ARG A 473      77.716  95.991  -0.861  1.00240.32           C  
+ANISOU 3559  CZ  ARG A 473    30786  29623  30903   4725  -6098  -5371       C  
+ATOM   3560  NH1 ARG A 473      77.388  95.172   0.115  1.00241.12           N  
+ANISOU 3560  NH1 ARG A 473    31370  29900  30344   5100  -5978  -5355       N  
+ATOM   3561  NH2 ARG A 473      78.988  96.195  -1.159  1.00241.54           N  
+ANISOU 3561  NH2 ARG A 473    30651  29398  31724   4605  -6518  -5533       N  
+ATOM   3562  N   ASN A 474      75.608  98.073  -5.901  1.00188.74           N  
+ANISOU 3562  N   ASN A 474    22768  23381  25563   3107  -4772  -4534       N  
+ATOM   3563  CA  ASN A 474      76.168  99.264  -6.526  1.00188.61           C  
+ANISOU 3563  CA  ASN A 474    22395  23075  26194   3026  -4977  -4605       C  
+ATOM   3564  C   ASN A 474      75.420  99.892  -7.729  1.00173.98           C  
+ANISOU 3564  C   ASN A 474    20312  21326  24467   2781  -4623  -4414       C  
+ATOM   3565  O   ASN A 474      75.482 101.107  -7.891  1.00176.08           O  
+ANISOU 3565  O   ASN A 474    20374  21426  25104   2827  -4803  -4518       O  
+ATOM   3566  CB  ASN A 474      77.650  99.066  -6.857  1.00199.45           C  
+ANISOU 3566  CB  ASN A 474    23514  24060  28207   2939  -5170  -4595       C  
+ATOM   3567  CG  ASN A 474      78.504  98.809  -5.625  1.00210.23           C  
+ANISOU 3567  CG  ASN A 474    25062  25219  29597   3243  -5689  -4883       C  
+ATOM   3568  OD1 ASN A 474      78.174  99.240  -4.527  1.00215.26           O  
+ANISOU 3568  OD1 ASN A 474    25969  25891  29928   3596  -6043  -5160       O  
+ATOM   3569  ND2 ASN A 474      79.613  98.103  -5.810  1.00212.07           N  
+ANISOU 3569  ND2 ASN A 474    25176  25222  30179   3148  -5748  -4822       N  
+ATOM   3570  N   ILE A 475      74.722  99.114  -8.562  1.00161.86           N  
+ANISOU 3570  N   ILE A 475    18813  20033  22652   2556  -4165  -4158       N  
+ATOM   3571  CA  ILE A 475      74.022  99.727  -9.709  1.00154.84           C  
+ANISOU 3571  CA  ILE A 475    17755  19216  21861   2390  -3885  -4015       C  
+ATOM   3572  C   ILE A 475      72.785 100.520  -9.312  1.00159.27           C  
+ANISOU 3572  C   ILE A 475    18401  19995  22121   2490  -3891  -4125       C  
+ATOM   3573  O   ILE A 475      72.662 101.687  -9.663  1.00162.60           O  
+ANISOU 3573  O   ILE A 475    18651  20327  22804   2505  -3962  -4186       O  
+ATOM   3574  CB  ILE A 475      73.600  98.727 -10.818  1.00214.93           C  
+ANISOU 3574  CB  ILE A 475    25397  26975  29293   2173  -3475  -3753       C  
+ATOM   3575  CG1 ILE A 475      74.808  98.227 -11.613  1.00218.74           C  
+ANISOU 3575  CG1 ILE A 475    25753  27211  30145   2083  -3390  -3585       C  
+ATOM   3576  CG2 ILE A 475      72.618  99.379 -11.789  1.00210.37           C  
+ANISOU 3576  CG2 ILE A 475    24743  26509  28681   2097  -3256  -3677       C  
+ATOM   3577  CD1 ILE A 475      74.446  97.201 -12.664  1.00218.15           C  
+ANISOU 3577  CD1 ILE A 475    25777  27260  29850   1946  -3056  -3359       C  
+ATOM   3578  N   GLU A 476      71.856  99.893  -8.600  1.00156.45           N  
+ANISOU 3578  N   GLU A 476    18293  19907  21245   2571  -3778  -4120       N  
+ATOM   3579  CA  GLU A 476      70.623 100.594  -8.252  1.00142.72           C  
+ANISOU 3579  CA  GLU A 476    16627  18370  19231   2677  -3720  -4176       C  
+ATOM   3580  C   GLU A 476      70.845 101.560  -7.094  1.00144.41           C  
+ANISOU 3580  C   GLU A 476    16959  18500  19412   3012  -4114  -4440       C  
+ATOM   3581  O   GLU A 476      70.012 102.417  -6.811  1.00142.58           O  
+ANISOU 3581  O   GLU A 476    16768  18380  19024   3141  -4136  -4517       O  
+ATOM   3582  CB  GLU A 476      69.486  99.616  -7.958  1.00128.68           C  
+ANISOU 3582  CB  GLU A 476    15020  16860  17012   2665  -3395  -4018       C  
+ATOM   3583  CG  GLU A 476      69.562  98.905  -6.628  1.00128.73           C  
+ANISOU 3583  CG  GLU A 476    15321  16930  16662   2941  -3433  -4041       C  
+ATOM   3584  CD  GLU A 476      68.465  97.866  -6.484  1.00133.35           C  
+ANISOU 3584  CD  GLU A 476    15992  17719  16955   2900  -3026  -3806       C  
+ATOM   3585  OE1 GLU A 476      68.285  97.061  -7.422  1.00132.30           O  
+ANISOU 3585  OE1 GLU A 476    15710  17598  16962   2603  -2816  -3643       O  
+ATOM   3586  OE2 GLU A 476      67.768  97.860  -5.448  1.00136.37           O  
+ANISOU 3586  OE2 GLU A 476    16588  18223  17003   3196  -2912  -3773       O  
+ATOM   3587  N   LYS A 477      71.990 101.424  -6.439  1.00148.46           N  
+ANISOU 3587  N   LYS A 477    17534  18788  20087   3179  -4467  -4596       N  
+ATOM   3588  CA  LYS A 477      72.399 102.365  -5.405  1.00154.25           C  
+ANISOU 3588  CA  LYS A 477    18378  19348  20882   3544  -4976  -4907       C  
+ATOM   3589  C   LYS A 477      72.634 103.732  -5.994  1.00159.76           C  
+ANISOU 3589  C   LYS A 477    18754  19833  22117   3467  -5183  -5014       C  
+ATOM   3590  O   LYS A 477      72.568 104.742  -5.292  1.00158.01           O  
+ANISOU 3590  O   LYS A 477    18598  19516  21921   3749  -5568  -5266       O  
+ATOM   3591  CB  LYS A 477      73.667 101.883  -4.706  1.00154.03           C  
+ANISOU 3591  CB  LYS A 477    18446  19057  21022   3730  -5372  -5076       C  
+ATOM   3592  CG  LYS A 477      73.367 100.787  -3.750  1.00149.76           C  
+ANISOU 3592  CG  LYS A 477    18324  18717  19861   3975  -5258  -5042       C  
+ATOM   3593  CD  LYS A 477      74.437 100.554  -2.740  1.00143.39           C  
+ANISOU 3593  CD  LYS A 477    17737  17664  19082   4327  -5762  -5306       C  
+ATOM   3594  CE  LYS A 477      73.739 100.087  -1.488  1.00145.72           C  
+ANISOU 3594  CE  LYS A 477    18569  18186  18613   4805  -5697  -5337       C  
+ATOM   3595  NZ  LYS A 477      74.661  99.556  -0.469  1.00149.42           N  
+ANISOU 3595  NZ  LYS A 477    19366  18470  18936   5206  -6108  -5561       N  
+ATOM   3596  N   THR A 478      72.908 103.757  -7.293  1.00166.45           N  
+ANISOU 3596  N   THR A 478    19271  20589  23384   3124  -4918  -4810       N  
+ATOM   3597  CA  THR A 478      73.186 105.012  -7.968  1.00170.99           C  
+ANISOU 3597  CA  THR A 478    19509  20929  24531   3052  -5023  -4844       C  
+ATOM   3598  C   THR A 478      71.905 105.733  -8.391  1.00172.33           C  
+ANISOU 3598  C   THR A 478    19686  21358  24435   2999  -4780  -4796       C  
+ATOM   3599  O   THR A 478      71.021 105.170  -9.046  1.00163.10           O  
+ANISOU 3599  O   THR A 478    18581  20461  22928   2823  -4356  -4594       O  
+ATOM   3600  CB  THR A 478      74.217 104.856  -9.128  1.00146.93           C  
+ANISOU 3600  CB  THR A 478    16115  17589  22125   2815  -4843  -4626       C  
+ATOM   3601  OG1 THR A 478      74.873 106.106  -9.369  1.00147.15           O  
+ANISOU 3601  OG1 THR A 478    15790  17239  22881   2857  -5085  -4705       O  
+ATOM   3602  CG2 THR A 478      73.562 104.391 -10.425  1.00144.32           C  
+ANISOU 3602  CG2 THR A 478    15764  17473  21597   2570  -4282  -4318       C  
+ATOM   3603  N   VAL A 479      71.809 106.979  -7.944  1.00177.73           N  
+ANISOU 3603  N   VAL A 479    20309  21929  25291   3181  -5110  -5014       N  
+ATOM   3604  CA  VAL A 479      70.674 107.838  -8.218  1.00175.65           C  
+ANISOU 3604  CA  VAL A 479    20044  21875  24819   3171  -4959  -5013       C  
+ATOM   3605  C   VAL A 479      71.176 109.077  -8.939  1.00177.67           C  
+ANISOU 3605  C   VAL A 479    19928  21830  25749   3101  -5069  -5035       C  
+ATOM   3606  O   VAL A 479      72.353 109.417  -8.840  1.00179.02           O  
+ANISOU 3606  O   VAL A 479    19865  21600  26555   3150  -5387  -5121       O  
+ATOM   3607  CB  VAL A 479      69.983 108.266  -6.909  1.00168.37           C  
+ANISOU 3607  CB  VAL A 479    19442  21113  23418   3524  -5243  -5249       C  
+ATOM   3608  CG1 VAL A 479      69.008 109.403  -7.169  1.00162.23           C  
+ANISOU 3608  CG1 VAL A 479    18603  20470  22565   3531  -5176  -5285       C  
+ATOM   3609  CG2 VAL A 479      69.288 107.080  -6.256  1.00163.89           C  
+ANISOU 3609  CG2 VAL A 479    19236  20856  22180   3624  -4991  -5142       C  
+ATOM   3610  N   MET A 486      57.931 103.433  -6.150  1.00 92.00           N  
+ANISOU 3610  N   MET A 486    10154  13425  11375   3371  -1523  -3283       N  
+ATOM   3611  CA  MET A 486      56.824 104.104  -5.482  1.00110.61           C  
+ANISOU 3611  CA  MET A 486    12558  15882  13585   3644  -1287  -3161       C  
+ATOM   3612  C   MET A 486      56.182 105.150  -6.389  1.00111.38           C  
+ANISOU 3612  C   MET A 486    12428  16016  13877   3424  -1416  -3308       C  
+ATOM   3613  O   MET A 486      56.000 106.305  -6.002  1.00120.35           O  
+ANISOU 3613  O   MET A 486    13691  17243  14794   3639  -1526  -3430       O  
+ATOM   3614  CB  MET A 486      57.288 104.743  -4.170  1.00120.60           C  
+ANISOU 3614  CB  MET A 486    14253  17221  14347   4174  -1395  -3243       C  
+ATOM   3615  CG  MET A 486      58.405 105.768  -4.316  1.00126.87           C  
+ANISOU 3615  CG  MET A 486    15171  17987  15047   4196  -1944  -3629       C  
+ATOM   3616  SD  MET A 486      58.150 107.169  -3.210  1.00146.78           S  
+ANISOU 3616  SD  MET A 486    18044  20597  17128   4757  -2124  -3782       S  
+ATOM   3617  CE  MET A 486      58.003 106.326  -1.640  1.00102.35           C  
+ANISOU 3617  CE  MET A 486    12883  15002  11003   5391  -1797  -3524       C  
+ATOM   3618  N   GLY A 496      57.154  99.412  -2.065  1.00157.62           N  
+ANISOU 3618  N   GLY A 496    19150  21656  19083   4616     82  -2024       N  
+ATOM   3619  CA  GLY A 496      57.031  99.217  -3.498  1.00158.07           C  
+ANISOU 3619  CA  GLY A 496    18749  21636  19677   3991   -116  -2141       C  
+ATOM   3620  C   GLY A 496      57.664  97.914  -3.942  1.00163.71           C  
+ANISOU 3620  C   GLY A 496    19349  22235  20619   3709   -140  -2093       C  
+ATOM   3621  O   GLY A 496      58.040  97.090  -3.111  1.00167.17           O  
+ANISOU 3621  O   GLY A 496    20009  22652  20858   3970     79  -1915       O  
+ATOM   3622  N   GLU A 497      57.778  97.722  -5.254  1.00166.67           N  
+ANISOU 3622  N   GLU A 497    19413  22530  21383   3222   -403  -2250       N  
+ATOM   3623  CA  GLU A 497      58.431  96.534  -5.792  1.00170.73           C  
+ANISOU 3623  CA  GLU A 497    19840  22933  22098   2955   -485  -2239       C  
+ATOM   3624  C   GLU A 497      59.931  96.621  -5.556  1.00172.64           C  
+ANISOU 3624  C   GLU A 497    20403  23228  21965   3043   -809  -2472       C  
+ATOM   3625  O   GLU A 497      60.589  95.609  -5.311  1.00173.01           O  
+ANISOU 3625  O   GLU A 497    20547  23223  21965   3047   -764  -2395       O  
+ATOM   3626  CB  GLU A 497      58.173  96.394  -7.290  1.00169.62           C  
+ANISOU 3626  CB  GLU A 497    19361  22681  22408   2505   -727  -2374       C  
+ATOM   3627  CG  GLU A 497      56.882  97.012  -7.777  1.00173.11           C  
+ANISOU 3627  CG  GLU A 497    19518  23086  23171   2413   -663  -2350       C  
+ATOM   3628  CD  GLU A 497      56.703  96.840  -9.270  1.00173.61           C  
+ANISOU 3628  CD  GLU A 497    19329  23013  23621   2054   -974  -2531       C  
+ATOM   3629  OE1 GLU A 497      57.597  96.241  -9.908  1.00170.78           O  
+ANISOU 3629  OE1 GLU A 497    19040  22600  23250   1901  -1202  -2647       O  
+ATOM   3630  OE2 GLU A 497      55.672  97.300  -9.805  1.00174.73           O  
+ANISOU 3630  OE2 GLU A 497    19233  23093  24064   1967   -999  -2559       O  
+ATOM   3631  N   ILE A 498      60.466  97.836  -5.652  1.00171.44           N  
+ANISOU 3631  N   ILE A 498    20381  23149  21608   3107  -1147  -2757       N  
+ATOM   3632  CA  ILE A 498      61.883  98.078  -5.403  1.00167.93           C  
+ANISOU 3632  CA  ILE A 498    20186  22695  20926   3210  -1503  -2995       C  
+ATOM   3633  C   ILE A 498      62.251  97.620  -4.004  1.00173.82           C  
+ANISOU 3633  C   ILE A 498    21298  23465  21280   3659  -1379  -2903       C  
+ATOM   3634  O   ILE A 498      63.315  97.034  -3.789  1.00168.12           O  
+ANISOU 3634  O   ILE A 498    20732  22684  20462   3692  -1544  -2980       O  
+ATOM   3635  CB  ILE A 498      62.227  99.564  -5.520  1.00165.53           C  
+ANISOU 3635  CB  ILE A 498    19934  22420  20540   3287  -1855  -3283       C  
+ATOM   3636  CG1 ILE A 498      61.848 100.100  -6.901  1.00171.37           C  
+ANISOU 3636  CG1 ILE A 498    20360  23137  21618   2911  -1947  -3365       C  
+ATOM   3637  CG2 ILE A 498      63.706  99.798  -5.239  1.00153.61           C  
+ANISOU 3637  CG2 ILE A 498    18613  20820  18931   3398  -2256  -3525       C  
+ATOM   3638  CD1 ILE A 498      61.891 101.605  -6.996  1.00174.73           C  
+ANISOU 3638  CD1 ILE A 498    20793  23594  22004   2996  -2195  -3587       C  
+ATOM   3639  N   SER A 499      61.362  97.890  -3.054  1.00187.32           N  
+ANISOU 3639  N   SER A 499    23169  25252  22753   4049  -1074  -2727       N  
+ATOM   3640  CA  SER A 499      61.558  97.444  -1.683  1.00198.47           C  
+ANISOU 3640  CA  SER A 499    24999  26682  23729   4594   -880  -2593       C  
+ATOM   3641  C   SER A 499      61.611  95.926  -1.651  1.00206.95           C  
+ANISOU 3641  C   SER A 499    26003  27687  24943   4481   -548  -2315       C  
+ATOM   3642  O   SER A 499      62.302  95.334  -0.823  1.00211.11           O  
+ANISOU 3642  O   SER A 499    26867  28195  25151   4806   -533  -2293       O  
+ATOM   3643  CB  SER A 499      60.435  97.952  -0.780  1.00200.16           C  
+ANISOU 3643  CB  SER A 499    25385  26976  23690   5064   -498  -2368       C  
+ATOM   3644  OG  SER A 499      60.635  97.541   0.556  1.00203.12           O  
+ANISOU 3644  OG  SER A 499    26244  27359  23574   5697   -286  -2224       O  
+ATOM   3645  N   ASP A 500      60.877  95.300  -2.564  1.00209.43           N  
+ANISOU 3645  N   ASP A 500    25883  27938  25751   4040   -320  -2123       N  
+ATOM   3646  CA  ASP A 500      60.862  93.851  -2.655  1.00212.36           C  
+ANISOU 3646  CA  ASP A 500    26120  28207  26361   3883    -39  -1865       C  
+ATOM   3647  C   ASP A 500      62.097  93.307  -3.366  1.00203.21           C  
+ANISOU 3647  C   ASP A 500    24946  26999  25265   3557   -426  -2093       C  
+ATOM   3648  O   ASP A 500      62.511  92.195  -3.092  1.00204.96           O  
+ANISOU 3648  O   ASP A 500    25238  27165  25472   3573   -286  -1954       O  
+ATOM   3649  CB  ASP A 500      59.580  93.355  -3.335  1.00221.23           C  
+ANISOU 3649  CB  ASP A 500    26765  29217  28075   3573    287  -1593       C  
+ATOM   3650  CG  ASP A 500      58.346  93.583  -2.486  1.00233.55           C  
+ANISOU 3650  CG  ASP A 500    28310  30773  29657   3938    816  -1243       C  
+ATOM   3651  OD1 ASP A 500      58.502  93.807  -1.272  1.00239.09           O  
+ANISOU 3651  OD1 ASP A 500    29432  31558  29852   4492   1029  -1137       O  
+ATOM   3652  OD2 ASP A 500      57.226  93.532  -3.034  1.00237.24           O  
+ANISOU 3652  OD2 ASP A 500    28355  31128  30656   3709   1011  -1072       O  
+ATOM   3653  N   ILE A 501      62.692  94.094  -4.258  1.00192.67           N  
+ANISOU 3653  N   ILE A 501    23525  25673  24008   3292   -875  -2413       N  
+ATOM   3654  CA  ILE A 501      63.864  93.633  -5.007  1.00181.71           C  
+ANISOU 3654  CA  ILE A 501    22108  24215  22719   3006  -1195  -2587       C  
+ATOM   3655  C   ILE A 501      65.165  93.699  -4.196  1.00170.68           C  
+ANISOU 3655  C   ILE A 501    21064  22814  20972   3287  -1450  -2764       C  
+ATOM   3656  O   ILE A 501      65.940  92.735  -4.173  1.00164.70           O  
+ANISOU 3656  O   ILE A 501    20376  21999  20202   3222  -1476  -2736       O  
+ATOM   3657  CB  ILE A 501      64.023  94.385  -6.353  1.00138.03           C  
+ANISOU 3657  CB  ILE A 501    16341  18649  17453   2657  -1507  -2802       C  
+ATOM   3658  CG1 ILE A 501      63.385  93.589  -7.491  1.00130.33           C  
+ANISOU 3658  CG1 ILE A 501    15061  17587  16872   2296  -1411  -2683       C  
+ATOM   3659  CG2 ILE A 501      65.491  94.642  -6.682  1.00137.98           C  
+ANISOU 3659  CG2 ILE A 501    16437  18581  17410   2596  -1883  -3037       C  
+ATOM   3660  CD1 ILE A 501      61.877  93.516  -7.426  1.00127.50           C  
+ANISOU 3660  CD1 ILE A 501    14480  17217  16748   2292  -1111  -2482       C  
+ATOM   3661  N   HIS A 502      65.396  94.829  -3.532  1.00164.00           N  
+ANISOU 3661  N   HIS A 502    20439  22007  19869   3613  -1676  -2964       N  
+ATOM   3662  CA  HIS A 502      66.603  95.022  -2.737  1.00157.69           C  
+ANISOU 3662  CA  HIS A 502    19968  21147  18800   3931  -2029  -3195       C  
+ATOM   3663  C   HIS A 502      66.627  94.018  -1.594  1.00162.64           C  
+ANISOU 3663  C   HIS A 502    20933  21795  19069   4322  -1761  -3012       C  
+ATOM   3664  O   HIS A 502      67.677  93.496  -1.229  1.00164.35           O  
+ANISOU 3664  O   HIS A 502    21348  21935  19163   4433  -1971  -3125       O  
+ATOM   3665  CB  HIS A 502      66.654  96.452  -2.195  1.00150.83           C  
+ANISOU 3665  CB  HIS A 502    19272  20282  17755   4264  -2351  -3452       C  
+ATOM   3666  CG  HIS A 502      67.989  97.117  -2.348  1.00143.78           C  
+ANISOU 3666  CG  HIS A 502    18387  19223  17019   4248  -2929  -3804       C  
+ATOM   3667  ND1 HIS A 502      68.672  97.155  -3.544  1.00137.00           N  
+ANISOU 3667  ND1 HIS A 502    17193  18253  16609   3785  -3096  -3872       N  
+ATOM   3668  CD2 HIS A 502      68.759  97.787  -1.457  1.00140.15           C  
+ANISOU 3668  CD2 HIS A 502    18217  18647  16387   4674  -3387  -4099       C  
+ATOM   3669  CE1 HIS A 502      69.807  97.814  -3.383  1.00131.33           C  
+ANISOU 3669  CE1 HIS A 502    16503  17343  16055   3893  -3583  -4155       C  
+ATOM   3670  NE2 HIS A 502      69.883  98.208  -2.125  1.00130.34           N  
+ANISOU 3670  NE2 HIS A 502    16741  17200  15583   4416  -3815  -4326       N  
+ATOM   3671  N   THR A 503      65.450  93.751  -1.039  1.00163.37           N  
+ANISOU 3671  N   THR A 503    21080  21971  19022   4552  -1268  -2705       N  
+ATOM   3672  CA  THR A 503      65.295  92.771   0.033  1.00163.31           C  
+ANISOU 3672  CA  THR A 503    21384  21972  18696   4974   -872  -2437       C  
+ATOM   3673  C   THR A 503      65.393  91.327  -0.475  1.00151.49           C  
+ANISOU 3673  C   THR A 503    19659  20415  17484   4610   -614  -2206       C  
+ATOM   3674  O   THR A 503      65.955  90.464   0.198  1.00146.11           O  
+ANISOU 3674  O   THR A 503    19247  19705  16563   4853   -520  -2130       O  
+ATOM   3675  CB  THR A 503      63.956  92.972   0.783  1.00170.09           C  
+ANISOU 3675  CB  THR A 503    22342  22899  19387   5379   -334  -2106       C  
+ATOM   3676  OG1 THR A 503      64.026  94.162   1.576  1.00176.61           O  
+ANISOU 3676  OG1 THR A 503    23551  23775  19778   5902   -585  -2325       O  
+ATOM   3677  CG2 THR A 503      63.645  91.790   1.693  1.00171.53           C  
+ANISOU 3677  CG2 THR A 503    22747  23054  19374   5760    235  -1707       C  
+ATOM   3678  N   LYS A 504      64.865  91.071  -1.669  1.00141.41           N  
+ANISOU 3678  N   LYS A 504    17911  19106  16711   4058   -541  -2117       N  
+ATOM   3679  CA  LYS A 504      64.918  89.730  -2.251  1.00138.96           C  
+ANISOU 3679  CA  LYS A 504    17368  18711  16719   3706   -369  -1930       C  
+ATOM   3680  C   LYS A 504      66.335  89.382  -2.646  1.00142.04           C  
+ANISOU 3680  C   LYS A 504    17848  19062  17058   3520   -779  -2178       C  
+ATOM   3681  O   LYS A 504      66.762  88.230  -2.559  1.00134.46           O  
+ANISOU 3681  O   LYS A 504    16927  18053  16108   3463   -666  -2057       O  
+ATOM   3682  CB  LYS A 504      64.010  89.614  -3.477  1.00129.82           C  
+ANISOU 3682  CB  LYS A 504    15721  17488  16116   3223   -303  -1839       C  
+ATOM   3683  CG  LYS A 504      62.585  89.222  -3.164  1.00130.75           C  
+ANISOU 3683  CG  LYS A 504    15616  17544  16518   3307    225  -1458       C  
+ATOM   3684  N   LEU A 505      67.053  90.395  -3.100  1.00138.41           N  
+ANISOU 3684  N   LEU A 505    17394  18602  16593   3427  -1237  -2505       N  
+ATOM   3685  CA  LEU A 505      68.435  90.224  -3.458  1.00120.29           C  
+ANISOU 3685  CA  LEU A 505    15154  16230  14322   3285  -1619  -2726       C  
+ATOM   3686  C   LEU A 505      69.260  89.889  -2.223  1.00124.70           C  
+ANISOU 3686  C   LEU A 505    16126  16770  14484   3724  -1710  -2800       C  
+ATOM   3687  O   LEU A 505      70.166  89.052  -2.259  1.00124.02           O  
+ANISOU 3687  O   LEU A 505    16106  16619  14396   3643  -1808  -2823       O  
+ATOM   3688  CB  LEU A 505      68.966  91.499  -4.066  1.00109.42           C  
+ANISOU 3688  CB  LEU A 505    13673  14807  13094   3171  -2036  -3016       C  
+ATOM   3689  CG  LEU A 505      70.386  91.097  -4.404  1.00128.61           C  
+ANISOU 3689  CG  LEU A 505    16120  17111  15635   3034  -2336  -3157       C  
+ATOM   3690  CD1 LEU A 505      70.509  91.048  -5.920  1.00141.22           C  
+ANISOU 3690  CD1 LEU A 505    17393  18648  17616   2580  -2370  -3131       C  
+ATOM   3691  CD2 LEU A 505      71.441  91.946  -3.655  1.00114.58           C  
+ANISOU 3691  CD2 LEU A 505    14554  15224  13758   3350  -2784  -3462       C  
+ATOM   3692  N   LEU A 506      68.951  90.579  -1.132  1.00130.40           N  
+ANISOU 3692  N   LEU A 506    17159  17539  14847   4233  -1705  -2854       N  
+ATOM   3693  CA  LEU A 506      69.612  90.336   0.139  1.00131.63           C  
+ANISOU 3693  CA  LEU A 506    17798  17665  14549   4786  -1814  -2947       C  
+ATOM   3694  C   LEU A 506      69.501  88.865   0.507  1.00144.65           C  
+ANISOU 3694  C   LEU A 506    19548  19330  16080   4841  -1380  -2638       C  
+ATOM   3695  O   LEU A 506      70.448  88.287   1.024  1.00156.36           O  
+ANISOU 3695  O   LEU A 506    21304  20754  17351   5038  -1550  -2741       O  
+ATOM   3696  CB  LEU A 506      69.008  91.206   1.240  1.00120.17           C  
+ANISOU 3696  CB  LEU A 506    16713  16270  12675   5409  -1772  -2980       C  
+ATOM   3697  N   ARG A 507      68.351  88.260   0.214  1.00146.01           N  
+ANISOU 3697  N   ARG A 507    19470  19552  16453   4658   -839  -2263       N  
+ATOM   3698  CA  ARG A 507      68.159  86.831   0.443  1.00152.26           C  
+ANISOU 3698  CA  ARG A 507    20261  20320  17271   4649   -394  -1930       C  
+ATOM   3699  C   ARG A 507      69.164  86.004  -0.360  1.00145.14           C  
+ANISOU 3699  C   ARG A 507    19199  19352  16597   4200   -653  -2042       C  
+ATOM   3700  O   ARG A 507      69.471  84.873   0.007  1.00142.95           O  
+ANISOU 3700  O   ARG A 507    19044  19045  16224   4273   -450  -1882       O  
+ATOM   3701  CB  ARG A 507      66.724  86.401   0.111  1.00161.16           C  
+ANISOU 3701  CB  ARG A 507    21023  21434  18777   4463    165  -1523       C  
+ATOM   3702  CG  ARG A 507      65.661  86.975   1.046  1.00177.63           C  
+ANISOU 3702  CG  ARG A 507    23283  23565  20645   4978    585  -1290       C  
+ATOM   3703  CD  ARG A 507      64.263  86.468   0.696  1.00187.68           C  
+ANISOU 3703  CD  ARG A 507    24111  24757  22442   4769   1148   -857       C  
+ATOM   3704  NE  ARG A 507      63.229  87.082   1.527  1.00198.88           N  
+ANISOU 3704  NE  ARG A 507    25661  26202  23704   5259   1588   -600       N  
+ATOM   3705  CZ  ARG A 507      61.923  86.883   1.368  1.00205.71           C  
+ANISOU 3705  CZ  ARG A 507    26137  26967  25058   5169   2095   -210       C  
+ATOM   3706  NH1 ARG A 507      61.484  86.084   0.406  1.00207.33           N  
+ANISOU 3706  NH1 ARG A 507    25797  27020  25959   4610   2159    -75       N  
+ATOM   3707  NH2 ARG A 507      61.055  87.485   2.171  1.00208.11           N  
+ANISOU 3707  NH2 ARG A 507    26596  27293  25185   5668   2517     41       N  
+ATOM   3708  N   LEU A 508      69.681  86.579  -1.445  1.00134.19           N  
+ANISOU 3708  N   LEU A 508    17555  17933  15496   3776  -1072  -2294       N  
+ATOM   3709  CA  LEU A 508      70.654  85.888  -2.287  1.00125.06           C  
+ANISOU 3709  CA  LEU A 508    16259  16704  14555   3385  -1304  -2382       C  
+ATOM   3710  C   LEU A 508      72.070  85.983  -1.730  1.00133.75           C  
+ANISOU 3710  C   LEU A 508    17660  17739  15419   3609  -1705  -2655       C  
+ATOM   3711  O   LEU A 508      72.775  84.975  -1.650  1.00132.42           O  
+ANISOU 3711  O   LEU A 508    17581  17530  15202   3562  -1700  -2615       O  
+ATOM   3712  CB  LEU A 508      70.606  86.404  -3.726  1.00112.64           C  
+ANISOU 3712  CB  LEU A 508    14312  15095  13392   2907  -1513  -2482       C  
+ATOM   3713  CG  LEU A 508      69.271  86.186  -4.436  1.00113.17           C  
+ANISOU 3713  CG  LEU A 508    14056  15174  13769   2653  -1215  -2260       C  
+ATOM   3714  CD1 LEU A 508      69.459  86.184  -5.945  1.00106.22           C  
+ANISOU 3714  CD1 LEU A 508    12898  14225  13237   2216  -1432  -2343       C  
+ATOM   3715  CD2 LEU A 508      68.613  84.894  -3.968  1.00117.32           C  
+ANISOU 3715  CD2 LEU A 508    14560  15678  14341   2703   -779  -1932       C  
+ATOM   3716  N   SER A 509      72.491  87.188  -1.355  1.00130.72           N  
+ANISOU 3716  N   SER A 509    17414  17317  14936   3856  -2085  -2944       N  
+ATOM   3717  CA  SER A 509      73.767  87.347  -0.663  1.00136.66           C  
+ANISOU 3717  CA  SER A 509    18457  17948  15519   4156  -2531  -3236       C  
+ATOM   3718  C   SER A 509      73.698  86.583   0.646  1.00143.40           C  
+ANISOU 3718  C   SER A 509    19773  18845  15866   4687  -2319  -3138       C  
+ATOM   3719  O   SER A 509      74.680  85.977   1.082  1.00138.35           O  
+ANISOU 3719  O   SER A 509    19358  18121  15090   4839  -2521  -3256       O  
+ATOM   3720  CB  SER A 509      74.089  88.820  -0.410  1.00130.15           C  
+ANISOU 3720  CB  SER A 509    17685  17028  14738   4382  -3008  -3572       C  
+ATOM   3721  OG  SER A 509      74.991  89.319  -1.384  1.00125.27           O  
+ANISOU 3721  OG  SER A 509    16739  16248  14609   4003  -3376  -3749       O  
+ATOM   3722  N   SER A 510      72.520  86.615   1.263  1.00144.65           N  
+ANISOU 3722  N   SER A 510    20078  19123  15761   4999  -1878  -2899       N  
+ATOM   3723  CA  SER A 510      72.236  85.777   2.417  1.00148.97           C  
+ANISOU 3723  CA  SER A 510    21044  19713  15846   5526  -1487  -2677       C  
+ATOM   3724  C   SER A 510      72.424  84.315   2.046  1.00145.48           C  
+ANISOU 3724  C   SER A 510    20455  19266  15554   5204  -1182  -2426       C  
+ATOM   3725  O   SER A 510      73.001  83.552   2.811  1.00140.49           O  
+ANISOU 3725  O   SER A 510    20177  18606  14598   5539  -1145  -2415       O  
+ATOM   3726  CB  SER A 510      70.807  85.999   2.911  1.00149.05           C  
+ANISOU 3726  CB  SER A 510    21111  19824  15699   5832   -930  -2348       C  
+ATOM   3727  OG  SER A 510      70.346  84.882   3.643  1.00147.27           O  
+ANISOU 3727  OG  SER A 510    21097  19617  15240   6154   -337  -1962       O  
+ATOM   3728  N   SER A 511      71.946  83.946   0.858  1.00139.39           N  
+ANISOU 3728  N   SER A 511    19184  18508  15269   4583  -1004  -2249       N  
+ATOM   3729  CA  SER A 511      72.011  82.573   0.365  1.00129.68           C  
+ANISOU 3729  CA  SER A 511    17763  17254  14255   4236   -745  -2013       C  
+ATOM   3730  C   SER A 511      73.437  82.171   0.006  1.00129.30           C  
+ANISOU 3730  C   SER A 511    17762  17135  14232   4035  -1175  -2258       C  
+ATOM   3731  O   SER A 511      73.792  80.991   0.047  1.00109.17           O  
+ANISOU 3731  O   SER A 511    15254  14565  11659   3957  -1019  -2119       O  
+ATOM   3732  CB  SER A 511      71.108  82.416  -0.862  1.00125.40           C  
+ANISOU 3732  CB  SER A 511    16701  16703  14243   3684   -564  -1828       C  
+ATOM   3733  OG  SER A 511      71.167  81.106  -1.394  1.00137.08           O  
+ANISOU 3733  OG  SER A 511    17990  18125  15969   3359   -392  -1635       O  
+ATOM   3734  N   GLN A 512      74.247  83.164  -0.347  1.00131.12           N  
+ANISOU 3734  N   GLN A 512    17958  17304  14560   3957  -1699  -2603       N  
+ATOM   3735  CA  GLN A 512      75.621  82.941  -0.774  1.00120.52           C  
+ANISOU 3735  CA  GLN A 512    16587  15845  13361   3755  -2110  -2821       C  
+ATOM   3736  C   GLN A 512      76.508  82.796   0.431  1.00123.24           C  
+ANISOU 3736  C   GLN A 512    17385  16120  13322   4264  -2359  -3023       C  
+ATOM   3737  O   GLN A 512      77.569  82.174   0.385  1.00128.94           O  
+ANISOU 3737  O   GLN A 512    18162  16749  14081   4188  -2573  -3124       O  
+ATOM   3738  CB  GLN A 512      76.096  84.150  -1.546  1.00118.44           C  
+ANISOU 3738  CB  GLN A 512    16077  15483  13440   3537  -2531  -3073       C  
+ATOM   3739  CG  GLN A 512      76.798  83.822  -2.807  1.00125.91           C  
+ANISOU 3739  CG  GLN A 512    16711  16343  14787   3048  -2644  -3057       C  
+ATOM   3740  CD  GLN A 512      76.915  85.020  -3.690  1.00137.22           C  
+ANISOU 3740  CD  GLN A 512    17859  17690  16589   2843  -2877  -3186       C  
+ATOM   3741  OE1 GLN A 512      77.456  86.052  -3.281  1.00153.03           O  
+ANISOU 3741  OE1 GLN A 512    19904  19568  18672   3053  -3245  -3442       O  
+ATOM   3742  NE2 GLN A 512      76.353  84.922  -4.897  1.00128.62           N  
+ANISOU 3742  NE2 GLN A 512    16487  16643  15739   2470  -2678  -3017       N  
+ATOM   3743  N   GLY A 513      76.073  83.422   1.510  1.00128.93           N  
+ANISOU 3743  N   GLY A 513    18453  16869  13665   4826  -2362  -3100       N  
+ATOM   3744  CA  GLY A 513      76.767  83.309   2.761  1.00135.31           C  
+ANISOU 3744  CA  GLY A 513    19790  17602  14021   5449  -2610  -3308       C  
+ATOM   3745  C   GLY A 513      76.597  81.908   3.295  1.00133.10           C  
+ANISOU 3745  C   GLY A 513    19748  17398  13425   5620  -2132  -3010       C  
+ATOM   3746  O   GLY A 513      77.464  81.407   3.988  1.00135.48           O  
+ANISOU 3746  O   GLY A 513    20407  17622  13448   5952  -2344  -3163       O  
+ATOM   3747  N   THR A 514      75.478  81.270   2.971  1.00130.00           N  
+ANISOU 3747  N   THR A 514    19139  17128  13128   5402  -1499  -2584       N  
+ATOM   3748  CA  THR A 514      75.252  79.899   3.409  1.00136.05           C  
+ANISOU 3748  CA  THR A 514    20053  17932  13707   5525   -990  -2248       C  
+ATOM   3749  C   THR A 514      76.125  78.980   2.571  1.00136.91           C  
+ANISOU 3749  C   THR A 514    19914  17993  14111   4991  -1151  -2279       C  
+ATOM   3750  O   THR A 514      76.451  77.859   2.971  1.00136.85           O  
+ANISOU 3750  O   THR A 514    20093  17981  13923   5102   -944  -2139       O  
+ATOM   3751  CB  THR A 514      73.784  79.475   3.234  1.00141.83           C  
+ANISOU 3751  CB  THR A 514    20522  18734  14631   5408   -287  -1768       C  
+ATOM   3752  OG1 THR A 514      73.591  78.921   1.927  1.00142.93           O  
+ANISOU 3752  OG1 THR A 514    20113  18858  15336   4676   -233  -1640       O  
+ATOM   3753  CG2 THR A 514      72.861  80.659   3.413  1.00145.09           C  
+ANISOU 3753  CG2 THR A 514    20916  19192  15018   5620   -214  -1761       C  
+ATOM   3754  N   ILE A 515      76.491  79.473   1.394  1.00129.08           N  
+ANISOU 3754  N   ILE A 515    18518  16960  13565   4442  -1494  -2442       N  
+ATOM   3755  CA  ILE A 515      77.327  78.735   0.468  1.00119.39           C  
+ANISOU 3755  CA  ILE A 515    17053  15677  12633   3951  -1657  -2465       C  
+ATOM   3756  C   ILE A 515      78.787  78.796   0.895  1.00127.05           C  
+ANISOU 3756  C   ILE A 515    18275  16524  13475   4143  -2161  -2798       C  
+ATOM   3757  O   ILE A 515      79.482  77.778   0.906  1.00128.44           O  
+ANISOU 3757  O   ILE A 515    18530  16671  13600   4065  -2153  -2760       O  
+ATOM   3758  CB  ILE A 515      77.220  79.308  -0.945  1.00110.42           C  
+ANISOU 3758  CB  ILE A 515    15452  14516  11987   3401  -1815  -2500       C  
+ATOM   3759  CG1 ILE A 515      75.801  79.150  -1.481  1.00109.39           C  
+ANISOU 3759  CG1 ILE A 515    15038  14466  12060   3177  -1388  -2203       C  
+ATOM   3760  CG2 ILE A 515      78.168  78.587  -1.861  1.00112.80           C  
+ANISOU 3760  CG2 ILE A 515    15581  14743  12533   2997  -1979  -2516       C  
+ATOM   3761  CD1 ILE A 515      75.570  79.879  -2.780  1.00110.01           C  
+ANISOU 3761  CD1 ILE A 515    14740  14519  12538   2759  -1561  -2268       C  
+ATOM   3762  N   GLU A 516      79.240  79.996   1.247  1.00122.76           N  
+ANISOU 3762  N   GLU A 516    17837  15878  12927   4400  -2627  -3132       N  
+ATOM   3763  CA  GLU A 516      80.636  80.218   1.589  1.00124.18           C  
+ANISOU 3763  CA  GLU A 516    18172  15860  13149   4571  -3208  -3493       C  
+ATOM   3764  C   GLU A 516      81.099  79.274   2.681  1.00126.09           C  
+ANISOU 3764  C   GLU A 516    18894  16095  12918   5029  -3183  -3522       C  
+ATOM   3765  O   GLU A 516      82.117  78.595   2.539  1.00116.84           O  
+ANISOU 3765  O   GLU A 516    17721  14825  11848   4893  -3381  -3605       O  
+ATOM   3766  CB  GLU A 516      80.863  81.656   2.046  1.00135.21           C  
+ANISOU 3766  CB  GLU A 516    19658  17112  14603   4907  -3722  -3854       C  
+ATOM   3767  CG  GLU A 516      82.315  82.045   1.962  1.00146.41           C  
+ANISOU 3767  CG  GLU A 516    20992  18238  16400   4885  -4381  -4215       C  
+ATOM   3768  CD  GLU A 516      82.865  81.775   0.582  1.00151.28           C  
+ANISOU 3768  CD  GLU A 516    21100  18789  17590   4220  -4329  -4073       C  
+ATOM   3769  OE1 GLU A 516      82.373  82.413  -0.367  1.00146.52           O  
+ANISOU 3769  OE1 GLU A 516    20133  18221  17316   3867  -4198  -3957       O  
+ATOM   3770  OE2 GLU A 516      83.763  80.917   0.441  1.00154.24           O  
+ANISOU 3770  OE2 GLU A 516    21471  19078  18055   4089  -4397  -4065       O  
+END                                                                             
diff --git a/examples/testdata/4IM2_missing_noid.pdb b/examples/testdata/4IM2_missing_noid.pdb
new file mode 100644 (file)
index 0000000..5a5ef94
--- /dev/null
@@ -0,0 +1,524 @@
+TITLE     STRUCTURE OF TANK-BINDING KINASE 1  (Truncated test file)
+ATOM   3510  N   LEU A 468      76.337  90.332  -7.628  1.00168.53           N  
+ANISOU 3510  N   LEU A 468    19760  15191  29082   5189   1248  -1702       N  
+ATOM   3511  CA  LEU A 468      75.576  90.788  -6.476  1.00181.60           C  
+ANISOU 3511  CA  LEU A 468    21073  16927  30998   5158   1421  -2051       C  
+ATOM   3512  C   LEU A 468      76.285  91.971  -5.836  1.00196.57           C  
+ANISOU 3512  C   LEU A 468    23029  18636  33021   5053   1667  -2229       C  
+ATOM   3513  O   LEU A 468      75.727  93.067  -5.733  1.00197.97           O  
+ANISOU 3513  O   LEU A 468    23115  18581  33523   5166   1662  -2304       O  
+ATOM   3514  CB  LEU A 468      75.409  89.671  -5.449  1.00173.72           C  
+ANISOU 3514  CB  LEU A 468    19829  16340  29836   4981   1593  -2304       C  
+ATOM   3515  CG  LEU A 468      74.099  88.882  -5.420  1.00170.58           C  
+ANISOU 3515  CG  LEU A 468    19142  16142  29529   5074   1449  -2345       C  
+ATOM   3516  CD1 LEU A 468      74.023  87.940  -6.581  1.00167.98           C  
+ANISOU 3516  CD1 LEU A 468    18951  15858  29015   5180   1156  -2025       C  
+ATOM   3517  CD2 LEU A 468      73.988  88.096  -4.145  1.00165.16           C  
+ANISOU 3517  CD2 LEU A 468    18217  15818  28720   4865   1706  -2656       C  
+ATOM   3518  N   ASP A 469      77.529  91.753  -5.429  1.00208.80           N  
+ANISOU 3518  N   ASP A 469    24731  20282  34322   4836   1875  -2296       N  
+ATOM   3519  CA  ASP A 469      78.267  92.785  -4.720  1.00223.11           C  
+ANISOU 3519  CA  ASP A 469    26577  21960  36233   4701   2123  -2500       C  
+ATOM   3520  C   ASP A 469      78.653  93.973  -5.599  1.00231.96           C  
+ANISOU 3520  C   ASP A 469    27954  22654  37525   4817   2037  -2283       C  
+ATOM   3521  O   ASP A 469      78.718  95.100  -5.118  1.00235.71           O  
+ANISOU 3521  O   ASP A 469    28377  22940  38242   4798   2175  -2449       O  
+ATOM   3522  CB  ASP A 469      79.506  92.197  -4.057  1.00224.50           C  
+ANISOU 3522  CB  ASP A 469    26841  22370  36089   4433   2350  -2633       C  
+ATOM   3523  CG  ASP A 469      79.748  92.767  -2.679  1.00229.51           C  
+ANISOU 3523  CG  ASP A 469    27303  23107  36794   4254   2637  -3018       C  
+ATOM   3524  OD1 ASP A 469      79.958  93.992  -2.564  1.00232.36           O  
+ANISOU 3524  OD1 ASP A 469    27695  23203  37387   4262   2718  -3093       O  
+ATOM   3525  OD2 ASP A 469      79.751  91.979  -1.709  1.00229.48           O  
+ANISOU 3525  OD2 ASP A 469    27145  23450  36598   4098   2779  -3242       O  
+ATOM   3526  N   PHE A 470      78.904  93.735  -6.882  1.00233.88           N  
+ANISOU 3526  N   PHE A 470    28481  22742  37641   4931   1813  -1912       N  
+ATOM   3527  CA  PHE A 470      79.292  94.831  -7.766  1.00237.73           C  
+ANISOU 3527  CA  PHE A 470    29252  22819  38256   5033   1733  -1677       C  
+ATOM   3528  C   PHE A 470      78.103  95.470  -8.467  1.00232.15           C  
+ANISOU 3528  C   PHE A 470    28512  21868  37828   5322   1470  -1512       C  
+ATOM   3529  O   PHE A 470      78.021  96.691  -8.532  1.00230.69           O  
+ANISOU 3529  O   PHE A 470    28371  21372  37909   5402   1493  -1517       O  
+ATOM   3530  CB  PHE A 470      80.344  94.379  -8.784  1.00242.99           C  
+ANISOU 3530  CB  PHE A 470    30297  23410  38616   4976   1661  -1357       C  
+ATOM   3531  CG  PHE A 470      80.663  95.388  -9.839  1.00251.53           C  
+ANISOU 3531  CG  PHE A 470    31709  24074  39788   5089   1550  -1064       C  
+ATOM   3532  CD1 PHE A 470      81.658  96.315  -9.620  1.00252.90           C  
+ANISOU 3532  CD1 PHE A 470    32021  24036  40032   4942   1771  -1133       C  
+ATOM   3533  CD2 PHE A 470      80.005  95.389 -11.059  1.00255.02           C  
+ANISOU 3533  CD2 PHE A 470    32335  24339  40221   5330   1225   -715       C  
+ATOM   3534  CE1 PHE A 470      81.981  97.242 -10.575  1.00254.75           C  
+ANISOU 3534  CE1 PHE A 470    32569  23879  40344   5028   1688   -862       C  
+ATOM   3535  CE2 PHE A 470      80.321  96.320 -12.027  1.00256.76           C  
+ANISOU 3535  CE2 PHE A 470    32894  24173  40491   5427   1126   -433       C  
+ATOM   3536  CZ  PHE A 470      81.313  97.248 -11.784  1.00256.57           C  
+ANISOU 3536  CZ  PHE A 470    33006  23929  40550   5272   1365   -504       C  
+ATOM   3537  N   CYS A 471      77.190  94.665  -8.997  1.00176.88           N  
+ANISOU 3537  N   CYS A 471    20955  21812  24441   2225  -3821  -3711       N  
+ATOM   3538  CA  CYS A 471      76.124  95.233  -9.815  1.00176.41           C  
+ANISOU 3538  CA  CYS A 471    20820  21906  24301   2124  -3576  -3614       C  
+ATOM   3539  C   CYS A 471      74.868  95.631  -9.050  1.00176.82           C  
+ANISOU 3539  C   CYS A 471    21026  22206  23952   2247  -3588  -3734       C  
+ATOM   3540  O   CYS A 471      74.632  96.811  -8.854  1.00178.66           O  
+ANISOU 3540  O   CYS A 471    21175  22393  24314   2353  -3749  -3873       O  
+ATOM   3541  CB  CYS A 471      75.805  94.346 -11.019  1.00173.95           C  
+ANISOU 3541  CB  CYS A 471    20521  21694  23877   1925  -3217  -3359       C  
+ATOM   3542  SG  CYS A 471      76.954  94.571 -12.398  1.00273.04           S  
+ANISOU 3542  SG  CYS A 471    32850  33934  36957   1863  -3075  -3146       S  
+ATOM   3543  N   ILE A 472      74.068  94.670  -8.603  1.00173.50           N  
+ANISOU 3543  N   ILE A 472    20813  22023  23085   2253  -3402  -3662       N  
+ATOM   3544  CA  ILE A 472      72.771  95.033  -8.022  1.00171.09           C  
+ANISOU 3544  CA  ILE A 472    20616  21936  22453   2374  -3307  -3694       C  
+ATOM   3545  C   ILE A 472      72.832  96.022  -6.874  1.00177.82           C  
+ANISOU 3545  C   ILE A 472    21591  22750  23222   2698  -3611  -3931       C  
+ATOM   3546  O   ILE A 472      71.992  96.914  -6.776  1.00182.92           O  
+ANISOU 3546  O   ILE A 472    22220  23491  23792   2778  -3598  -3985       O  
+ATOM   3547  CB  ILE A 472      71.979  93.843  -7.518  1.00159.41           C  
+ANISOU 3547  CB  ILE A 472    19318  20653  20599   2393  -3038  -3546       C  
+ATOM   3548  CG1 ILE A 472      70.708  93.667  -8.341  1.00147.27           C  
+ANISOU 3548  CG1 ILE A 472    17653  19253  19051   2196  -2745  -3384       C  
+ATOM   3549  CG2 ILE A 472      71.526  94.090  -6.105  1.00155.95           C  
+ANISOU 3549  CG2 ILE A 472    19129  20312  19812   2752  -3085  -3637       C  
+ATOM   3550  CD1 ILE A 472      70.927  92.915  -9.606  1.00135.92           C  
+ANISOU 3550  CD1 ILE A 472    16097  17752  17794   1929  -2643  -3254       C  
+ATOM   3551  N   ARG A 473      73.812  95.865  -5.996  1.00180.33           N  
+ANISOU 3551  N   ARG A 473    22055  22917  23544   2920  -3920  -4092       N  
+ATOM   3552  CA  ARG A 473      73.860  96.762  -4.877  1.00189.65           C  
+ANISOU 3552  CA  ARG A 473    23415  24034  24610   3307  -4283  -4357       C  
+ATOM   3553  C   ARG A 473      74.328  98.021  -5.558  1.00185.98           C  
+ANISOU 3553  C   ARG A 473    22628  23344  24692   3195  -4530  -4477       C  
+ATOM   3554  O   ARG A 473      73.519  98.885  -5.866  1.00181.76           O  
+ANISOU 3554  O   ARG A 473    22002  22904  24153   3165  -4446  -4474       O  
+ATOM   3555  CB  ARG A 473      74.803  96.287  -3.768  1.00205.24           C  
+ANISOU 3555  CB  ARG A 473    25661  25862  26460   3635  -4629  -4545       C  
+ATOM   3556  CG  ARG A 473      74.468  96.921  -2.433  1.00220.50           C  
+ANISOU 3556  CG  ARG A 473    27955  27814  28011   4171  -4923  -4787       C  
+ATOM   3557  CD  ARG A 473      75.337  96.433  -1.295  1.00232.58           C  
+ANISOU 3557  CD  ARG A 473    29837  29192  29341   4591  -5300  -5003       C  
+ATOM   3558  NE  ARG A 473      76.763  96.602  -1.549  1.00237.46           N  
+ANISOU 3558  NE  ARG A 473    30220  29440  30564   4489  -5773  -5205       N  
+ATOM   3559  CZ  ARG A 473      77.716  95.991  -0.861  1.00240.32           C  
+ANISOU 3559  CZ  ARG A 473    30786  29623  30903   4725  -6098  -5371       C  
+ATOM   3560  NH1 ARG A 473      77.388  95.172   0.115  1.00241.12           N  
+ANISOU 3560  NH1 ARG A 473    31370  29900  30344   5100  -5978  -5355       N  
+ATOM   3561  NH2 ARG A 473      78.988  96.195  -1.159  1.00241.54           N  
+ANISOU 3561  NH2 ARG A 473    30651  29398  31724   4605  -6518  -5533       N  
+ATOM   3562  N   ASN A 474      75.608  98.073  -5.901  1.00188.74           N  
+ANISOU 3562  N   ASN A 474    22768  23381  25563   3107  -4772  -4534       N  
+ATOM   3563  CA  ASN A 474      76.168  99.264  -6.526  1.00188.61           C  
+ANISOU 3563  CA  ASN A 474    22395  23075  26194   3026  -4977  -4605       C  
+ATOM   3564  C   ASN A 474      75.420  99.892  -7.729  1.00173.98           C  
+ANISOU 3564  C   ASN A 474    20312  21326  24467   2781  -4623  -4414       C  
+ATOM   3565  O   ASN A 474      75.482 101.107  -7.891  1.00176.08           O  
+ANISOU 3565  O   ASN A 474    20374  21426  25104   2827  -4803  -4518       O  
+ATOM   3566  CB  ASN A 474      77.650  99.066  -6.857  1.00199.45           C  
+ANISOU 3566  CB  ASN A 474    23514  24060  28207   2939  -5170  -4595       C  
+ATOM   3567  CG  ASN A 474      78.504  98.809  -5.625  1.00210.23           C  
+ANISOU 3567  CG  ASN A 474    25062  25219  29597   3243  -5689  -4883       C  
+ATOM   3568  OD1 ASN A 474      78.174  99.240  -4.527  1.00215.26           O  
+ANISOU 3568  OD1 ASN A 474    25969  25891  29928   3596  -6043  -5160       O  
+ATOM   3569  ND2 ASN A 474      79.613  98.103  -5.810  1.00212.07           N  
+ANISOU 3569  ND2 ASN A 474    25176  25222  30179   3148  -5748  -4822       N  
+ATOM   3570  N   ILE A 475      74.722  99.114  -8.562  1.00161.86           N  
+ANISOU 3570  N   ILE A 475    18813  20033  22652   2556  -4165  -4158       N  
+ATOM   3571  CA  ILE A 475      74.022  99.727  -9.709  1.00154.84           C  
+ANISOU 3571  CA  ILE A 475    17755  19216  21861   2390  -3885  -4015       C  
+ATOM   3572  C   ILE A 475      72.785 100.520  -9.312  1.00159.27           C  
+ANISOU 3572  C   ILE A 475    18401  19995  22121   2490  -3891  -4125       C  
+ATOM   3573  O   ILE A 475      72.662 101.687  -9.663  1.00162.60           O  
+ANISOU 3573  O   ILE A 475    18651  20327  22804   2505  -3962  -4186       O  
+ATOM   3574  CB  ILE A 475      73.600  98.727 -10.818  1.00214.93           C  
+ANISOU 3574  CB  ILE A 475    25397  26975  29293   2173  -3475  -3753       C  
+ATOM   3575  CG1 ILE A 475      74.808  98.227 -11.613  1.00218.74           C  
+ANISOU 3575  CG1 ILE A 475    25753  27211  30145   2083  -3390  -3585       C  
+ATOM   3576  CG2 ILE A 475      72.618  99.379 -11.789  1.00210.37           C  
+ANISOU 3576  CG2 ILE A 475    24743  26509  28681   2097  -3256  -3677       C  
+ATOM   3577  CD1 ILE A 475      74.446  97.201 -12.664  1.00218.15           C  
+ANISOU 3577  CD1 ILE A 475    25777  27260  29850   1946  -3056  -3359       C  
+ATOM   3578  N   GLU A 476      71.856  99.893  -8.600  1.00156.45           N  
+ANISOU 3578  N   GLU A 476    18293  19907  21245   2571  -3778  -4120       N  
+ATOM   3579  CA  GLU A 476      70.623 100.594  -8.252  1.00142.72           C  
+ANISOU 3579  CA  GLU A 476    16627  18370  19231   2677  -3720  -4176       C  
+ATOM   3580  C   GLU A 476      70.845 101.560  -7.094  1.00144.41           C  
+ANISOU 3580  C   GLU A 476    16959  18500  19412   3012  -4114  -4440       C  
+ATOM   3581  O   GLU A 476      70.012 102.417  -6.811  1.00142.58           O  
+ANISOU 3581  O   GLU A 476    16768  18380  19024   3141  -4136  -4517       O  
+ATOM   3582  CB  GLU A 476      69.486  99.616  -7.958  1.00128.68           C  
+ANISOU 3582  CB  GLU A 476    15020  16860  17012   2665  -3395  -4018       C  
+ATOM   3583  CG  GLU A 476      69.562  98.905  -6.628  1.00128.73           C  
+ANISOU 3583  CG  GLU A 476    15321  16930  16662   2941  -3433  -4041       C  
+ATOM   3584  CD  GLU A 476      68.465  97.866  -6.484  1.00133.35           C  
+ANISOU 3584  CD  GLU A 476    15992  17719  16955   2900  -3026  -3806       C  
+ATOM   3585  OE1 GLU A 476      68.285  97.061  -7.422  1.00132.30           O  
+ANISOU 3585  OE1 GLU A 476    15710  17598  16962   2603  -2816  -3643       O  
+ATOM   3586  OE2 GLU A 476      67.768  97.860  -5.448  1.00136.37           O  
+ANISOU 3586  OE2 GLU A 476    16588  18223  17003   3196  -2912  -3773       O  
+ATOM   3587  N   LYS A 477      71.990 101.424  -6.439  1.00148.46           N  
+ANISOU 3587  N   LYS A 477    17534  18788  20087   3179  -4467  -4596       N  
+ATOM   3588  CA  LYS A 477      72.399 102.365  -5.405  1.00154.25           C  
+ANISOU 3588  CA  LYS A 477    18378  19348  20882   3544  -4976  -4907       C  
+ATOM   3589  C   LYS A 477      72.634 103.732  -5.994  1.00159.76           C  
+ANISOU 3589  C   LYS A 477    18754  19833  22117   3467  -5183  -5014       C  
+ATOM   3590  O   LYS A 477      72.568 104.742  -5.292  1.00158.01           O  
+ANISOU 3590  O   LYS A 477    18598  19516  21921   3749  -5568  -5266       O  
+ATOM   3591  CB  LYS A 477      73.667 101.883  -4.706  1.00154.03           C  
+ANISOU 3591  CB  LYS A 477    18446  19057  21022   3730  -5372  -5076       C  
+ATOM   3592  CG  LYS A 477      73.367 100.787  -3.750  1.00149.76           C  
+ANISOU 3592  CG  LYS A 477    18324  18717  19861   3975  -5258  -5042       C  
+ATOM   3593  CD  LYS A 477      74.437 100.554  -2.740  1.00143.39           C  
+ANISOU 3593  CD  LYS A 477    17737  17664  19082   4327  -5762  -5306       C  
+ATOM   3594  CE  LYS A 477      73.739 100.087  -1.488  1.00145.72           C  
+ANISOU 3594  CE  LYS A 477    18569  18186  18613   4805  -5697  -5337       C  
+ATOM   3595  NZ  LYS A 477      74.661  99.556  -0.469  1.00149.42           N  
+ANISOU 3595  NZ  LYS A 477    19366  18470  18936   5206  -6108  -5561       N  
+ATOM   3596  N   THR A 478      72.908 103.757  -7.293  1.00166.45           N  
+ANISOU 3596  N   THR A 478    19271  20589  23384   3124  -4918  -4810       N  
+ATOM   3597  CA  THR A 478      73.186 105.012  -7.968  1.00170.99           C  
+ANISOU 3597  CA  THR A 478    19509  20929  24531   3052  -5023  -4844       C  
+ATOM   3598  C   THR A 478      71.905 105.733  -8.391  1.00172.33           C  
+ANISOU 3598  C   THR A 478    19686  21358  24435   2999  -4780  -4796       C  
+ATOM   3599  O   THR A 478      71.021 105.170  -9.046  1.00163.10           O  
+ANISOU 3599  O   THR A 478    18581  20461  22928   2823  -4356  -4594       O  
+ATOM   3600  CB  THR A 478      74.217 104.856  -9.128  1.00146.93           C  
+ANISOU 3600  CB  THR A 478    16115  17589  22125   2815  -4843  -4626       C  
+ATOM   3601  OG1 THR A 478      74.873 106.106  -9.369  1.00147.15           O  
+ANISOU 3601  OG1 THR A 478    15790  17239  22881   2857  -5085  -4705       O  
+ATOM   3602  CG2 THR A 478      73.562 104.391 -10.425  1.00144.32           C  
+ANISOU 3602  CG2 THR A 478    15764  17473  21597   2570  -4282  -4318       C  
+ATOM   3603  N   VAL A 479      71.809 106.979  -7.944  1.00177.73           N  
+ANISOU 3603  N   VAL A 479    20309  21929  25291   3181  -5110  -5014       N  
+ATOM   3604  CA  VAL A 479      70.674 107.838  -8.218  1.00175.65           C  
+ANISOU 3604  CA  VAL A 479    20044  21875  24819   3171  -4959  -5013       C  
+ATOM   3605  C   VAL A 479      71.176 109.077  -8.939  1.00177.67           C  
+ANISOU 3605  C   VAL A 479    19928  21830  25749   3101  -5069  -5035       C  
+ATOM   3606  O   VAL A 479      72.353 109.417  -8.840  1.00179.02           O  
+ANISOU 3606  O   VAL A 479    19865  21600  26555   3150  -5387  -5121       O  
+ATOM   3607  CB  VAL A 479      69.983 108.266  -6.909  1.00168.37           C  
+ANISOU 3607  CB  VAL A 479    19442  21113  23418   3524  -5243  -5249       C  
+ATOM   3608  CG1 VAL A 479      69.008 109.403  -7.169  1.00162.23           C  
+ANISOU 3608  CG1 VAL A 479    18603  20470  22565   3531  -5176  -5285       C  
+ATOM   3609  CG2 VAL A 479      69.288 107.080  -6.256  1.00163.89           C  
+ANISOU 3609  CG2 VAL A 479    19236  20856  22180   3624  -4991  -5142       C  
+ATOM   3610  N   MET A 486      57.931 103.433  -6.150  1.00 92.00           N  
+ANISOU 3610  N   MET A 486    10154  13425  11375   3371  -1523  -3283       N  
+ATOM   3611  CA  MET A 486      56.824 104.104  -5.482  1.00110.61           C  
+ANISOU 3611  CA  MET A 486    12558  15882  13585   3644  -1287  -3161       C  
+ATOM   3612  C   MET A 486      56.182 105.150  -6.389  1.00111.38           C  
+ANISOU 3612  C   MET A 486    12428  16016  13877   3424  -1416  -3308       C  
+ATOM   3613  O   MET A 486      56.000 106.305  -6.002  1.00120.35           O  
+ANISOU 3613  O   MET A 486    13691  17243  14794   3639  -1526  -3430       O  
+ATOM   3614  CB  MET A 486      57.288 104.743  -4.170  1.00120.60           C  
+ANISOU 3614  CB  MET A 486    14253  17221  14347   4174  -1395  -3243       C  
+ATOM   3615  CG  MET A 486      58.405 105.768  -4.316  1.00126.87           C  
+ANISOU 3615  CG  MET A 486    15171  17987  15047   4196  -1944  -3629       C  
+ATOM   3616  SD  MET A 486      58.150 107.169  -3.210  1.00146.78           S  
+ANISOU 3616  SD  MET A 486    18044  20597  17128   4757  -2124  -3782       S  
+ATOM   3617  CE  MET A 486      58.003 106.326  -1.640  1.00102.35           C  
+ANISOU 3617  CE  MET A 486    12883  15002  11003   5391  -1797  -3524       C  
+ATOM   3618  N   GLY A 496      57.154  99.412  -2.065  1.00157.62           N  
+ANISOU 3618  N   GLY A 496    19150  21656  19083   4616     82  -2024       N  
+ATOM   3619  CA  GLY A 496      57.031  99.217  -3.498  1.00158.07           C  
+ANISOU 3619  CA  GLY A 496    18749  21636  19677   3991   -116  -2141       C  
+ATOM   3620  C   GLY A 496      57.664  97.914  -3.942  1.00163.71           C  
+ANISOU 3620  C   GLY A 496    19349  22235  20619   3709   -140  -2093       C  
+ATOM   3621  O   GLY A 496      58.040  97.090  -3.111  1.00167.17           O  
+ANISOU 3621  O   GLY A 496    20009  22652  20858   3970     79  -1915       O  
+ATOM   3622  N   GLU A 497      57.778  97.722  -5.254  1.00166.67           N  
+ANISOU 3622  N   GLU A 497    19413  22530  21383   3222   -403  -2250       N  
+ATOM   3623  CA  GLU A 497      58.431  96.534  -5.792  1.00170.73           C  
+ANISOU 3623  CA  GLU A 497    19840  22933  22098   2955   -485  -2239       C  
+ATOM   3624  C   GLU A 497      59.931  96.621  -5.556  1.00172.64           C  
+ANISOU 3624  C   GLU A 497    20403  23228  21965   3043   -809  -2472       C  
+ATOM   3625  O   GLU A 497      60.589  95.609  -5.311  1.00173.01           O  
+ANISOU 3625  O   GLU A 497    20547  23223  21965   3047   -764  -2395       O  
+ATOM   3626  CB  GLU A 497      58.173  96.394  -7.290  1.00169.62           C  
+ANISOU 3626  CB  GLU A 497    19361  22681  22408   2505   -727  -2374       C  
+ATOM   3627  CG  GLU A 497      56.882  97.012  -7.777  1.00173.11           C  
+ANISOU 3627  CG  GLU A 497    19518  23086  23171   2413   -663  -2350       C  
+ATOM   3628  CD  GLU A 497      56.703  96.840  -9.270  1.00173.61           C  
+ANISOU 3628  CD  GLU A 497    19329  23013  23621   2054   -974  -2531       C  
+ATOM   3629  OE1 GLU A 497      57.597  96.241  -9.908  1.00170.78           O  
+ANISOU 3629  OE1 GLU A 497    19040  22600  23250   1901  -1202  -2647       O  
+ATOM   3630  OE2 GLU A 497      55.672  97.300  -9.805  1.00174.73           O  
+ANISOU 3630  OE2 GLU A 497    19233  23093  24064   1967   -999  -2559       O  
+ATOM   3631  N   ILE A 498      60.466  97.836  -5.652  1.00171.44           N  
+ANISOU 3631  N   ILE A 498    20381  23149  21608   3107  -1147  -2757       N  
+ATOM   3632  CA  ILE A 498      61.883  98.078  -5.403  1.00167.93           C  
+ANISOU 3632  CA  ILE A 498    20186  22695  20926   3210  -1503  -2995       C  
+ATOM   3633  C   ILE A 498      62.251  97.620  -4.004  1.00173.82           C  
+ANISOU 3633  C   ILE A 498    21298  23465  21280   3659  -1379  -2903       C  
+ATOM   3634  O   ILE A 498      63.315  97.034  -3.789  1.00168.12           O  
+ANISOU 3634  O   ILE A 498    20732  22684  20462   3692  -1544  -2980       O  
+ATOM   3635  CB  ILE A 498      62.227  99.564  -5.520  1.00165.53           C  
+ANISOU 3635  CB  ILE A 498    19934  22420  20540   3287  -1855  -3283       C  
+ATOM   3636  CG1 ILE A 498      61.848 100.100  -6.901  1.00171.37           C  
+ANISOU 3636  CG1 ILE A 498    20360  23137  21618   2911  -1947  -3365       C  
+ATOM   3637  CG2 ILE A 498      63.706  99.798  -5.239  1.00153.61           C  
+ANISOU 3637  CG2 ILE A 498    18613  20820  18931   3398  -2256  -3525       C  
+ATOM   3638  CD1 ILE A 498      61.891 101.605  -6.996  1.00174.73           C  
+ANISOU 3638  CD1 ILE A 498    20793  23594  22004   2996  -2195  -3587       C  
+ATOM   3639  N   SER A 499      61.362  97.890  -3.054  1.00187.32           N  
+ANISOU 3639  N   SER A 499    23169  25252  22753   4049  -1074  -2727       N  
+ATOM   3640  CA  SER A 499      61.558  97.444  -1.683  1.00198.47           C  
+ANISOU 3640  CA  SER A 499    24999  26682  23729   4594   -880  -2593       C  
+ATOM   3641  C   SER A 499      61.611  95.926  -1.651  1.00206.95           C  
+ANISOU 3641  C   SER A 499    26003  27687  24943   4481   -548  -2315       C  
+ATOM   3642  O   SER A 499      62.302  95.334  -0.823  1.00211.11           O  
+ANISOU 3642  O   SER A 499    26867  28195  25151   4806   -533  -2293       O  
+ATOM   3643  CB  SER A 499      60.435  97.952  -0.780  1.00200.16           C  
+ANISOU 3643  CB  SER A 499    25385  26976  23690   5064   -498  -2368       C  
+ATOM   3644  OG  SER A 499      60.635  97.541   0.556  1.00203.12           O  
+ANISOU 3644  OG  SER A 499    26244  27359  23574   5697   -286  -2224       O  
+ATOM   3645  N   ASP A 500      60.877  95.300  -2.564  1.00209.43           N  
+ANISOU 3645  N   ASP A 500    25883  27938  25751   4040   -320  -2123       N  
+ATOM   3646  CA  ASP A 500      60.862  93.851  -2.655  1.00212.36           C  
+ANISOU 3646  CA  ASP A 500    26120  28207  26361   3883    -39  -1865       C  
+ATOM   3647  C   ASP A 500      62.097  93.307  -3.366  1.00203.21           C  
+ANISOU 3647  C   ASP A 500    24946  26999  25265   3557   -426  -2093       C  
+ATOM   3648  O   ASP A 500      62.511  92.195  -3.092  1.00204.96           O  
+ANISOU 3648  O   ASP A 500    25238  27165  25472   3573   -286  -1954       O  
+ATOM   3649  CB  ASP A 500      59.580  93.355  -3.335  1.00221.23           C  
+ANISOU 3649  CB  ASP A 500    26765  29217  28075   3573    287  -1593       C  
+ATOM   3650  CG  ASP A 500      58.346  93.583  -2.486  1.00233.55           C  
+ANISOU 3650  CG  ASP A 500    28310  30773  29657   3938    816  -1243       C  
+ATOM   3651  OD1 ASP A 500      58.502  93.807  -1.272  1.00239.09           O  
+ANISOU 3651  OD1 ASP A 500    29432  31558  29852   4492   1029  -1137       O  
+ATOM   3652  OD2 ASP A 500      57.226  93.532  -3.034  1.00237.24           O  
+ANISOU 3652  OD2 ASP A 500    28355  31128  30656   3709   1011  -1072       O  
+ATOM   3653  N   ILE A 501      62.692  94.094  -4.258  1.00192.67           N  
+ANISOU 3653  N   ILE A 501    23525  25673  24008   3292   -875  -2413       N  
+ATOM   3654  CA  ILE A 501      63.864  93.633  -5.007  1.00181.71           C  
+ANISOU 3654  CA  ILE A 501    22108  24215  22719   3006  -1195  -2587       C  
+ATOM   3655  C   ILE A 501      65.165  93.699  -4.196  1.00170.68           C  
+ANISOU 3655  C   ILE A 501    21064  22814  20972   3287  -1450  -2764       C  
+ATOM   3656  O   ILE A 501      65.940  92.735  -4.173  1.00164.70           O  
+ANISOU 3656  O   ILE A 501    20376  21999  20202   3222  -1476  -2736       O  
+ATOM   3657  CB  ILE A 501      64.023  94.385  -6.353  1.00138.03           C  
+ANISOU 3657  CB  ILE A 501    16341  18649  17453   2657  -1507  -2802       C  
+ATOM   3658  CG1 ILE A 501      63.385  93.589  -7.491  1.00130.33           C  
+ANISOU 3658  CG1 ILE A 501    15061  17587  16872   2296  -1411  -2683       C  
+ATOM   3659  CG2 ILE A 501      65.491  94.642  -6.682  1.00137.98           C  
+ANISOU 3659  CG2 ILE A 501    16437  18581  17410   2596  -1883  -3037       C  
+ATOM   3660  CD1 ILE A 501      61.877  93.516  -7.426  1.00127.50           C  
+ANISOU 3660  CD1 ILE A 501    14480  17217  16748   2292  -1111  -2482       C  
+ATOM   3661  N   HIS A 502      65.396  94.829  -3.532  1.00164.00           N  
+ANISOU 3661  N   HIS A 502    20439  22007  19869   3613  -1676  -2964       N  
+ATOM   3662  CA  HIS A 502      66.603  95.022  -2.737  1.00157.69           C  
+ANISOU 3662  CA  HIS A 502    19968  21147  18800   3931  -2029  -3195       C  
+ATOM   3663  C   HIS A 502      66.627  94.018  -1.594  1.00162.64           C  
+ANISOU 3663  C   HIS A 502    20933  21795  19069   4322  -1761  -3012       C  
+ATOM   3664  O   HIS A 502      67.677  93.496  -1.229  1.00164.35           O  
+ANISOU 3664  O   HIS A 502    21348  21935  19163   4433  -1971  -3125       O  
+ATOM   3665  CB  HIS A 502      66.654  96.452  -2.195  1.00150.83           C  
+ANISOU 3665  CB  HIS A 502    19272  20282  17755   4264  -2351  -3452       C  
+ATOM   3666  CG  HIS A 502      67.989  97.117  -2.348  1.00143.78           C  
+ANISOU 3666  CG  HIS A 502    18387  19223  17019   4248  -2929  -3804       C  
+ATOM   3667  ND1 HIS A 502      68.672  97.155  -3.544  1.00137.00           N  
+ANISOU 3667  ND1 HIS A 502    17193  18253  16609   3785  -3096  -3872       N  
+ATOM   3668  CD2 HIS A 502      68.759  97.787  -1.457  1.00140.15           C  
+ANISOU 3668  CD2 HIS A 502    18217  18647  16387   4674  -3387  -4099       C  
+ATOM   3669  CE1 HIS A 502      69.807  97.814  -3.383  1.00131.33           C  
+ANISOU 3669  CE1 HIS A 502    16503  17343  16055   3893  -3583  -4155       C  
+ATOM   3670  NE2 HIS A 502      69.883  98.208  -2.125  1.00130.34           N  
+ANISOU 3670  NE2 HIS A 502    16741  17200  15583   4416  -3815  -4326       N  
+ATOM   3671  N   THR A 503      65.450  93.751  -1.039  1.00163.37           N  
+ANISOU 3671  N   THR A 503    21080  21971  19022   4552  -1268  -2705       N  
+ATOM   3672  CA  THR A 503      65.295  92.771   0.033  1.00163.31           C  
+ANISOU 3672  CA  THR A 503    21384  21972  18696   4974   -872  -2437       C  
+ATOM   3673  C   THR A 503      65.393  91.327  -0.475  1.00151.49           C  
+ANISOU 3673  C   THR A 503    19659  20415  17484   4610   -614  -2206       C  
+ATOM   3674  O   THR A 503      65.955  90.464   0.198  1.00146.11           O  
+ANISOU 3674  O   THR A 503    19247  19705  16563   4853   -520  -2130       O  
+ATOM   3675  CB  THR A 503      63.956  92.972   0.783  1.00170.09           C  
+ANISOU 3675  CB  THR A 503    22342  22899  19387   5379   -334  -2106       C  
+ATOM   3676  OG1 THR A 503      64.026  94.162   1.576  1.00176.61           O  
+ANISOU 3676  OG1 THR A 503    23551  23775  19778   5902   -585  -2325       O  
+ATOM   3677  CG2 THR A 503      63.645  91.790   1.693  1.00171.53           C  
+ANISOU 3677  CG2 THR A 503    22747  23054  19374   5760    235  -1707       C  
+ATOM   3678  N   LYS A 504      64.865  91.071  -1.669  1.00141.41           N  
+ANISOU 3678  N   LYS A 504    17911  19106  16711   4058   -541  -2117       N  
+ATOM   3679  CA  LYS A 504      64.918  89.730  -2.251  1.00138.96           C  
+ANISOU 3679  CA  LYS A 504    17368  18711  16719   3706   -369  -1930       C  
+ATOM   3680  C   LYS A 504      66.335  89.382  -2.646  1.00142.04           C  
+ANISOU 3680  C   LYS A 504    17848  19062  17058   3520   -779  -2178       C  
+ATOM   3681  O   LYS A 504      66.762  88.230  -2.559  1.00134.46           O  
+ANISOU 3681  O   LYS A 504    16927  18053  16108   3463   -666  -2057       O  
+ATOM   3682  CB  LYS A 504      64.010  89.614  -3.477  1.00129.82           C  
+ANISOU 3682  CB  LYS A 504    15721  17488  16116   3223   -303  -1839       C  
+ATOM   3683  CG  LYS A 504      62.585  89.222  -3.164  1.00130.75           C  
+ANISOU 3683  CG  LYS A 504    15616  17544  16518   3307    225  -1458       C  
+ATOM   3684  N   LEU A 505      67.053  90.395  -3.100  1.00138.41           N  
+ANISOU 3684  N   LEU A 505    17394  18602  16593   3427  -1237  -2505       N  
+ATOM   3685  CA  LEU A 505      68.435  90.224  -3.458  1.00120.29           C  
+ANISOU 3685  CA  LEU A 505    15154  16230  14322   3285  -1619  -2726       C  
+ATOM   3686  C   LEU A 505      69.260  89.889  -2.223  1.00124.70           C  
+ANISOU 3686  C   LEU A 505    16126  16770  14484   3724  -1710  -2800       C  
+ATOM   3687  O   LEU A 505      70.166  89.052  -2.259  1.00124.02           O  
+ANISOU 3687  O   LEU A 505    16106  16619  14396   3643  -1808  -2823       O  
+ATOM   3688  CB  LEU A 505      68.966  91.499  -4.066  1.00109.42           C  
+ANISOU 3688  CB  LEU A 505    13673  14807  13094   3171  -2036  -3016       C  
+ATOM   3689  CG  LEU A 505      70.386  91.097  -4.404  1.00128.61           C  
+ANISOU 3689  CG  LEU A 505    16120  17111  15635   3034  -2336  -3157       C  
+ATOM   3690  CD1 LEU A 505      70.509  91.048  -5.920  1.00141.22           C  
+ANISOU 3690  CD1 LEU A 505    17393  18648  17616   2580  -2370  -3131       C  
+ATOM   3691  CD2 LEU A 505      71.441  91.946  -3.655  1.00114.58           C  
+ANISOU 3691  CD2 LEU A 505    14554  15224  13758   3350  -2784  -3462       C  
+ATOM   3692  N   LEU A 506      68.951  90.579  -1.132  1.00130.40           N  
+ANISOU 3692  N   LEU A 506    17159  17539  14847   4233  -1705  -2854       N  
+ATOM   3693  CA  LEU A 506      69.612  90.336   0.139  1.00131.63           C  
+ANISOU 3693  CA  LEU A 506    17798  17665  14549   4786  -1814  -2947       C  
+ATOM   3694  C   LEU A 506      69.501  88.865   0.507  1.00144.65           C  
+ANISOU 3694  C   LEU A 506    19548  19330  16080   4841  -1380  -2638       C  
+ATOM   3695  O   LEU A 506      70.448  88.287   1.024  1.00156.36           O  
+ANISOU 3695  O   LEU A 506    21304  20754  17351   5038  -1550  -2741       O  
+ATOM   3696  CB  LEU A 506      69.008  91.206   1.240  1.00120.17           C  
+ANISOU 3696  CB  LEU A 506    16713  16270  12675   5409  -1772  -2980       C  
+ATOM   3697  N   ARG A 507      68.351  88.260   0.214  1.00146.01           N  
+ANISOU 3697  N   ARG A 507    19470  19552  16453   4658   -839  -2263       N  
+ATOM   3698  CA  ARG A 507      68.159  86.831   0.443  1.00152.26           C  
+ANISOU 3698  CA  ARG A 507    20261  20320  17271   4649   -394  -1930       C  
+ATOM   3699  C   ARG A 507      69.164  86.004  -0.360  1.00145.14           C  
+ANISOU 3699  C   ARG A 507    19199  19352  16597   4200   -653  -2042       C  
+ATOM   3700  O   ARG A 507      69.471  84.873   0.007  1.00142.95           O  
+ANISOU 3700  O   ARG A 507    19044  19045  16224   4273   -450  -1882       O  
+ATOM   3701  CB  ARG A 507      66.724  86.401   0.111  1.00161.16           C  
+ANISOU 3701  CB  ARG A 507    21023  21434  18777   4463    165  -1523       C  
+ATOM   3702  CG  ARG A 507      65.661  86.975   1.046  1.00177.63           C  
+ANISOU 3702  CG  ARG A 507    23283  23565  20645   4978    585  -1290       C  
+ATOM   3703  CD  ARG A 507      64.263  86.468   0.696  1.00187.68           C  
+ANISOU 3703  CD  ARG A 507    24111  24757  22442   4769   1148   -857       C  
+ATOM   3704  NE  ARG A 507      63.229  87.082   1.527  1.00198.88           N  
+ANISOU 3704  NE  ARG A 507    25661  26202  23704   5259   1588   -600       N  
+ATOM   3705  CZ  ARG A 507      61.923  86.883   1.368  1.00205.71           C  
+ANISOU 3705  CZ  ARG A 507    26137  26967  25058   5169   2095   -210       C  
+ATOM   3706  NH1 ARG A 507      61.484  86.084   0.406  1.00207.33           N  
+ANISOU 3706  NH1 ARG A 507    25797  27020  25959   4610   2159    -75       N  
+ATOM   3707  NH2 ARG A 507      61.055  87.485   2.171  1.00208.11           N  
+ANISOU 3707  NH2 ARG A 507    26596  27293  25185   5668   2517     41       N  
+ATOM   3708  N   LEU A 508      69.681  86.579  -1.445  1.00134.19           N  
+ANISOU 3708  N   LEU A 508    17555  17933  15496   3776  -1072  -2294       N  
+ATOM   3709  CA  LEU A 508      70.654  85.888  -2.287  1.00125.06           C  
+ANISOU 3709  CA  LEU A 508    16259  16704  14555   3385  -1304  -2382       C  
+ATOM   3710  C   LEU A 508      72.070  85.983  -1.730  1.00133.75           C  
+ANISOU 3710  C   LEU A 508    17660  17739  15419   3609  -1705  -2655       C  
+ATOM   3711  O   LEU A 508      72.775  84.975  -1.650  1.00132.42           O  
+ANISOU 3711  O   LEU A 508    17581  17530  15202   3562  -1700  -2615       O  
+ATOM   3712  CB  LEU A 508      70.606  86.404  -3.726  1.00112.64           C  
+ANISOU 3712  CB  LEU A 508    14312  15095  13392   2907  -1513  -2482       C  
+ATOM   3713  CG  LEU A 508      69.271  86.186  -4.436  1.00113.17           C  
+ANISOU 3713  CG  LEU A 508    14056  15174  13769   2653  -1215  -2260       C  
+ATOM   3714  CD1 LEU A 508      69.459  86.184  -5.945  1.00106.22           C  
+ANISOU 3714  CD1 LEU A 508    12898  14225  13237   2216  -1432  -2343       C  
+ATOM   3715  CD2 LEU A 508      68.613  84.894  -3.968  1.00117.32           C  
+ANISOU 3715  CD2 LEU A 508    14560  15678  14341   2703   -779  -1932       C  
+ATOM   3716  N   SER A 509      72.491  87.188  -1.355  1.00130.72           N  
+ANISOU 3716  N   SER A 509    17414  17317  14936   3856  -2085  -2944       N  
+ATOM   3717  CA  SER A 509      73.767  87.347  -0.663  1.00136.66           C  
+ANISOU 3717  CA  SER A 509    18457  17948  15519   4156  -2531  -3236       C  
+ATOM   3718  C   SER A 509      73.698  86.583   0.646  1.00143.40           C  
+ANISOU 3718  C   SER A 509    19773  18845  15866   4687  -2319  -3138       C  
+ATOM   3719  O   SER A 509      74.680  85.977   1.082  1.00138.35           O  
+ANISOU 3719  O   SER A 509    19358  18121  15090   4839  -2521  -3256       O  
+ATOM   3720  CB  SER A 509      74.089  88.820  -0.410  1.00130.15           C  
+ANISOU 3720  CB  SER A 509    17685  17028  14738   4382  -3008  -3572       C  
+ATOM   3721  OG  SER A 509      74.991  89.319  -1.384  1.00125.27           O  
+ANISOU 3721  OG  SER A 509    16739  16248  14609   4003  -3376  -3749       O  
+ATOM   3722  N   SER A 510      72.520  86.615   1.263  1.00144.65           N  
+ANISOU 3722  N   SER A 510    20078  19123  15761   4999  -1878  -2899       N  
+ATOM   3723  CA  SER A 510      72.236  85.777   2.417  1.00148.97           C  
+ANISOU 3723  CA  SER A 510    21044  19713  15846   5526  -1487  -2677       C  
+ATOM   3724  C   SER A 510      72.424  84.315   2.046  1.00145.48           C  
+ANISOU 3724  C   SER A 510    20455  19266  15554   5204  -1182  -2426       C  
+ATOM   3725  O   SER A 510      73.001  83.552   2.811  1.00140.49           O  
+ANISOU 3725  O   SER A 510    20177  18606  14598   5539  -1145  -2415       O  
+ATOM   3726  CB  SER A 510      70.807  85.999   2.911  1.00149.05           C  
+ANISOU 3726  CB  SER A 510    21111  19824  15699   5832   -930  -2348       C  
+ATOM   3727  OG  SER A 510      70.346  84.882   3.643  1.00147.27           O  
+ANISOU 3727  OG  SER A 510    21097  19617  15240   6154   -337  -1962       O  
+ATOM   3728  N   SER A 511      71.946  83.946   0.858  1.00139.39           N  
+ANISOU 3728  N   SER A 511    19184  18508  15269   4583  -1004  -2249       N  
+ATOM   3729  CA  SER A 511      72.011  82.573   0.365  1.00129.68           C  
+ANISOU 3729  CA  SER A 511    17763  17254  14255   4236   -745  -2013       C  
+ATOM   3730  C   SER A 511      73.437  82.171   0.006  1.00129.30           C  
+ANISOU 3730  C   SER A 511    17762  17135  14232   4035  -1175  -2258       C  
+ATOM   3731  O   SER A 511      73.792  80.991   0.047  1.00109.17           O  
+ANISOU 3731  O   SER A 511    15254  14565  11659   3957  -1019  -2119       O  
+ATOM   3732  CB  SER A 511      71.108  82.416  -0.862  1.00125.40           C  
+ANISOU 3732  CB  SER A 511    16701  16703  14243   3684   -564  -1828       C  
+ATOM   3733  OG  SER A 511      71.167  81.106  -1.394  1.00137.08           O  
+ANISOU 3733  OG  SER A 511    17990  18125  15969   3359   -392  -1635       O  
+ATOM   3734  N   GLN A 512      74.247  83.164  -0.347  1.00131.12           N  
+ANISOU 3734  N   GLN A 512    17958  17304  14560   3957  -1699  -2603       N  
+ATOM   3735  CA  GLN A 512      75.621  82.941  -0.774  1.00120.52           C  
+ANISOU 3735  CA  GLN A 512    16587  15845  13361   3755  -2110  -2821       C  
+ATOM   3736  C   GLN A 512      76.508  82.796   0.431  1.00123.24           C  
+ANISOU 3736  C   GLN A 512    17385  16120  13322   4264  -2359  -3023       C  
+ATOM   3737  O   GLN A 512      77.569  82.174   0.385  1.00128.94           O  
+ANISOU 3737  O   GLN A 512    18162  16749  14081   4188  -2573  -3124       O  
+ATOM   3738  CB  GLN A 512      76.096  84.150  -1.546  1.00118.44           C  
+ANISOU 3738  CB  GLN A 512    16077  15483  13440   3537  -2531  -3073       C  
+ATOM   3739  CG  GLN A 512      76.798  83.822  -2.807  1.00125.91           C  
+ANISOU 3739  CG  GLN A 512    16711  16343  14787   3048  -2644  -3057       C  
+ATOM   3740  CD  GLN A 512      76.915  85.020  -3.690  1.00137.22           C  
+ANISOU 3740  CD  GLN A 512    17859  17690  16589   2843  -2877  -3186       C  
+ATOM   3741  OE1 GLN A 512      77.456  86.052  -3.281  1.00153.03           O  
+ANISOU 3741  OE1 GLN A 512    19904  19568  18672   3053  -3245  -3442       O  
+ATOM   3742  NE2 GLN A 512      76.353  84.922  -4.897  1.00128.62           N  
+ANISOU 3742  NE2 GLN A 512    16487  16643  15739   2470  -2678  -3017       N  
+ATOM   3743  N   GLY A 513      76.073  83.422   1.510  1.00128.93           N  
+ANISOU 3743  N   GLY A 513    18453  16869  13665   4826  -2362  -3100       N  
+ATOM   3744  CA  GLY A 513      76.767  83.309   2.761  1.00135.31           C  
+ANISOU 3744  CA  GLY A 513    19790  17602  14021   5449  -2610  -3308       C  
+ATOM   3745  C   GLY A 513      76.597  81.908   3.295  1.00133.10           C  
+ANISOU 3745  C   GLY A 513    19748  17398  13425   5620  -2132  -3010       C  
+ATOM   3746  O   GLY A 513      77.464  81.407   3.988  1.00135.48           O  
+ANISOU 3746  O   GLY A 513    20407  17622  13448   5952  -2344  -3163       O  
+ATOM   3747  N   THR A 514      75.478  81.270   2.971  1.00130.00           N  
+ANISOU 3747  N   THR A 514    19139  17128  13128   5402  -1499  -2584       N  
+ATOM   3748  CA  THR A 514      75.252  79.899   3.409  1.00136.05           C  
+ANISOU 3748  CA  THR A 514    20053  17932  13707   5525   -990  -2248       C  
+ATOM   3749  C   THR A 514      76.125  78.980   2.571  1.00136.91           C  
+ANISOU 3749  C   THR A 514    19914  17993  14111   4991  -1151  -2279       C  
+ATOM   3750  O   THR A 514      76.451  77.859   2.971  1.00136.85           O  
+ANISOU 3750  O   THR A 514    20093  17981  13923   5102   -944  -2139       O  
+ATOM   3751  CB  THR A 514      73.784  79.475   3.234  1.00141.83           C  
+ANISOU 3751  CB  THR A 514    20522  18734  14631   5408   -287  -1768       C  
+ATOM   3752  OG1 THR A 514      73.591  78.921   1.927  1.00142.93           O  
+ANISOU 3752  OG1 THR A 514    20113  18858  15336   4676   -233  -1640       O  
+ATOM   3753  CG2 THR A 514      72.861  80.659   3.413  1.00145.09           C  
+ANISOU 3753  CG2 THR A 514    20916  19192  15018   5620   -214  -1761       C  
+ATOM   3754  N   ILE A 515      76.491  79.473   1.394  1.00129.08           N  
+ANISOU 3754  N   ILE A 515    18518  16960  13565   4442  -1494  -2442       N  
+ATOM   3755  CA  ILE A 515      77.327  78.735   0.468  1.00119.39           C  
+ANISOU 3755  CA  ILE A 515    17053  15677  12633   3951  -1657  -2465       C  
+ATOM   3756  C   ILE A 515      78.787  78.796   0.895  1.00127.05           C  
+ANISOU 3756  C   ILE A 515    18275  16524  13475   4143  -2161  -2798       C  
+ATOM   3757  O   ILE A 515      79.482  77.778   0.906  1.00128.44           O  
+ANISOU 3757  O   ILE A 515    18530  16671  13600   4065  -2153  -2760       O  
+ATOM   3758  CB  ILE A 515      77.220  79.308  -0.945  1.00110.42           C  
+ANISOU 3758  CB  ILE A 515    15452  14516  11987   3401  -1815  -2500       C  
+ATOM   3759  CG1 ILE A 515      75.801  79.150  -1.481  1.00109.39           C  
+ANISOU 3759  CG1 ILE A 515    15038  14466  12060   3177  -1388  -2203       C  
+ATOM   3760  CG2 ILE A 515      78.168  78.587  -1.861  1.00112.80           C  
+ANISOU 3760  CG2 ILE A 515    15581  14743  12533   2997  -1979  -2516       C  
+ATOM   3761  CD1 ILE A 515      75.570  79.879  -2.780  1.00110.01           C  
+ANISOU 3761  CD1 ILE A 515    14740  14519  12538   2759  -1561  -2268       C  
+ATOM   3762  N   GLU A 516      79.240  79.996   1.247  1.00122.76           N  
+ANISOU 3762  N   GLU A 516    17837  15878  12927   4400  -2627  -3132       N  
+ATOM   3763  CA  GLU A 516      80.636  80.218   1.589  1.00124.18           C  
+ANISOU 3763  CA  GLU A 516    18172  15860  13149   4571  -3208  -3493       C  
+ATOM   3764  C   GLU A 516      81.099  79.274   2.681  1.00126.09           C  
+ANISOU 3764  C   GLU A 516    18894  16095  12918   5029  -3183  -3522       C  
+ATOM   3765  O   GLU A 516      82.117  78.595   2.539  1.00116.84           O  
+ANISOU 3765  O   GLU A 516    17721  14825  11848   4893  -3381  -3605       O  
+ATOM   3766  CB  GLU A 516      80.863  81.656   2.046  1.00135.21           C  
+ANISOU 3766  CB  GLU A 516    19658  17112  14603   4907  -3722  -3854       C  
+ATOM   3767  CG  GLU A 516      82.315  82.045   1.962  1.00146.41           C  
+ANISOU 3767  CG  GLU A 516    20992  18238  16400   4885  -4381  -4215       C  
+ATOM   3768  CD  GLU A 516      82.865  81.775   0.582  1.00151.28           C  
+ANISOU 3768  CD  GLU A 516    21100  18789  17590   4220  -4329  -4073       C  
+ATOM   3769  OE1 GLU A 516      82.373  82.413  -0.367  1.00146.52           O  
+ANISOU 3769  OE1 GLU A 516    20133  18221  17316   3867  -4198  -3957       O  
+ATOM   3770  OE2 GLU A 516      83.763  80.917   0.441  1.00154.24           O  
+ANISOU 3770  OE2 GLU A 516    21471  19078  18055   4089  -4397  -4065       O  
+END                                                                             
diff --git a/examples/testdata/4IM2_nterm.pdb b/examples/testdata/4IM2_nterm.pdb
new file mode 100644 (file)
index 0000000..48f7803
--- /dev/null
@@ -0,0 +1,139 @@
+HEADER    TRANSFERASE/TRANSFERASE INHIBITOR       01-JAN-13   4IM2              
+TITLE     STRUCTURE OF TANK-BINDING KINASE 1  (Truncated test file)
+DBREF  4IM2 A    1   657  UNP    Q9UHD2   TBK1_HUMAN       1    657             
+SEQADV 4IM2 GLY A   -5  UNP  Q9UHD2              EXPRESSION TAG                 
+SEQADV 4IM2 SER A   -4  UNP  Q9UHD2              EXPRESSION TAG                 
+SEQADV 4IM2 GLY A   -3  UNP  Q9UHD2              EXPRESSION TAG                 
+SEQADV 4IM2 SER A   -2  UNP  Q9UHD2              EXPRESSION TAG                 
+SEQADV 4IM2 GLY A   -1  UNP  Q9UHD2              EXPRESSION TAG                 
+SEQADV 4IM2 SER A    0  UNP  Q9UHD2              EXPRESSION TAG                 
+SEQRES   1 A  663  GLY SER GLY SER GLY SER MET GLN SER THR SER ASN HIS
+ATOM      1  N   GLY A  -1     126.784   4.226 -23.353  1.00158.13           N  
+ANISOU    1  N   GLY A  -1    19370  17517  23197   6628   1162   2075       N  
+ATOM      2  CA  GLY A  -1     125.521   4.306 -24.062  1.00150.94           C  
+ANISOU    2  CA  GLY A  -1    18746  16231  22374   6153   1277   1996       C  
+ATOM      3  C   GLY A  -1     125.742   4.361 -25.557  1.00146.29           C  
+ANISOU    3  C   GLY A  -1    18187  15453  21943   5900   1405   1498       C  
+ATOM      4  O   GLY A  -1     126.691   4.980 -26.029  1.00150.85           O  
+ANISOU    4  O   GLY A  -1    18536  16366  22413   5906   1385   1160       O  
+ATOM      5  N   SER A   0     124.869   3.710 -26.313  1.00137.36           N  
+ANISOU    5  N   SER A   0    17328  13796  21068   5675   1550   1432       N  
+ATOM      6  CA  SER A   0     125.052   3.672 -27.755  1.00139.44           C  
+ANISOU    6  CA  SER A   0    17634  13884  21461   5464   1674    953       C  
+ATOM      7  C   SER A   0     123.846   4.104 -28.574  1.00137.43           C  
+ANISOU    7  C   SER A   0    17591  13478  21149   4975   1714    755       C  
+ATOM      8  O   SER A   0     122.737   4.275 -28.071  1.00128.25           O  
+ANISOU    8  O   SER A   0    16566  12244  19921   4780   1667    988       O  
+ATOM      9  CB  SER A   0     125.578   2.312 -28.214  1.00155.09           C  
+ANISOU    9  CB  SER A   0    19671  15395  23862   5752   1827    887       C  
+ATOM     10  OG  SER A   0     126.993   2.281 -28.131  1.00164.59           O  
+ANISOU   10  OG  SER A   0    20608  16866  25062   6113   1802    781       O  
+ATOM     11  N   MET A   1     124.096   4.270 -29.861  1.00134.87           N  
+ANISOU   11  N   MET A   1    17283  13123  20839   4799   1805    311       N  
+ATOM     12  CA  MET A   1     123.214   5.039 -30.698  1.00125.22           C  
+ANISOU   12  CA  MET A   1    16193  11958  19428   4369   1804     70       C  
+ATOM     13  C   MET A   1     122.885   4.351 -32.006  1.00124.69           C  
+ANISOU   13  C   MET A   1    16293  11510  19572   4225   1942   -293       C  
+ATOM     14  O   MET A   1     123.723   3.686 -32.606  1.00129.61           O  
+ANISOU   14  O   MET A   1    16868  11984  20394   4414   2057   -519       O  
+ATOM     15  CB  MET A   1     123.867   6.392 -30.970  1.00122.51           C  
+ANISOU   15  CB  MET A   1    15675  12140  18732   4254   1762   -132       C  
+ATOM     16  CG  MET A   1     125.074   6.368 -31.866  1.00120.74           C  
+ANISOU   16  CG  MET A   1    15318  12013  18544   4369   1884   -495       C  
+ATOM     17  SD  MET A   1     125.834   7.982 -31.850  1.00196.33           S  
+ANISOU   17  SD  MET A   1    24655  22193  27747   4246   1861   -642       S  
+ATOM     18  CE  MET A   1     126.785   7.896 -30.345  1.00132.53           C  
+ANISOU   18  CE  MET A   1    16264  14397  19693   4639   1728   -355       C  
+ATOM     19  N   GLN A   2     121.643   4.496 -32.440  1.00123.78           N  
+ANISOU   19  N   GLN A   2    16363  11253  19416   3898   1925   -369       N  
+ATOM     20  CA  GLN A   2     121.313   4.161 -33.809  1.00128.51           C  
+ANISOU   20  CA  GLN A   2    17093  11643  20094   3714   2020   -799       C  
+ATOM     21  C   GLN A   2     121.639   5.396 -34.617  1.00121.06           C  
+ANISOU   21  C   GLN A   2    16105  11138  18752   3541   2004  -1065       C  
+ATOM     22  O   GLN A   2     121.959   6.442 -34.059  1.00107.32           O  
+ANISOU   22  O   GLN A   2    14247   9790  16739   3528   1928   -906       O  
+ATOM     23  CB  GLN A   2     119.832   3.845 -33.965  1.00136.11           C  
+ANISOU   23  CB  GLN A   2    18240  12314  21161   3439   1994   -809       C  
+ATOM     24  CG  GLN A   2     119.171   3.277 -32.740  1.00148.45           C  
+ANISOU   24  CG  GLN A   2    19841  13613  22949   3500   1973   -376       C  
+ATOM     25  CD  GLN A   2     117.773   2.799 -33.042  1.00158.28           C  
+ANISOU   25  CD  GLN A   2    21243  14511  24385   3221   1993   -473       C  
+ATOM     26  OE1 GLN A   2     116.827   3.097 -32.313  1.00163.28           O  
+ANISOU   26  OE1 GLN A   2    21915  15160  24966   3070   1921   -211       O  
+ATOM     27  NE2 GLN A   2     117.631   2.057 -34.134  1.00155.02           N  
+ANISOU   27  NE2 GLN A   2    20902  13797  24200   3144   2095   -885       N  
+ATOM     28  N   SER A   3     121.547   5.280 -35.931  1.00124.66           N  
+ANISOU   28  N   SER A   3    16661  11530  19175   3410   2090  -1474       N  
+ATOM     29  CA  SER A   3     121.742   6.432 -36.781  1.00120.35           C  
+ANISOU   29  CA  SER A   3    16121  11369  18236   3242   2107  -1703       C  
+ATOM     30  C   SER A   3     121.190   6.186 -38.161  1.00125.27           C  
+ANISOU   30  C   SER A   3    16914  11882  18801   3073   2165  -2108       C  
+ATOM     31  O   SER A   3     120.746   5.090 -38.489  1.00135.86           O  
+ANISOU   31  O   SER A   3    18337  12848  20436   3082   2197  -2268       O  
+ATOM     32  CB  SER A   3     123.217   6.751 -36.923  1.00116.70           C  
+ANISOU   32  CB  SER A   3    15475  11153  17711   3435   2220  -1807       C  
+ATOM     33  OG  SER A   3     123.770   5.974 -37.974  1.00112.78           O  
+ANISOU   33  OG  SER A   3    15005  10478  17367   3528   2375  -2175       O  
+ATOM     34  N   THR A   4     121.244   7.232 -38.972  1.00116.48           N  
+ANISOU   34  N   THR A   4    15849  11109  17301   2928   2191  -2281       N  
+ATOM     35  CA  THR A   4     120.978   7.130 -40.394  1.00113.12           C  
+ANISOU   35  CA  THR A   4    15568  10691  16723   2823   2262  -2692       C  
+ATOM     36  C   THR A   4     122.118   7.839 -41.119  1.00116.32           C  
+ANISOU   36  C   THR A   4    15918  11410  16867   2884   2432  -2867       C  
+ATOM     37  O   THR A   4     123.106   8.236 -40.495  1.00117.17           O  
+ANISOU   37  O   THR A   4    15851  11671  16998   3007   2493  -2706       O  
+ATOM     38  CB  THR A   4     119.615   7.756 -40.775  1.00106.20           C  
+ANISOU   38  CB  THR A   4    14854   9927  15568   2568   2121  -2713       C  
+ATOM     39  OG1 THR A   4     119.774   9.154 -41.043  1.00107.14           O  
+ANISOU   39  OG1 THR A   4    15001  10451  15258   2480   2138  -2644       O  
+ATOM     40  CG2 THR A   4     118.597   7.567 -39.657  1.00 99.42           C  
+ANISOU   40  CG2 THR A   4    13990   8889  14896   2483   1956  -2396       C  
+ATOM     41  N   SER A   5     121.981   7.982 -42.432  1.00116.70           N  
+ANISOU   41  N   SER A   5    16106  11564  16670   2803   2517  -3210       N  
+ATOM     42  CA  SER A   5     122.975   8.671 -43.247  1.00122.60           C  
+ANISOU   42  CA  SER A   5    16837  12604  17144   2839   2721  -3385       C  
+ATOM     43  C   SER A   5     123.317  10.064 -42.713  1.00128.43           C  
+ANISOU   43  C   SER A   5    17501  13666  17630   2768   2748  -3105       C  
+ATOM     44  O   SER A   5     124.481  10.467 -42.712  1.00133.01           O  
+ANISOU   44  O   SER A   5    17934  14410  18193   2852   2925  -3133       O  
+ATOM     45  CB  SER A   5     122.473   8.779 -44.687  1.00127.34           C  
+ANISOU   45  CB  SER A   5    17646  13318  17418   2741   2774  -3729       C  
+ATOM     46  OG  SER A   5     121.108   9.163 -44.712  1.00135.31           O  
+ANISOU   46  OG  SER A   5    18807  14370  18235   2568   2576  -3643       O  
+ATOM     47  N   ASN A   6     122.303  10.783 -42.240  1.00122.78           N  
+ANISOU   47  N   ASN A   6    16868  13033  16750   2608   2581  -2859       N  
+ATOM     48  CA  ASN A   6     122.460  12.194 -41.897  1.00114.44           C  
+ANISOU   48  CA  ASN A   6    15777  12275  15429   2507   2620  -2639       C  
+ATOM     49  C   ASN A   6     122.348  12.537 -40.412  1.00108.55           C  
+ANISOU   49  C   ASN A   6    14870  11544  14832   2498   2474  -2282       C  
+ATOM     50  O   ASN A   6     122.712  13.640 -40.004  1.00110.16           O  
+ANISOU   50  O   ASN A   6    14983  11984  14890   2435   2531  -2135       O  
+ATOM     51  CB  ASN A   6     121.461  13.034 -42.695  1.00113.00           C  
+ANISOU   51  CB  ASN A   6    15832  12254  14850   2339   2583  -2658       C  
+ATOM     52  CG  ASN A   6     121.646  12.886 -44.191  1.00118.14           C  
+ANISOU   52  CG  ASN A   6    16648  12982  15257   2366   2743  -2999       C  
+ATOM     53  OD1 ASN A   6     122.765  12.952 -44.698  1.00122.16           O  
+ANISOU   53  OD1 ASN A   6    17097  13580  15737   2449   2985  -3154       O  
+ATOM     54  ND2 ASN A   6     120.546  12.672 -44.905  1.00118.96           N  
+ANISOU   54  ND2 ASN A   6    16946  13074  15179   2302   2609  -3139       N  
+ATOM     55  N   HIS A   7     121.845  11.605 -39.608  1.00100.48           N  
+ANISOU   55  N   HIS A   7    13810  10269  14098   2560   2305  -2149       N  
+ATOM     56  CA  HIS A   7     121.657  11.871 -38.183  1.00 91.49           C  
+ANISOU   56  CA  HIS A   7    12535   9160  13066   2569   2162  -1799       C  
+ATOM     57  C   HIS A   7     122.134  10.725 -37.300  1.00 97.74           C  
+ANISOU   57  C   HIS A   7    13180   9725  14232   2793   2117  -1685       C  
+ATOM     58  O   HIS A   7     122.456   9.647 -37.791  1.00101.23           O  
+ANISOU   58  O   HIS A   7    13643   9923  14898   2924   2188  -1876       O  
+ATOM     59  CB  HIS A   7     120.189  12.175 -37.884  1.00 86.30           C  
+ANISOU   59  CB  HIS A   7    12021   8464  12306   2383   1977  -1628       C  
+ATOM     60  CG  HIS A   7     119.634  13.303 -38.694  1.00101.46           C  
+ANISOU   60  CG  HIS A   7    14094  10603  13853   2201   2000  -1699       C  
+ATOM     61  ND1 HIS A   7     119.265  13.157 -40.015  1.00 99.83           N  
+ANISOU   61  ND1 HIS A   7    14076  10384  13472   2153   2049  -1976       N  
+ATOM     62  CD2 HIS A   7     119.401  14.600 -38.379  1.00 89.60           C  
+ANISOU   62  CD2 HIS A   7    12588   9342  12114   2078   1988  -1527       C  
+ATOM     63  CE1 HIS A   7     118.823  14.314 -40.476  1.00 97.86           C  
+ANISOU   63  CE1 HIS A   7    13944  10363  12875   2029   2062  -1939       C  
+ATOM     64  NE2 HIS A   7     118.896  15.206 -39.503  1.00 93.14           N  
+ANISOU   64  NE2 HIS A   7    13235   9899  12253   1975   2035  -1667       N  
+END                                                                             
index 732f01b..f129193 100755 (executable)
@@ -22,7 +22,7 @@
    <mapID target="home" url="html/index.html" />
    
    <mapID target="new" url="html/whatsNew.html"/>
-   <mapID target="release" url="html/releases.html#Jalview.2.10.3b1"/>
+   <mapID target="release" url="html/releases.html#Jalview.2.10.4"/>
    <mapID target="alannotation" url="html/features/annotation.html"/>
    <mapID target="keys" url="html/keys.html"/>
    <mapID target="newkeys" url="html/features/newkeystrokes.html"/>
index be1bd66..e1c07c1 100644 (file)
@@ -76,7 +76,7 @@
       or <strong>"View&#8594;Nucleotide"</strong> (in the protein panel)
       allows you to show or hide one or other of the linked alignment
       panels.</li>
-    <li>Panel heights are adjusted dragging the divider between
+    <li>Panel heights are adjusted by dragging the divider between
       them using the mouse</li>
     <li><a href="../menus/alwview.html"><strong>"View&#8594;New
           View / Expand Views / Gather Views"</strong></a> behave as for a normal
index 83d2ce4..6f15361 100755 (executable)
@@ -70,6 +70,35 @@ li:before {
     <tr>
       <td width="60" nowrap>
         <div align="center">
+          <strong><a name="Jalview.2.10.4">2.10.4</a><br /> <em>27/02/2018</em></strong>
+        </div>
+      </td>
+      <td><div align="left">
+          <em></em>
+          <ul>
+            <li>
+              <!-- JAL-984 -->Mouse cursor changes to indicate Sequence ID and annotation area margins can be click-dragged to adjust them.</li> 
+            <li>
+            <!-- JAL-2885 -->Jalview uses HTTPS for Uniprot, Xfam and Ensembl services 
+            </li>
+          </ul>
+          </div>
+      </td>
+      <td><div align="left">
+          <ul>
+            <li>
+              <!-- JAL-2778 -->Slow redraw when Overview panel shown overlapping alignment panel
+            </li>
+            <li>
+              <!-- JAL-2666 -->Linked scrolling via protein horizontal scroll bar doesn't work for some CDS/Protein views 
+            </li>
+          </ul>
+      </div>
+      </td>
+    </tr>
+    <tr>
+      <td width="60" nowrap>
+        <div align="center">
           <strong><a name="Jalview.2.10.3b1">2.10.3b1</a><br /> <em>24/1/2018</em></strong>
         </div>
       </td>
index 6d75f0f..d3972f5 100755 (executable)
 </head>
 <body>
   <p>
-    <strong>What's new in Jalview 2.10.3b1 ?</strong>
+    <strong>What's new in Jalview 2.10.4 ?</strong>
   </p>
   <p>
-    This is the January 2018 patch release, which addresses critical bugs including trackpad function in OSX, and display of multiple 3D structures. 
-    The full list bugs fixed in this release can be found in the <a href="releases.html#Jalview.2.10.3b1">2.10.3b1
-      Release Notes</a>. In addition, Jalview 2.10.3 provides:
+    This is the February 2018 release of Jalview, with several minor bug fixes and enhanvements. 
+    The full list bugs fixed in this release can be found in the <a href="releases.html#Jalview.2.10.4">2.10.4
+      Release Notes</a>. In addition, Jalview 2.10.4 provides:
   </p>
   <ul>
-    <li>Faster and more responsive UI when importing and working
-      with wide alignments and handling hundreds and thousands of
-      sequence features</li>
-    <li>Improved usability with <a
-      href="features/pdbsequencefetcher.html">PDB</a> and <a
-      href="features/uniprotsequencefetcher.html">UniProt</a> Free Text
-      Search dialog, and new tab for retrieval of sequences for lists of
-      IDs.
-    </li>
-    <li>Short names assigned to sequences retrieved from UniProt</li>
-    <li>Groovy console upgraded to 2.4.12 (improved support for Java 9)</li>
+    <li></li>
   </ul>
   <p>
     <strong><a name="experimental">Experimental Features</a></strong>
diff --git a/resources/images/idwidth.gif b/resources/images/idwidth.gif
deleted file mode 100755 (executable)
index c1bd8cb..0000000
Binary files a/resources/images/idwidth.gif and /dev/null differ
index f4bd31c..29b994e 100755 (executable)
@@ -162,6 +162,50 @@ public class PDBChain
   }
 
   /**
+   * Annotate the residues with their corresponding positions in s1 using the
+   * alignment in as NOTE: This clears all atom.alignmentMapping values on the
+   * structure.
+   * 
+   * @param as
+   * @param s1
+   */
+  public void makeExactMapping(StructureMapping mapping, SequenceI s1)
+  {
+    // first clear out any old alignmentMapping values:
+    for (Atom atom : atoms)
+    {
+      atom.alignmentMapping = -1;
+    }
+    SequenceI ds = s1;
+    while (ds.getDatasetSequence() != null)
+    {
+      ds = ds.getDatasetSequence();
+    }
+    int pdboffset = 0;
+    for (Residue res : residues)
+    {
+      // res.number isn't set correctly for discontinuous/mismapped residues
+      int seqpos = mapping.getSeqPos(res.atoms.get(0).resNumber);
+      char strchar = sequence.getCharAt(pdboffset++);
+      if (seqpos == StructureMapping.UNASSIGNED_VALUE)
+      {
+        continue;
+      }
+      char seqchar = ds.getCharAt(seqpos - ds.getStart());
+
+      boolean sameResidue = Comparison.isSameResidue(
+              seqchar, strchar, false);
+      if (sameResidue)
+      {
+        for (Atom atom : res.atoms)
+        {
+          atom.alignmentMapping = seqpos - 1;
+        }
+      }
+    }
+  }
+
+  /**
    * Copies over the RESNUM seqfeatures from the internal chain sequence to the
    * mapped sequence
    * 
@@ -550,6 +594,12 @@ public class PDBChain
   {
     SequenceI sq = mapping.getSequence();
     SequenceI dsq = sq;
+    if (sqmpping == null)
+    {
+      // SIFTS mappings are recorded in the StructureMapping object...
+
+      sqmpping = mapping.getSeqToPdbMapping();
+    }
     if (sq != null)
     {
       while (dsq.getDatasetSequence() != null)
index 90d9197..343ebc7 100644 (file)
@@ -117,7 +117,7 @@ public class AlignmentUtils
    */
   public static AlignmentI expandContext(AlignmentI core, int flankSize)
   {
-    List<SequenceI> sq = new ArrayList<SequenceI>();
+    List<SequenceI> sq = new ArrayList<>();
     int maxoffset = 0;
     for (SequenceI s : core.getSequences())
     {
@@ -247,7 +247,7 @@ public class AlignmentUtils
   public static Map<String, List<SequenceI>> getSequencesByName(
           AlignmentI al)
   {
-    Map<String, List<SequenceI>> theMap = new LinkedHashMap<String, List<SequenceI>>();
+    Map<String, List<SequenceI>> theMap = new LinkedHashMap<>();
     for (SequenceI seq : al.getSequences())
     {
       String name = seq.getName();
@@ -256,7 +256,7 @@ public class AlignmentUtils
         List<SequenceI> seqs = theMap.get(name);
         if (seqs == null)
         {
-          seqs = new ArrayList<SequenceI>();
+          seqs = new ArrayList<>();
           theMap.put(name, seqs);
         }
         seqs.add(seq);
@@ -283,8 +283,8 @@ public class AlignmentUtils
       return false;
     }
 
-    Set<SequenceI> mappedDna = new HashSet<SequenceI>();
-    Set<SequenceI> mappedProtein = new HashSet<SequenceI>();
+    Set<SequenceI> mappedDna = new HashSet<>();
+    Set<SequenceI> mappedProtein = new HashSet<>();
 
     /*
      * First pass - map sequences where cross-references exist. This include
@@ -870,7 +870,7 @@ public class AlignmentUtils
       System.err.println("Wrong alignment type in alignProteinAsDna");
       return 0;
     }
-    List<SequenceI> unmappedProtein = new ArrayList<SequenceI>();
+    List<SequenceI> unmappedProtein = new ArrayList<>();
     Map<AlignedCodon, Map<SequenceI, AlignedCodon>> alignedCodons = buildCodonColumnsMap(
             protein, dna, unmappedProtein);
     return alignProteinAs(protein, alignedCodons, unmappedProtein);
@@ -1081,7 +1081,7 @@ public class AlignmentUtils
      * {dnaSequence, {proteinSequence, codonProduct}} at that position. The
      * comparator keeps the codon positions ordered.
      */
-    Map<AlignedCodon, Map<SequenceI, AlignedCodon>> alignedCodons = new TreeMap<AlignedCodon, Map<SequenceI, AlignedCodon>>(
+    Map<AlignedCodon, Map<SequenceI, AlignedCodon>> alignedCodons = new TreeMap<>(
             new CodonComparator());
 
     for (SequenceI dnaSeq : dna.getSequences())
@@ -1127,9 +1127,9 @@ public class AlignmentUtils
     // TODO delete this ugly hack once JAL-2022 is resolved
     // i.e. we can model startPhase > 0 (incomplete start codon)
 
-    List<SequenceI> sequencesChecked = new ArrayList<SequenceI>();
+    List<SequenceI> sequencesChecked = new ArrayList<>();
     AlignedCodon lastCodon = null;
-    Map<SequenceI, AlignedCodon> toAdd = new HashMap<SequenceI, AlignedCodon>();
+    Map<SequenceI, AlignedCodon> toAdd = new HashMap<>();
 
     for (Entry<AlignedCodon, Map<SequenceI, AlignedCodon>> entry : alignedCodons
             .entrySet())
@@ -1308,7 +1308,7 @@ public class AlignmentUtils
     Map<SequenceI, AlignedCodon> seqProduct = alignedCodons.get(codon);
     if (seqProduct == null)
     {
-      seqProduct = new HashMap<SequenceI, AlignedCodon>();
+      seqProduct = new HashMap<>();
       alignedCodons.put(codon, seqProduct);
     }
     seqProduct.put(protein, codon);
@@ -1445,7 +1445,7 @@ public class AlignmentUtils
       {
         continue;
       }
-      final List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+      final List<AlignmentAnnotation> result = new ArrayList<>();
       for (AlignmentAnnotation dsann : datasetAnnotations)
       {
         /*
@@ -1627,13 +1627,13 @@ public class AlignmentUtils
       throw new IllegalArgumentException(
               "IMPLEMENTATION ERROR: dataset.getDataset() must be null!");
     }
-    List<SequenceI> foundSeqs = new ArrayList<SequenceI>();
-    List<SequenceI> cdsSeqs = new ArrayList<SequenceI>();
+    List<SequenceI> foundSeqs = new ArrayList<>();
+    List<SequenceI> cdsSeqs = new ArrayList<>();
     List<AlignedCodonFrame> mappings = dataset.getCodonFrames();
     HashSet<SequenceI> productSeqs = null;
     if (products != null)
     {
-      productSeqs = new HashSet<SequenceI>();
+      productSeqs = new HashSet<>();
       for (SequenceI seq : products)
       {
         productSeqs.add(seq.getDatasetSequence() == null ? seq
@@ -1833,7 +1833,7 @@ public class AlignmentUtils
    * @param seqMappings
    *          the set of mappings involving dnaSeq
    * @param aMapping
-   *          an initial candidate from seqMappings
+   *          a transcript-to-peptide mapping
    * @return
    */
   static SequenceI findCdsForProtein(List<AlignedCodonFrame> mappings,
@@ -1858,7 +1858,15 @@ public class AlignmentUtils
     if (mappedFromLength == dnaLength
             || mappedFromLength == dnaLength - CODON_LENGTH)
     {
-      return seqDss;
+      /*
+       * if sequence has CDS features, this is a transcript with no UTR
+       * - do not take this as the CDS sequence! (JAL-2789)
+       */
+      if (seqDss.getFeatures().getFeaturesByOntology(SequenceOntologyI.CDS)
+              .isEmpty())
+      {
+        return seqDss;
+      }
     }
 
     /*
@@ -1883,10 +1891,12 @@ public class AlignmentUtils
           {
             /*
             * found a 3:1 mapping to the protein product which covers
-            * the whole dna sequence i.e. is from CDS; finally check it
-            * is from the dna start sequence
+            * the whole dna sequence i.e. is from CDS; finally check the CDS
+            * is mapped from the given dna start sequence
             */
             SequenceI cdsSeq = map.getFromSeq();
+            // todo this test is weak if seqMappings contains multiple mappings;
+            // we get away with it if transcript:cds relationship is 1:1
             List<AlignedCodonFrame> dnaToCdsMaps = MappingUtils
                     .findMappingsForSequence(cdsSeq, seqMappings);
             if (!dnaToCdsMaps.isEmpty())
@@ -2002,8 +2012,8 @@ public class AlignmentUtils
   {
 
     // gather direct refs from contig congrent with mapping
-    List<DBRefEntry> direct = new ArrayList<DBRefEntry>();
-    HashSet<String> directSources = new HashSet<String>();
+    List<DBRefEntry> direct = new ArrayList<>();
+    HashSet<String> directSources = new HashSet<>();
     if (contig.getDBRefs() != null)
     {
       for (DBRefEntry dbr : contig.getDBRefs())
@@ -2023,7 +2033,7 @@ public class AlignmentUtils
     DBRefEntry[] onSource = DBRefUtils.selectRefs(
             proteinProduct.getDBRefs(),
             directSources.toArray(new String[0]));
-    List<DBRefEntry> propagated = new ArrayList<DBRefEntry>();
+    List<DBRefEntry> propagated = new ArrayList<>();
 
     // and generate appropriate mappings
     for (DBRefEntry cdsref : direct)
@@ -2180,12 +2190,13 @@ public class AlignmentUtils
     int mappedDnaLength = MappingUtils.getLength(ranges);
 
     /*
-     * if not a whole number of codons, something is wrong,
-     * abort mapping
+     * if not a whole number of codons, truncate mapping
      */
-    if (mappedDnaLength % CODON_LENGTH > 0)
+    int codonRemainder = mappedDnaLength % CODON_LENGTH;
+    if (codonRemainder > 0)
     {
-      return null;
+      mappedDnaLength -= codonRemainder;
+      MappingUtils.removeEndPositions(codonRemainder, ranges);
     }
 
     int proteinLength = proteinSeq.getLength();
@@ -2202,7 +2213,7 @@ public class AlignmentUtils
       proteinStart++;
       proteinLength--;
     }
-    List<int[]> proteinRange = new ArrayList<int[]>();
+    List<int[]> proteinRange = new ArrayList<>();
 
     /*
      * dna length should map to protein (or protein plus stop codon)
@@ -2237,7 +2248,7 @@ public class AlignmentUtils
    */
   public static List<int[]> findCdsPositions(SequenceI dnaSeq)
   {
-    List<int[]> result = new ArrayList<int[]>();
+    List<int[]> result = new ArrayList<>();
 
     List<SequenceFeature> sfs = dnaSeq.getFeatures().getFeaturesByOntology(
             SequenceOntologyI.CDS);
@@ -2523,7 +2534,7 @@ public class AlignmentUtils
      * map from peptide position to all variants of the codon which codes for it
      * LinkedHashMap ensures we keep the peptide features in sequence order
      */
-    LinkedHashMap<Integer, List<DnaVariant>[]> variants = new LinkedHashMap<Integer, List<DnaVariant>[]>();
+    LinkedHashMap<Integer, List<DnaVariant>[]> variants = new LinkedHashMap<>();
 
     List<SequenceFeature> dnaFeatures = dnaSeq.getFeatures()
             .getFeaturesByOntology(SequenceOntologyI.SEQUENCE_VARIANT);
@@ -2558,9 +2569,9 @@ public class AlignmentUtils
       if (codonVariants == null)
       {
         codonVariants = new ArrayList[CODON_LENGTH];
-        codonVariants[0] = new ArrayList<DnaVariant>();
-        codonVariants[1] = new ArrayList<DnaVariant>();
-        codonVariants[2] = new ArrayList<DnaVariant>();
+        codonVariants[0] = new ArrayList<>();
+        codonVariants[1] = new ArrayList<>();
+        codonVariants[2] = new ArrayList<>();
         variants.put(peptidePosition, codonVariants);
       }
 
@@ -2699,7 +2710,7 @@ public class AlignmentUtils
     /*
      * fancy case - aligning via mappings between sequences
      */
-    List<SequenceI> unmapped = new ArrayList<SequenceI>();
+    List<SequenceI> unmapped = new ArrayList<>();
     Map<Integer, Map<SequenceI, Character>> columnMap = buildMappedColumnsMap(
             unaligned, aligned, unmapped);
     int width = columnMap.size();
@@ -2774,7 +2785,7 @@ public class AlignmentUtils
     }
 
     // map from dataset sequence to alignment sequence(s)
-    Map<SequenceI, List<SequenceI>> alignedDatasets = new HashMap<SequenceI, List<SequenceI>>();
+    Map<SequenceI, List<SequenceI>> alignedDatasets = new HashMap<>();
     for (SequenceI seq : aligned.getSequences())
     {
       SequenceI ds = seq.getDatasetSequence();
@@ -2837,7 +2848,7 @@ public class AlignmentUtils
      * {unalignedSequence, characterPerSequence} at that position.
      * TreeMap keeps the entries in ascending column order. 
      */
-    SortedMap<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
+    SortedMap<Integer, Map<SequenceI, Character>> map = new TreeMap<>();
 
     /*
      * record any sequences that have no mapping so can't be realigned
@@ -2942,7 +2953,7 @@ public class AlignmentUtils
             Map<SequenceI, Character> seqsMap = map.get(fromCol);
             if (seqsMap == null)
             {
-              seqsMap = new HashMap<SequenceI, Character>();
+              seqsMap = new HashMap<>();
               map.put(fromCol, seqsMap);
             }
             seqsMap.put(seq, seq.getCharAt(mappedCharPos - toStart));
index fd66388..b4612cf 100644 (file)
@@ -62,4 +62,11 @@ public interface JalviewStructureDisplayI
    */
   void setJalviewColourScheme(ColourSchemeI colourScheme);
 
+  /**
+   * 
+   * @return true if all background sequence/structure binding threads have
+   *         completed for this viewer instance
+   */
+  boolean hasMapping();
+
 }
index 6e3257d..bbcb3b8 100755 (executable)
@@ -32,6 +32,7 @@ import jalview.util.ParseHtmlBodyAndLinks;
 import java.awt.Checkbox;
 import java.awt.CheckboxMenuItem;
 import java.awt.Color;
+import java.awt.Cursor;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.FontMetrics;
@@ -57,6 +58,16 @@ public class AnnotationLabels extends Panel
 {
   Image image;
 
+  /**
+   * width in pixels within which height adjuster arrows are shown and active
+   */
+  private static final int HEIGHT_ADJUSTER_WIDTH = 50;
+
+  /**
+   * height in pixels for allowing height adjuster to be active
+   */
+  private static int HEIGHT_ADJUSTER_HEIGHT = 10;
+
   boolean active = false;
 
   AlignmentPanel ap;
@@ -92,23 +103,6 @@ public class AnnotationLabels extends Panel
     this.ap = ap;
     this.av = ap.av;
     setLayout(null);
-
-    /**
-     * this retrieves the adjustable height glyph from resources. we don't use
-     * it at the moment. java.net.URL url =
-     * getClass().getResource("/images/idwidth.gif"); Image temp = null;
-     * 
-     * if (url != null) { temp =
-     * java.awt.Toolkit.getDefaultToolkit().createImage(url); }
-     * 
-     * try { MediaTracker mt = new MediaTracker(this); mt.addImage(temp, 0);
-     * mt.waitForID(0); } catch (Exception ex) { }
-     * 
-     * BufferedImage bi = new BufferedImage(temp.getHeight(this),
-     * temp.getWidth(this), BufferedImage.TYPE_INT_RGB); Graphics2D g =
-     * (Graphics2D) bi.getGraphics(); g.rotate(Math.toRadians(90));
-     * g.drawImage(temp, 0, -bi.getWidth(this), this); image = (Image) bi;
-     */
     addMouseListener(this);
     addMouseMotionListener(this);
   }
@@ -268,7 +262,10 @@ public class AnnotationLabels extends Panel
   @Override
   public void mouseMoved(MouseEvent evt)
   {
-    resizePanel = evt.getY() < 10 && evt.getX() < 14;
+    resizePanel = evt.getY() < HEIGHT_ADJUSTER_HEIGHT
+            && evt.getX() < HEIGHT_ADJUSTER_WIDTH;
+    setCursor(Cursor.getPredefinedCursor(
+            resizePanel ? Cursor.S_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR));
     int row = getSelectedRow(evt.getY() + scrollOffset);
 
     if (row > -1)
@@ -406,6 +403,7 @@ public class AnnotationLabels extends Panel
     resizePanel = false;
     dragEvent = null;
     dragCancelled = false;
+    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
     repaint();
     ap.annotationPanel.repaint();
   }
@@ -418,6 +416,8 @@ public class AnnotationLabels extends Panel
       resizePanel = true;
       repaint();
     }
+    setCursor(Cursor.getPredefinedCursor(
+            resizePanel ? Cursor.S_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR));
   }
 
   @Override
@@ -903,14 +903,8 @@ public class AnnotationLabels extends Panel
       }
     }
     g.translate(0, +scrollOffset);
-    if (resizePanel)
-    {
-      g.setColor(Color.red);
-      g.setPaintMode();
-      g.drawLine(2, 8, 5, 2);
-      g.drawLine(5, 2, 8, 8);
-    }
-    else if (!dragCancelled && dragEvent != null && aa != null)
+
+    if (!resizePanel && !dragCancelled && dragEvent != null && aa != null)
     {
       g.setColor(Color.lightGray);
       g.drawString(aa[selectedRow].label, dragEvent.getX(),
index 75e3243..2602268 100755 (executable)
@@ -21,9 +21,8 @@
 package jalview.appletgui;
 
 import java.awt.Color;
+import java.awt.Cursor;
 import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Image;
 import java.awt.Panel;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
@@ -36,29 +35,24 @@ public class IdwidthAdjuster extends Panel
 
   int oldX = 0;
 
-  Image image;
-
   AlignmentPanel ap;
 
   public IdwidthAdjuster(AlignmentPanel ap)
   {
     setLayout(null);
     this.ap = ap;
-    java.net.URL url = getClass().getResource("/images/idwidth.gif");
-    if (url != null)
-    {
-      image = java.awt.Toolkit.getDefaultToolkit().getImage(url);
-    }
-
+    setBackground(Color.WHITE);
     addMouseListener(this);
     addMouseMotionListener(this);
   }
 
+  @Override
   public void mousePressed(MouseEvent evt)
   {
     oldX = evt.getX();
   }
 
+  @Override
   public void mouseReleased(MouseEvent evt)
   {
     active = false;
@@ -85,18 +79,24 @@ public class IdwidthAdjuster extends Panel
     // }
   }
 
+  @Override
   public void mouseEntered(MouseEvent evt)
   {
     active = true;
+    setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
+
     repaint();
   }
 
+  @Override
   public void mouseExited(MouseEvent evt)
   {
     active = false;
+    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
     repaint();
   }
 
+  @Override
   public void mouseDragged(MouseEvent evt)
   {
     active = true;
@@ -112,25 +112,13 @@ public class IdwidthAdjuster extends Panel
     }
   }
 
+  @Override
   public void mouseMoved(MouseEvent evt)
   {
   }
 
+  @Override
   public void mouseClicked(MouseEvent evt)
   {
   }
-
-  public void paint(Graphics g)
-  {
-    g.setColor(Color.white);
-    g.fillRect(0, 0, getSize().width, getSize().height);
-    if (active)
-    {
-      if (image != null)
-      {
-        g.drawImage(image, getSize().width - 20, 2, this);
-      }
-    }
-  }
-
 }
index 8ce597d..3bbbe95 100755 (executable)
@@ -155,6 +155,10 @@ public class OverviewPanel extends Panel implements Runnable,
       if (!od.isPositionInBox(evt.getX(), evt.getY()))
       { 
        draggingBox = false;
+
+        // display drag cursor at mouse position
+        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+
         od.updateViewportFromMouse(evt.getX(), evt.getY(),
                 av.getAlignment().getHiddenSequences(),
                 av.getAlignment().getHiddenColumns());
@@ -172,6 +176,7 @@ public class OverviewPanel extends Panel implements Runnable,
   @Override
   public void mouseReleased(MouseEvent evt)
   {
+    draggingBox = false;
   }
 
   @Override
index dc50843..dcd6546 100755 (executable)
@@ -281,7 +281,7 @@ public class Cache
     @Override
     public synchronized Enumeration<Object> keys()
     {
-      return Collections.enumeration(new TreeSet<Object>(super.keySet()));
+      return Collections.enumeration(new TreeSet<>(super.keySet()));
     }
   };
 
@@ -334,7 +334,10 @@ public class Cache
     }
   }
 
-  /** Called when Jalview is started */
+  /**
+   * Loads properties from the given properties file. Any existing properties
+   * are first cleared.
+   */
   public static void loadProperties(String propsFile)
   {
     propertiesFile = propsFile;
@@ -369,6 +372,7 @@ public class Cache
       {
         fis = new FileInputStream(propertiesFile);
       }
+      applicationProperties.clear();
       applicationProperties.load(fis);
 
       // remove any old build properties
@@ -621,14 +625,14 @@ public class Cache
    * @param obj
    *          String value of property
    * 
-   * @return String value of property
+   * @return previous value of property (or null)
    */
-  public static String setProperty(String key, String obj)
+  public static Object setProperty(String key, String obj)
   {
-
+    Object oldValue = null;
     try
     {
-      applicationProperties.setProperty(key, obj);
+      oldValue = applicationProperties.setProperty(key, obj);
       if (!propsAreReadOnly)
       {
         FileOutputStream out = new FileOutputStream(propertiesFile);
@@ -640,7 +644,7 @@ public class Cache
       System.out.println(
               "Error setting property: " + key + " " + obj + "\n" + ex);
     }
-    return obj;
+    return oldValue;
   }
 
   /**
index 9475f00..3ba35b6 100755 (executable)
@@ -51,7 +51,7 @@ public class Alignment implements AlignmentI
 {
   private Alignment dataset;
 
-  protected List<SequenceI> sequences;
+  private List<SequenceI> sequences;
 
   protected List<SequenceGroup> groups;
 
@@ -200,6 +200,7 @@ public class Alignment implements AlignmentI
         return sequences.get(i);
       }
     }
+
     return null;
   }
 
@@ -708,7 +709,7 @@ public class Alignment implements AlignmentI
   public int getWidth()
   {
     int maxLength = -1;
-
+  
     for (int i = 0; i < sequences.size(); i++)
     {
       if (getSequenceAt(i).getLength() > maxLength)
@@ -716,9 +717,34 @@ public class Alignment implements AlignmentI
         maxLength = getSequenceAt(i).getLength();
       }
     }
-
+  
     return maxLength;
   }
+  /*
+  @Override
+  public int getWidth()
+  {
+    final Wrapper temp = new Wrapper();
+  
+    forEachSequence(new Consumer<SequenceI>()
+    {
+      @Override
+      public void accept(SequenceI s)
+      {
+        if (s.getLength() > temp.inner)
+        {
+          temp.inner = s.getLength();
+        }
+      }
+    }, 0, sequences.size() - 1);
+  
+    return temp.inner;
+  }
+  
+  public static class Wrapper
+  {
+    public int inner;
+  }*/
 
   /**
    * DOCUMENT ME!
@@ -1605,7 +1631,10 @@ public class Alignment implements AlignmentI
     AlignmentAnnotation annot = new AlignmentAnnotation(name, name,
             new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH);
     annot.hasText = false;
-    annot.setCalcId(new String(calcId));
+    if (calcId != null)
+    {
+      annot.setCalcId(new String(calcId));
+    }
     annot.autoCalculated = autoCalc;
     if (seqRef != null)
     {
index bbd1f26..6dd69a8 100644 (file)
@@ -20,6 +20,8 @@
  */
 package jalview.ext.ensembl;
 
+import jalview.bin.Cache;
+
 /**
  * A class to behave much like EnsemblGene but referencing the ensemblgenomes
  * domain and data
@@ -35,7 +37,9 @@ public class EnsemblGenomes extends EnsemblGene
    */
   public EnsemblGenomes()
   {
-    super(ENSEMBL_GENOMES_REST);
+    super();
+    setDomain(Cache.getDefault(ENSEMBL_GENOMES_BASEURL,
+            DEFAULT_ENSEMBL_GENOMES_BASEURL));
   }
 
   @Override
index 92763a1..0ddef2b 100644 (file)
@@ -41,6 +41,19 @@ import org.json.simple.parser.ParseException;
  */
 public class EnsemblLookup extends EnsemblRestClient
 {
+
+  private static final String OBJECT_TYPE_TRANSLATION = "Translation";
+  private static final String PARENT = "Parent";
+  private static final String OBJECT_TYPE_TRANSCRIPT = "Transcript";
+  private static final String ID = "id";
+  private static final String OBJECT_TYPE_GENE = "Gene";
+  private static final String OBJECT_TYPE = "object_type";
+
+  /**
+   * keep track of last identifier retrieved to break loops
+   */
+  private String lastId;
+
   /**
    * Default constructor (to use rest.ensembl.org)
    */
@@ -150,7 +163,18 @@ public class EnsemblLookup extends EnsemblRestClient
     BufferedReader br = null;
     try
     {
+
       URL url = getUrl(identifier, objectType);
+
+      if (identifier.equals(lastId))
+      {
+        System.err.println("** Ensembl lookup " + url.toString()
+                + " looping on Parent!");
+        return null;
+      }
+
+      lastId = identifier;
+
       if (url != null)
       {
         br = getHttpResponse(url, ids);
index b1bc8e5..b19f557 100644 (file)
@@ -72,10 +72,7 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
 
   private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log";
 
-  private static Map<String, EnsemblInfo> domainData;
-
-  // @see https://github.com/Ensembl/ensembl-rest/wiki/Output-formats
-  private static final String PING_URL = "http://rest.ensembl.org/info/ping.json";
+  private static Map<String, EnsemblInfo> domainData = new HashMap<>();
 
   private final static long AVAILABILITY_RETEST_INTERVAL = 10000L; // 10 seconds
 
@@ -85,11 +82,11 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
 
   static
   {
-    domainData = new HashMap<>();
-    domainData.put(ENSEMBL_REST,
-            new EnsemblInfo(ENSEMBL_REST, LATEST_ENSEMBL_REST_VERSION));
-    domainData.put(ENSEMBL_GENOMES_REST, new EnsemblInfo(
-            ENSEMBL_GENOMES_REST, LATEST_ENSEMBLGENOMES_REST_VERSION));
+    domainData.put(DEFAULT_ENSEMBL_BASEURL,
+            new EnsemblInfo(DEFAULT_ENSEMBL_BASEURL, LATEST_ENSEMBL_REST_VERSION));
+    domainData.put(DEFAULT_ENSEMBL_GENOMES_BASEURL,
+            new EnsemblInfo(
+            DEFAULT_ENSEMBL_GENOMES_BASEURL, LATEST_ENSEMBLGENOMES_REST_VERSION));
   }
 
   protected volatile boolean inProgress = false;
@@ -99,7 +96,21 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
    */
   public EnsemblRestClient()
   {
-    this(ENSEMBL_REST);
+    super();
+
+    /*
+     * initialise domain info lazily
+     */
+    if (!domainData.containsKey(ensemblDomain))
+    {
+      domainData.put(ensemblDomain,
+              new EnsemblInfo(ensemblDomain, LATEST_ENSEMBL_REST_VERSION));
+    }
+    if (!domainData.containsKey(ensemblGenomesDomain))
+    {
+      domainData.put(ensemblGenomesDomain, new EnsemblInfo(
+              ensemblGenomesDomain, LATEST_ENSEMBLGENOMES_REST_VERSION));
+    }
   }
 
   /**
@@ -169,11 +180,12 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
   boolean checkEnsembl()
   {
     BufferedReader br = null;
+    String pingUrl = getDomain() + "/info/ping" + CONTENT_TYPE_JSON;
     try
     {
       // note this format works for both ensembl and ensemblgenomes
       // info/ping.json works for ensembl only (March 2016)
-      URL ping = new URL(getDomain() + "/info/ping" + CONTENT_TYPE_JSON);
+      URL ping = new URL(pingUrl);
 
       /*
        * expect {"ping":1} if ok
@@ -192,7 +204,7 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher
     } catch (Throwable t)
     {
       System.err.println(
-              "Error connecting to " + PING_URL + ": " + t.getMessage());
+              "Error connecting to " + pingUrl + ": " + t.getMessage());
     } finally
     {
       if (br != null)
index c4abb20..0aaaf93 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.ext.ensembl;
 
+import jalview.bin.Cache;
 import jalview.datamodel.DBRefSource;
 import jalview.ws.seqfetcher.DbSourceProxyImpl;
 
@@ -32,6 +33,16 @@ import com.stevesoft.pat.Regex;
  */
 abstract class EnsemblSequenceFetcher extends DbSourceProxyImpl
 {
+  // domain properties lookup keys:
+  protected static final String ENSEMBL_BASEURL = "ENSEMBL_BASEURL";
+
+  protected static final String ENSEMBL_GENOMES_BASEURL = "ENSEMBL_GENOMES_BASEURL";
+
+  // domain properties default values:
+  protected static final String DEFAULT_ENSEMBL_BASEURL = "https://rest.ensembl.org";
+
+  protected static final String DEFAULT_ENSEMBL_GENOMES_BASEURL = "https://rest.ensemblgenomes.org";
+
   /*
    * accepts ENSG/T/E/P with 11 digits
    * or ENSMUSP or similar for other species
@@ -41,9 +52,9 @@ abstract class EnsemblSequenceFetcher extends DbSourceProxyImpl
           "(ENS([A-Z]{3}|)[GTEP]{1}[0-9]{11}$)" + "|"
                   + "(CCDS[0-9.]{3,}$)");
 
-  protected static final String ENSEMBL_GENOMES_REST = "http://rest.ensemblgenomes.org";
+  protected final String ensemblGenomesDomain;
 
-  protected static final String ENSEMBL_REST = "http://rest.ensembl.org";
+  protected final String ensemblDomain;
 
   protected static final String OBJECT_TYPE_TRANSLATION = "Translation";
 
@@ -68,13 +79,29 @@ abstract class EnsemblSequenceFetcher extends DbSourceProxyImpl
     constrained, regulatory
   }
 
-  private String domain = ENSEMBL_REST;
+  private String domain;
+
+  /**
+   * Constructor
+   */
+  public EnsemblSequenceFetcher()
+  {
+    /*
+     * the default domain names may be overridden in .jalview_properties;
+     * this allows an easy change from http to https in future if needed
+     */
+    ensemblDomain = Cache.getDefault(ENSEMBL_BASEURL,
+            DEFAULT_ENSEMBL_BASEURL);
+    ensemblGenomesDomain = Cache.getDefault(ENSEMBL_GENOMES_BASEURL,
+            DEFAULT_ENSEMBL_GENOMES_BASEURL);
+    domain = ensemblDomain;
+  }
 
   @Override
   public String getDbSource()
   {
     // NB ensure Uniprot xrefs are canonicalised from "Ensembl" to "ENSEMBL"
-    if (ENSEMBL_GENOMES_REST.equals(getDomain()))
+    if (ensemblGenomesDomain.equals(getDomain()))
     {
       return DBRefSource.ENSEMBLGENOMES;
     }
index 6bf7010..8fb0de6 100644 (file)
@@ -77,7 +77,6 @@ public class JmolCommands
         continue;
       }
 
-      int lastPos = -1;
       for (int s = 0; s < sequence[pdbfnum].length; s++)
       {
         for (int sp, m = 0; m < mapping.length; m++)
@@ -85,6 +84,7 @@ public class JmolCommands
           if (mapping[m].getSequence() == sequence[pdbfnum][s]
                   && (sp = al.findIndex(sequence[pdbfnum][s])) > -1)
           {
+            int lastPos = StructureMapping.UNASSIGNED_VALUE;
             SequenceI asp = al.getSequenceAt(sp);
             for (int r = 0; r < asp.getLength(); r++)
             {
@@ -95,10 +95,22 @@ public class JmolCommands
               }
               int pos = mapping[m].getPDBResNum(asp.findPosition(r));
 
-              if (pos < 1 || pos == lastPos)
+              if (pos == lastPos)
               {
                 continue;
               }
+              if (pos == StructureMapping.UNASSIGNED_VALUE)
+              {
+                // terminate current colour op
+                if (command.length() > 0
+                        && command.charAt(command.length() - 1) != ';')
+                {
+                  command.append(";");
+                }
+                // reset lastPos
+                lastPos = StructureMapping.UNASSIGNED_VALUE;
+                continue;
+              }
 
               lastPos = pos;
 
@@ -128,7 +140,12 @@ public class JmolCommands
               // TODO: deal with case when buffer is too large for Jmol to parse
               // - execute command and flush
 
-              command.append(";");
+              if (command.length() > 0
+                      && command.charAt(command.length() - 1) != ';')
+              {
+                command.append(";");
+              }
+
               if (command.length() > 51200)
               {
                 // add another chunk
index 250fba0..262ed86 100644 (file)
@@ -21,6 +21,7 @@
 
 package jalview.fts.service.uniprot;
 
+import jalview.bin.Cache;
 import jalview.fts.api.FTSData;
 import jalview.fts.api.FTSDataColumnI;
 import jalview.fts.api.FTSRestClientI;
@@ -44,9 +45,18 @@ import com.sun.jersey.api.client.config.DefaultClientConfig;
 
 public class UniProtFTSRestClient extends FTSRestClient
 {
+  private static final String DEFAULT_UNIPROT_DOMAIN = "https://www.uniprot.org";
+
   private static FTSRestClientI instance = null;
 
-  public static final String UNIPROT_SEARCH_ENDPOINT = "http://www.uniprot.org/uniprot/?";
+  public final String uniprotSearchEndpoint;
+
+  public UniProtFTSRestClient()
+  {
+    super();
+    uniprotSearchEndpoint = Cache.getDefault("UNIPROT_DOMAIN",
+            DEFAULT_UNIPROT_DOMAIN) + "/uniprot/?";
+  }
 
   @Override
   public FTSRestResponse executeRequest(FTSRestRequest uniportRestRequest)
@@ -81,7 +91,7 @@ public class UniProtFTSRestClient extends FTSRestClient
       }
 
       WebResource webResource = null;
-      webResource = client.resource(UNIPROT_SEARCH_ENDPOINT)
+      webResource = client.resource(uniprotSearchEndpoint)
               .queryParam("format", "tab")
               .queryParam("columns", wantedFields)
               .queryParam("limit", String.valueOf(responseSize))
@@ -158,7 +168,7 @@ public class UniProtFTSRestClient extends FTSRestClient
     String[] foundDataRow = uniProtTabDelimittedResponseString.split("\n");
     if (foundDataRow != null && foundDataRow.length > 0)
     {
-      result = new ArrayList<FTSData>();
+      result = new ArrayList<>();
       boolean firstRow = true;
       for (String dataRow : foundDataRow)
       {
index 0c452c3..9981559 100644 (file)
@@ -4849,14 +4849,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             MessageManager.getString("option.trim_retrieved_seqs"));
     trimrs.setToolTipText(
             MessageManager.getString("label.trim_retrieved_sequences"));
-    trimrs.setSelected(Cache.getDefault("TRIM_FETCHED_DATASET_SEQS", true));
+    trimrs.setSelected(
+            Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
     trimrs.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
         trimrs.setSelected(trimrs.isSelected());
-        Cache.setProperty("TRIM_FETCHED_DATASET_SEQS",
+        Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
                 Boolean.valueOf(trimrs.isSelected()).toString());
       };
     });
index 60ca80a..f5634d2 100644 (file)
@@ -874,15 +874,17 @@ public class AlignmentPanel extends GAlignmentPanel implements
   @Override
   public void paintComponent(Graphics g)
   {
-    invalidate();
+    invalidate(); // needed so that the id width adjuster works correctly
 
     Dimension d = getIdPanel().getIdCanvas().getPreferredSize();
     idPanelHolder.setPreferredSize(d);
     hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
-    validate();
+
+    validate(); // needed so that the id width adjuster works correctly
 
     /*
-     * set scroll bar positions
+     * set scroll bar positions - tried to remove but necessary for split panel to resize correctly
+     * though I still think this call should be elsewhere.
      */
     ViewportRanges ranges = av.getRanges();
     setScrollValues(ranges.getStartRes(), ranges.getStartSeq());
@@ -1813,35 +1815,6 @@ public class AlignmentPanel extends GAlignmentPanel implements
    */
   protected void scrollToCentre(SearchResultsI sr, int verticalOffset)
   {
-    /*
-     * To avoid jumpy vertical scrolling (if some sequences are gapped or not
-     * mapped), we can make the scroll-to location a sequence above the one
-     * actually mapped.
-     */
-    SequenceI mappedTo = sr.getResults().get(0).getSequence();
-    List<SequenceI> seqs = av.getAlignment().getSequences();
-
-    /*
-     * This is like AlignmentI.findIndex(seq) but here we are matching the
-     * dataset sequence not the aligned sequence
-     */
-    boolean matched = false;
-    for (SequenceI seq : seqs)
-    {
-      if (mappedTo == seq.getDatasetSequence())
-      {
-        matched = true;
-        break;
-      }
-    }
-    if (!matched)
-    {
-      return; // failsafe, shouldn't happen
-    }
-
-    /*
-     * Scroll to position but centring the target residue.
-     */
     scrollToPosition(sr, verticalOffset, true, true);
   }
 
index c883071..b58269d 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import jalview.analysis.AlignSeq;
 import jalview.analysis.AlignmentUtils;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
@@ -30,16 +31,17 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.FileFormat;
 import jalview.io.FormatAdapter;
+import jalview.util.Comparison;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
 import java.awt.Color;
+import java.awt.Cursor;
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.MediaTracker;
 import java.awt.RenderingHints;
 import java.awt.Toolkit;
 import java.awt.datatransfer.StringSelection;
@@ -50,6 +52,7 @@ import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
@@ -63,63 +66,74 @@ import javax.swing.SwingUtilities;
 import javax.swing.ToolTipManager;
 
 /**
- * DOCUMENT ME!
- * 
- * @author $author$
- * @version $Revision$
+ * The panel that holds the labels for alignment annotations, providing
+ * tooltips, context menus, drag to reorder rows, and drag to adjust panel
+ * height
  */
 public class AnnotationLabels extends JPanel
         implements MouseListener, MouseMotionListener, ActionListener
 {
+  /**
+   * width in pixels within which height adjuster arrows are shown and active
+   */
+  private static final int HEIGHT_ADJUSTER_WIDTH = 50;
+
+  /**
+   * height in pixels for allowing height adjuster to be active
+   */
+  private static int HEIGHT_ADJUSTER_HEIGHT = 10;
+
   private static final Pattern LEFT_ANGLE_BRACKET_PATTERN = Pattern
           .compile("<");
 
-  String TOGGLE_LABELSCALE = MessageManager
+  private static final Font font = new Font("Arial", Font.PLAIN, 11);
+
+  private static final String TOGGLE_LABELSCALE = MessageManager
           .getString("label.scale_label_to_column");
 
-  String ADDNEW = MessageManager.getString("label.add_new_row");
+  private static final String ADDNEW = MessageManager
+          .getString("label.add_new_row");
 
-  String EDITNAME = MessageManager
+  private static final String EDITNAME = MessageManager
           .getString("label.edit_label_description");
 
-  String HIDE = MessageManager.getString("label.hide_row");
+  private static final String HIDE = MessageManager
+          .getString("label.hide_row");
 
-  String DELETE = MessageManager.getString("label.delete_row");
+  private static final String DELETE = MessageManager
+          .getString("label.delete_row");
 
-  String SHOWALL = MessageManager.getString("label.show_all_hidden_rows");
+  private static final String SHOWALL = MessageManager
+          .getString("label.show_all_hidden_rows");
 
-  String OUTPUT_TEXT = MessageManager.getString("label.export_annotation");
+  private static final String OUTPUT_TEXT = MessageManager
+          .getString("label.export_annotation");
 
-  String COPYCONS_SEQ = MessageManager
+  private static final String COPYCONS_SEQ = MessageManager
           .getString("label.copy_consensus_sequence");
 
-  boolean resizePanel = false;
-
-  Image image;
+  private final boolean debugRedraw = false;
 
-  AlignmentPanel ap;
+  private AlignmentPanel ap;
 
   AlignViewport av;
 
-  boolean resizing = false;
-
-  MouseEvent dragEvent;
+  private MouseEvent dragEvent;
 
-  int oldY;
+  private int oldY;
 
-  int selectedRow;
+  private int selectedRow;
 
   private int scrollOffset = 0;
 
-  Font font = new Font("Arial", Font.PLAIN, 11);
-
   private boolean hasHiddenRows;
 
+  private boolean resizePanel = false;
+
   /**
-   * Creates a new AnnotationLabels object.
+   * Creates a new AnnotationLabels object
    * 
    * @param ap
-   *          DOCUMENT ME!
    */
   public AnnotationLabels(AlignmentPanel ap)
   {
@@ -127,30 +141,6 @@ public class AnnotationLabels extends JPanel
     av = ap.av;
     ToolTipManager.sharedInstance().registerComponent(this);
 
-    java.net.URL url = getClass().getResource("/images/idwidth.gif");
-    Image temp = null;
-
-    if (url != null)
-    {
-      temp = java.awt.Toolkit.getDefaultToolkit().createImage(url);
-    }
-
-    try
-    {
-      MediaTracker mt = new MediaTracker(this);
-      mt.addImage(temp, 0);
-      mt.waitForID(0);
-    } catch (Exception ex)
-    {
-    }
-
-    BufferedImage bi = new BufferedImage(temp.getHeight(this),
-            temp.getWidth(this), BufferedImage.TYPE_INT_RGB);
-    Graphics2D g = (Graphics2D) bi.getGraphics();
-    g.rotate(Math.toRadians(90));
-    g.drawImage(temp, 0, -bi.getWidth(this), this);
-    image = bi;
-
     addMouseListener(this);
     addMouseMotionListener(this);
     addMouseWheelListener(ap.getAnnotationPanel());
@@ -608,10 +598,9 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * Reorders annotation rows after a drag of a label
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseReleased(MouseEvent evt)
@@ -626,6 +615,9 @@ public class AnnotationLabels extends JPanel
     getSelectedRow(evt.getY() - getScrollOffset());
     int end = selectedRow;
 
+    /*
+     * if dragging to resize instead, start == end
+     */
     if (start != end)
     {
       // Swap these annotations
@@ -649,31 +641,13 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void mouseEntered(MouseEvent evt)
-  {
-    if (evt.getY() < 10)
-    {
-      resizePanel = true;
-      repaint();
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *          DOCUMENT ME!
+   * Removes the height adjuster image on leaving the panel, unless currently
+   * dragging it
    */
   @Override
   public void mouseExited(MouseEvent evt)
   {
-    if (dragEvent == null)
+    if (resizePanel && dragEvent == null)
     {
       resizePanel = false;
       repaint();
@@ -681,10 +655,11 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * A mouse drag may be either an adjustment of the panel height (if flag
+   * resizePanel is set on), or a reordering of the annotation rows. The former
+   * is dealt with by this method, the latter in mouseReleased.
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseDragged(MouseEvent evt)
@@ -718,15 +693,14 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * Updates the tooltip as the mouse moves over the labels
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseMoved(MouseEvent evt)
   {
-    resizePanel = evt.getY() < 10;
+    showOrHideAdjuster(evt);
 
     getSelectedRow(evt.getY() - getScrollOffset());
 
@@ -802,6 +776,26 @@ public class AnnotationLabels extends JPanel
     }
   }
 
+  /**
+   * Shows the height adjuster image if the mouse moves into the top left
+   * region, or hides it if the mouse leaves the regio
+   * 
+   * @param evt
+   */
+  protected void showOrHideAdjuster(MouseEvent evt)
+  {
+    boolean was = resizePanel;
+    resizePanel = evt.getY() < HEIGHT_ADJUSTER_HEIGHT && evt.getX() < HEIGHT_ADJUSTER_WIDTH;
+
+    if (resizePanel != was)
+    {
+      setCursor(Cursor.getPredefinedCursor(
+              resizePanel ? Cursor.S_RESIZE_CURSOR
+                      : Cursor.DEFAULT_CURSOR));
+      repaint();
+    }
+  }
+
   @Override
   public void mouseClicked(MouseEvent evt)
   {
@@ -821,11 +815,9 @@ public class AnnotationLabels extends JPanel
             // process modifiers
             SequenceGroup sg = ap.av.getSelectionGroup();
             if (sg == null || sg == aa[selectedRow].groupRef
-                    || !(jalview.util.Platform.isControlDown(evt)
-                            || evt.isShiftDown()))
+                    || !(Platform.isControlDown(evt) || evt.isShiftDown()))
             {
-              if (jalview.util.Platform.isControlDown(evt)
-                      || evt.isShiftDown())
+              if (Platform.isControlDown(evt) || evt.isShiftDown())
               {
                 // clone a new selection group from the associated group
                 ap.av.setSelectionGroup(
@@ -884,8 +876,7 @@ public class AnnotationLabels extends JPanel
               // we make a copy rather than edit the current selection if no
               // modifiers pressed
               // see Enhancement JAL-1557
-              if (!(jalview.util.Platform.isControlDown(evt)
-                      || evt.isShiftDown()))
+              if (!(Platform.isControlDown(evt) || evt.isShiftDown()))
               {
                 sg = new SequenceGroup(sg);
                 sg.clear();
@@ -893,7 +884,7 @@ public class AnnotationLabels extends JPanel
               }
               else
               {
-                if (jalview.util.Platform.isControlDown(evt))
+                if (Platform.isControlDown(evt))
                 {
                   sg.addOrRemove(aa[selectedRow].sequenceRef, true);
                 }
@@ -938,8 +929,8 @@ public class AnnotationLabels extends JPanel
     if (dseqs[0] == null)
     {
       dseqs[0] = new Sequence(sq);
-      dseqs[0].setSequence(jalview.analysis.AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars, sq.getSequenceAsString()));
+      dseqs[0].setSequence(AlignSeq.extractGaps(Comparison.GapChars,
+              sq.getSequenceAsString()));
 
       sq.setDatasetSequence(dseqs[0]);
     }
@@ -1022,8 +1013,6 @@ public class AnnotationLabels extends JPanel
     drawComponent(g, false, width);
   }
 
-  private final boolean debugRedraw = false;
-
   /**
    * Draw the full set of annotation Labels for the alignment at the given
    * cursor
@@ -1206,11 +1195,7 @@ public class AnnotationLabels extends JPanel
       }
     }
 
-    if (resizePanel)
-    {
-      g.drawImage(image, 2, 0 - getScrollOffset(), this);
-    }
-    else if (dragEvent != null && aa != null)
+    if (!resizePanel && dragEvent != null && aa != null)
     {
       g.setColor(Color.lightGray);
       g.drawString(aa[selectedRow].label, dragEvent.getX(),
@@ -1229,4 +1214,9 @@ public class AnnotationLabels extends JPanel
   {
     return scrollOffset;
   }
+
+  @Override
+  public void mouseEntered(MouseEvent e)
+  {
+  }
 }
index f8e8a78..71cdc9c 100755 (executable)
@@ -904,6 +904,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
   @Override
   public void paintComponent(Graphics g)
   {
+    super.paintComponent(g);
+
     g.setColor(Color.white);
     g.fillRect(0, 0, getWidth(), getHeight());
 
@@ -959,7 +961,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
       gg.fillRect(0, 0, imgWidth, image.getHeight());
       imageFresh = true;
     }
-
+    
     drawComponent(gg, av.getRanges().getStartRes(),
             av.getRanges().getEndRes() + 1);
     imageFresh = false;
@@ -992,10 +994,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     int er = av.getRanges().getEndRes() + 1;
     int transX = 0;
 
-    long stime = System.currentTimeMillis();
     gg.copyArea(0, 0, imgWidth, getHeight(),
             -horizontal * av.getCharWidth(), 0);
-    long mtime = System.currentTimeMillis();
 
     if (horizontal > 0) // scrollbar pulled right, image to the left
     {
@@ -1012,17 +1012,13 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     drawComponent(gg, sr, er);
 
     gg.translate(-transX, 0);
-    long dtime = System.currentTimeMillis();
+
     fastPaint = true;
-    repaint();
-    long rtime = System.currentTimeMillis();
-    if (debugRedraw)
-    {
-      System.err.println("Scroll:\t" + horizontal + "\tCopyArea:\t"
-              + (mtime - stime) + "\tDraw component:\t" + (dtime - mtime)
-              + "\tRepaint call:\t" + (rtime - dtime));
-    }
 
+    // Call repaint on alignment panel so that repaints from other alignment
+    // panel components can be aggregated. Otherwise performance of the overview
+    // window and others may be adversely affected.
+    av.getAlignPanel().repaint();
   }
 
   private volatile boolean lastImageGood = false;
index 128481c..5ee9150 100644 (file)
@@ -849,6 +849,7 @@ public class Desktop extends jalview.jbgui.GDesktop
     frame.setResizable(resizable);
     frame.setMaximizable(resizable);
     frame.setIconifiable(resizable);
+    frame.setOpaque(false);
 
     if (frame.getX() < 1 && frame.getY() < 1)
     {
index ab96d80..cd7b0b7 100755 (executable)
@@ -83,7 +83,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     this.av = av;
     PaintRefresher.Register(this, av.getSequenceSetId());
     av.getRanges().addPropertyChangeListener(this);
-  }
+    }
 
   /**
    * DOCUMENT ME!
@@ -204,7 +204,11 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     gg.translate(0, -transY);
 
     fastPaint = true;
-    repaint();
+
+    // Call repaint on alignment panel so that repaints from other alignment
+    // panel components can be aggregated. Otherwise performance of the overview
+    // window and others may be adversely affected.
+    av.getAlignPanel().repaint();
   }
 
   /**
@@ -216,41 +220,43 @@ public class IdCanvas extends JPanel implements ViewportListenerI
   @Override
   public void paintComponent(Graphics g)
   {
+    super.paintComponent(g);
+
     g.setColor(Color.white);
     g.fillRect(0, 0, getWidth(), getHeight());
-
+    
     if (fastPaint)
     {
       fastPaint = false;
       g.drawImage(image, 0, 0, this);
-
+    
       return;
     }
-
+    
     int oldHeight = imgHeight;
-
+    
     imgHeight = getHeight();
     imgHeight -= (imgHeight % av.getCharHeight());
-
+    
     if (imgHeight < 1)
     {
       return;
     }
-
+    
     if (oldHeight != imgHeight || image.getWidth(this) != getWidth())
     {
-      image = new BufferedImage(getWidth(), imgHeight,
-              BufferedImage.TYPE_INT_RGB);
+       image = new BufferedImage(getWidth(), imgHeight,
+                BufferedImage.TYPE_INT_RGB);
     }
-
+    
     gg = (Graphics2D) image.getGraphics();
-
+    
     // Fill in the background
     gg.setColor(Color.white);
     gg.fillRect(0, 0, getWidth(), imgHeight);
-
+    
     drawIds(av.getRanges().getStartSeq(), av.getRanges().getEndSeq());
-
+    
     g.drawImage(image, 0, 0, this);
   }
 
index 8400543..0cffc3b 100755 (executable)
@@ -23,8 +23,8 @@ package jalview.gui;
 import jalview.api.AlignViewportI;
 
 import java.awt.Color;
+import java.awt.Cursor;
 import java.awt.Graphics;
-import java.awt.Image;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
@@ -44,8 +44,6 @@ public class IdwidthAdjuster extends JPanel
 
   int oldX = 0;
 
-  Image image;
-
   AlignmentPanel ap;
 
   /**
@@ -57,14 +55,7 @@ public class IdwidthAdjuster extends JPanel
   public IdwidthAdjuster(AlignmentPanel ap)
   {
     this.ap = ap;
-
-    java.net.URL url = getClass().getResource("/images/idwidth.gif");
-
-    if (url != null)
-    {
-      image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
-    }
-
+    setBackground(Color.white);
     addMouseListener(this);
     addMouseMotionListener(this);
   }
@@ -196,10 +187,7 @@ public class IdwidthAdjuster extends JPanel
 
     if (active)
     {
-      if (image != null)
-      {
-        g.drawImage(image, getWidth() - 20, 2, this);
-      }
+        setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
     }
   }
 }
index 2991889..9df0d82 100644 (file)
@@ -183,7 +183,7 @@ public class OverviewCanvas extends JComponent
   @Override
   public void paintComponent(Graphics g)
   {
-    // super.paintComponent(g);
+    super.paintComponent(g);
 
     if (restart)
     {
index 43b4310..02d54a8 100755 (executable)
@@ -170,15 +170,20 @@ public class OverviewPanel extends JPanel
       @Override
       public void mouseMoved(MouseEvent evt)
       {
-        if (od.isPositionInBox(evt.getX(), evt.getY()))
+        if (!draggingBox)
+        // don't bother changing the cursor if we're dragging the box
+        // as we can't have moved inside or out of the box in that case
         {
-          // display drag cursor at mouse position
-          setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
-        }
-        else
-        {
-          // reset cursor
-          setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+          if (od.isPositionInBox(evt.getX(), evt.getY()))
+          {
+            // display drag cursor at mouse position
+            setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+          }
+          else
+          {
+            // reset cursor
+            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+          }
         }
       }
     });
@@ -203,6 +208,10 @@ public class OverviewPanel extends JPanel
           if (!od.isPositionInBox(evt.getX(), evt.getY()))
           {
             draggingBox = false;
+
+            // display drag cursor at mouse position
+            setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+
             od.updateViewportFromMouse(evt.getX(), evt.getY(),
                     av.getAlignment().getHiddenSequences(),
                     av.getAlignment().getHiddenColumns());
@@ -225,6 +234,13 @@ public class OverviewPanel extends JPanel
           showPopupMenu(evt);
         }
       }
+
+      @Override
+      public void mouseReleased(MouseEvent evt)
+      {
+        draggingBox = false;
+      }
+
     });
   }
 
index f772a1f..e6bba02 100755 (executable)
@@ -410,6 +410,8 @@ public class ScalePanel extends JPanel
   @Override
   public void paintComponent(Graphics g)
   {
+    super.paintComponent(g);
+
     /*
      * shouldn't get called in wrapped mode as the scale above is
      * drawn instead by SeqCanvas.drawNorthScale
@@ -550,7 +552,11 @@ public class ScalePanel extends JPanel
             || evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
     {
       // scroll event, repaint panel
-      repaint();
+       
+       // Call repaint on alignment panel so that repaints from other alignment
+    // panel components can be aggregated. Otherwise performance of the overview
+    // window and others may be adversely affected.
+      av.getAlignPanel().repaint();
     }
   }
 
index fb81f4d..2d8eb7d 100755 (executable)
@@ -297,7 +297,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       int endSeq = ranges.getEndSeq();
       int transX = 0;
       int transY = 0;
-
+      
       gg.copyArea(horizontal * charWidth, vertical * charHeight,
               img.getWidth(), img.getHeight(), -horizontal * charWidth,
               -vertical * charHeight);
@@ -339,7 +339,10 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
       gg.translate(-transX, -transY);
 
-      repaint();
+      // Call repaint on alignment panel so that repaints from other alignment
+      // panel components can be aggregated. Otherwise performance of the
+      // overview window and others may be adversely affected.
+      av.getAlignPanel().repaint();
     } finally
     {
       fastpainting = false;
@@ -353,20 +356,20 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     
     int charHeight = av.getCharHeight();
     int charWidth = av.getCharWidth();
-
+    
     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)))
@@ -390,16 +393,16 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
         gg = (Graphics2D) img.getGraphics();
         gg.setFont(av.getFont());
       }
-
+    
       if (av.antiAlias)
       {
         gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                 RenderingHints.VALUE_ANTIALIAS_ON);
       }
-
+    
       gg.setColor(Color.white);
       gg.fillRect(0, 0, img.getWidth(), img.getHeight());
-
+    
       if (av.getWrapAlignment())
       {
         drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
@@ -409,7 +412,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
         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);
@@ -506,8 +509,11 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   private BufferedImage buildLocalImage(BufferedImage selectImage)
   {
     // clone the cached image
-    BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
-            img.getType());
+         BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
+                   img.getType());
+
+    // BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
+    // img.getType());
     Graphics2D g2d = lcimg.createGraphics();
     g2d.drawImage(img, 0, 0, null);
 
@@ -547,8 +553,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
     try
     {
-      lcimg = new BufferedImage(width, height,
-              BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
+       lcimg = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
     } catch (OutOfMemoryError er)
     {
       System.gc();
@@ -1120,16 +1126,16 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       if (av.hasSearchResults())
       {
         SearchResultsI searchResults = av.getSearchResults();
-        int[] visibleResults = searchResults.getResults(nextSeq,
-                startRes, endRes);
+        int[] visibleResults = searchResults.getResults(nextSeq, startRes,
+                endRes);
         if (visibleResults != null)
         {
           for (int r = 0; r < visibleResults.length; r += 2)
           {
             seqRdr.drawHighlightedText(nextSeq, visibleResults[r],
-                    visibleResults[r + 1], (visibleResults[r] - startRes)
-                            * charWidth, offset
-                            + ((i - startSeq) * charHeight));
+                    visibleResults[r + 1],
+                    (visibleResults[r] - startRes) * charWidth,
+                    offset + ((i - startSeq) * charHeight));
           }
         }
       }
@@ -1803,9 +1809,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   {
     ViewportRanges ranges = av.getRanges();
 
-    // if (Math.abs(scrollX) > ranges.getViewportWidth())
-    // JAL-2836, 2836 temporarily removed wrapped fastpaint for release 2.10.3
-    if (true)
+    if (Math.abs(scrollX) > ranges.getViewportWidth())
     {
       /*
        * shift of more than one view width is 
index 217f653..198aa62 100644 (file)
@@ -21,6 +21,7 @@
 
 package jalview.gui;
 
+import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Jalview;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
@@ -53,6 +54,8 @@ import java.util.Vector;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
 import javax.swing.table.AbstractTableModel;
 
 /**
@@ -728,16 +731,65 @@ public class StructureChooser extends GStructureChooser
   }
 
   /**
+   * select structures for viewing by their PDB IDs
+   * 
+   * @param pdbids
+   * @return true if structures were found and marked as selected
+   */
+  public boolean selectStructure(String... pdbids)
+  {
+    boolean found = false;
+
+    FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
+            .getSelectedItem());
+    String currentView = selectedFilterOpt.getView();
+    JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
+            : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
+
+    if (restable == null)
+    {
+      // can't select (enter PDB ID, or load file - need to also select which
+      // sequence to associate with)
+      return false;
+    }
+
+    int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
+    for (int r = 0; r < restable.getRowCount(); r++)
+    {
+      for (int p = 0; p < pdbids.length; p++)
+      {
+        if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
+                .equalsIgnoreCase(pdbids[p]))
+        {
+          restable.setRowSelectionInterval(r, r);
+          found = true;
+        }
+      }
+    }
+    return found;
+  }
+  /**
    * Handles action event for btn_ok
    */
   @Override
   public void ok_ActionPerformed()
   {
+    showStructures(false);
+  }
+
+  /**
+   * structure viewer opened by this dialog, or null
+   */
+  private StructureViewer sViewer = null;
+
+  public void showStructures(boolean waitUntilFinished)
+  {
+
     final StructureSelectionManager ssm = ap.getStructureSelectionManager();
 
     final int preferredHeight = pnl_filter.getHeight();
 
-    new Thread(new Runnable()
+    Runnable viewStruc = new Runnable()
     {
       @Override
       public void run()
@@ -745,21 +797,24 @@ public class StructureChooser extends GStructureChooser
         FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
                 .getSelectedItem());
         String currentView = selectedFilterOpt.getView();
+        JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
+                : tbl_local_pdb;
+
         if (currentView == VIEWS_FILTER)
         {
-          int pdbIdColIndex = getResultTable().getColumn("PDB Id")
+          int pdbIdColIndex = restable.getColumn("PDB Id")
                   .getModelIndex();
-          int refSeqColIndex = getResultTable().getColumn("Ref Sequence")
+          int refSeqColIndex = restable.getColumn("Ref Sequence")
                   .getModelIndex();
-          int[] selectedRows = getResultTable().getSelectedRows();
+          int[] selectedRows = restable.getSelectedRows();
           PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
           int count = 0;
           List<SequenceI> selectedSeqsToView = new ArrayList<>();
           for (int row : selectedRows)
           {
-            String pdbIdStr = getResultTable()
+            String pdbIdStr = restable
                     .getValueAt(row, pdbIdColIndex).toString();
-            SequenceI selectedSeq = (SequenceI) getResultTable()
+            SequenceI selectedSeq = (SequenceI) restable
                     .getValueAt(row, refSeqColIndex);
             selectedSeqsToView.add(selectedSeq);
             PDBEntry pdbEntry = selectedSeq.getPDBEntry(pdbIdStr);
@@ -780,7 +835,8 @@ public class StructureChooser extends GStructureChooser
           }
           SequenceI[] selectedSeqs = selectedSeqsToView
                   .toArray(new SequenceI[selectedSeqsToView.size()]);
-          launchStructureViewer(ssm, pdbEntriesToView, ap, selectedSeqs);
+          sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
+                  selectedSeqs);
         }
         else if (currentView == VIEWS_LOCAL_PDB)
         {
@@ -803,7 +859,8 @@ public class StructureChooser extends GStructureChooser
           }
           SequenceI[] selectedSeqs = selectedSeqsToView
                   .toArray(new SequenceI[selectedSeqsToView.size()]);
-          launchStructureViewer(ssm, pdbEntriesToView, ap, selectedSeqs);
+          sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
+                  selectedSeqs);
         }
         else if (currentView == VIEWS_ENTER_ID)
         {
@@ -832,7 +889,7 @@ public class StructureChooser extends GStructureChooser
           }
 
           PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
-          launchStructureViewer(ssm, pdbEntriesToView, ap,
+          sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
                   new SequenceI[]
                   { selectedSequence });
         }
@@ -849,14 +906,40 @@ public class StructureChooser extends GStructureChooser
                           DataSourceType.FILE, selectedSequence, true,
                           Desktop.instance);
 
-          launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
+          sViewer = launchStructureViewer(
+                  ssm, new PDBEntry[]
+                  { fileEntry }, ap,
                   new SequenceI[]
                   { selectedSequence });
         }
-        closeAction(preferredHeight);
-        mainFrame.dispose();
+        SwingUtilities.invokeLater(new Runnable()
+        {
+          @Override
+          public void run()
+          {
+            closeAction(preferredHeight);
+            mainFrame.dispose();
+          }
+        });
       }
-    }).start();
+    };
+    Thread runner = new Thread(viewStruc);
+    runner.start();
+    if (waitUntilFinished)
+    {
+      while (sViewer == null ? runner.isAlive()
+              : (sViewer.sview == null ? true
+                      : !sViewer.sview.hasMapping()))
+      {
+        try
+        {
+          Thread.sleep(300);
+        } catch (InterruptedException ie)
+        {
+
+        }
+      }
+    }
   }
 
   private PDBEntry getFindEntry(String id, Vector<PDBEntry> pdbEntries)
@@ -874,7 +957,8 @@ public class StructureChooser extends GStructureChooser
     return foundEntry;
   }
 
-  private void launchStructureViewer(StructureSelectionManager ssm,
+  private StructureViewer launchStructureViewer(
+          StructureSelectionManager ssm,
           final PDBEntry[] pdbEntriesToView,
           final AlignmentPanel alignPanel, SequenceI[] sequences)
   {
@@ -948,6 +1032,7 @@ public class StructureChooser extends GStructureChooser
       sViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
     }
     setProgressBar(null, progressId);
+    return sViewer;
   }
 
   /**
@@ -1178,4 +1263,9 @@ public class StructureChooser extends GStructureChooser
   {
     return progressBar.operationInProgress();
   }
+
+  public JalviewStructureDisplayI getOpenedStructureViewer()
+  {
+    return sViewer == null ? null : sViewer.sview;
+  }
 }
index fb37b77..f37df71 100644 (file)
@@ -104,7 +104,7 @@ public class StructureViewer
             new PDBEntry[seqsForPdbs.size()]);
     SequenceI[][] theSeqs = seqsForPdbs.values().toArray(
             new SequenceI[seqsForPdbs.size()][]);
-    JalviewStructureDisplayI sview = null;
+
     if (viewerType.equals(ViewerType.JMOL))
     {
       sview = new AppJmol(ap, pdbsForFile, theSeqs);
@@ -203,7 +203,7 @@ public class StructureViewer
   private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs,
           SequenceI[] seqsForPdbs, AlignmentPanel ap)
   {
-    List<SequenceI> seqs = new ArrayList<SequenceI>();
+    List<SequenceI> seqs = new ArrayList<>();
     if (pdbs == null || pdbs.length == 0)
     {
       return null;
@@ -227,11 +227,12 @@ public class StructureViewer
             ap);
   }
 
+  JalviewStructureDisplayI sview = null;
+
   public JalviewStructureDisplayI viewStructures(PDBEntry pdb,
           SequenceI[] seqsForPdb, AlignmentPanel ap)
   {
     ViewerType viewerType = getViewerType();
-    JalviewStructureDisplayI sview = null;
     if (viewerType.equals(ViewerType.JMOL))
     {
       sview = new AppJmol(pdb, seqsForPdb, null, ap);
@@ -270,7 +271,6 @@ public class StructureViewer
     final boolean usetoColourbyseq = viewerData.isColourWithAlignPanel();
     final boolean viewerColouring = viewerData.isColourByViewer();
 
-    JalviewStructureDisplayI sview = null;
     switch (type)
     {
     case JMOL:
@@ -287,4 +287,16 @@ public class StructureViewer
     return sview;
   }
 
+  public boolean isBusy()
+  {
+    if (sview != null)
+    {
+      if (!sview.hasMapping())
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
 }
index 31c20ed..93d675a 100644 (file)
@@ -34,6 +34,7 @@ import jalview.io.JalviewFileView;
 import jalview.jbgui.GStructureViewer;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemes;
+import jalview.structure.StructureMapping;
 import jalview.structures.models.AAStructureBindingModel;
 import jalview.util.MessageManager;
 
@@ -102,9 +103,9 @@ public abstract class StructureViewerBase extends GStructureViewer
 
   protected boolean alignAddedStructures = false;
 
-  protected boolean _started = false;
+  protected volatile boolean _started = false;
 
-  protected boolean addingStructures = false;
+  protected volatile boolean addingStructures = false;
 
   protected Thread worker = null;
 
@@ -113,6 +114,13 @@ public abstract class StructureViewerBase extends GStructureViewer
   protected JMenu viewSelectionMenu;
 
   /**
+   * set after sequence colouring has been applied for this structure viewer.
+   * used to determine if the final sequence/structure mapping has been
+   * determined
+   */
+  protected volatile boolean seqColoursApplied = false;
+
+  /**
    * Default constructor
    */
   public StructureViewerBase()
@@ -909,6 +917,7 @@ public abstract class StructureViewerBase extends GStructureViewer
       {
         binding.colourBySequence(ap);
       }
+      seqColoursApplied = true;
     }
   }
 
@@ -1028,4 +1037,42 @@ public abstract class StructureViewerBase extends GStructureViewer
       seqColour_actionPerformed(null);
     }
   }
+
+  @Override
+  public boolean hasMapping()
+  {
+    if (worker != null && (addingStructures || _started))
+    {
+      return false;
+    }
+    if (getBinding() == null)
+    {
+      if (_aps == null || _aps.size() == 0)
+      {
+        // viewer has been closed, but we did at some point run.
+        return true;
+      }
+      return false;
+    }
+    String[] pdbids = getBinding().getStructureFiles();
+    if (pdbids == null)
+    {
+      return false;
+    }
+    int p=0;
+    for (String pdbid:pdbids) {
+      StructureMapping sm[] = getBinding().getSsm().getMapping(pdbid);
+      if (sm!=null && sm.length>0 && sm[0]!=null) {
+        p++;
+      }
+    }
+    // only return true if there is a mapping for every structure file we have loaded
+    if (p == 0 || p != pdbids.length)
+    {
+      return false;
+    }
+    // and that coloring has been applied
+    return seqColoursApplied;
+  }
+
 }
index 40789ed..fcf322d 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.structure;
 
 import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Mapping;
 import jalview.datamodel.SequenceI;
 
 import java.util.ArrayList;
@@ -39,7 +40,7 @@ public class StructureMapping
 
   String pdbchain;
 
-  public static final int UNASSIGNED_VALUE = -1;
+  public static final int UNASSIGNED_VALUE = Integer.MIN_VALUE;
 
   private static final int PDB_RES_NUM_INDEX = 0;
 
@@ -49,6 +50,7 @@ public class StructureMapping
   // and atomNo
   HashMap<Integer, int[]> mapping;
 
+  jalview.datamodel.Mapping seqToPdbMapping = null;
   /**
    * Constructor
    * 
@@ -73,6 +75,14 @@ public class StructureMapping
     this.mappingDetails = mappingDetails;
   }
 
+  public StructureMapping(SequenceI seq, String pdbFile2, String pdbId2,
+          String chain, HashMap<Integer, int[]> mapping2,
+          String mappingOutput, Mapping seqToPdbMapping)
+  {
+    this(seq, pdbFile2, pdbId2, chain, mapping2, mappingOutput);
+    this.seqToPdbMapping = seqToPdbMapping;
+  }
+
   public SequenceI getSequence()
   {
     return sequence;
@@ -109,7 +119,8 @@ public class StructureMapping
   /**
    * 
    * @param seqpos
-   * @return 0 or the corresponding residue number for the sequence position
+   * @return UNASSIGNED_VALUE or the corresponding residue number for the
+   *         sequence position
    */
   public int getPDBResNum(int seqpos)
   {
@@ -247,4 +258,9 @@ public class StructureMapping
   {
     return mapping;
   }
+
+  public Mapping getSeqToPdbMapping()
+  {
+    return seqToPdbMapping;
+  }
 }
index 35e2536..10fe836 100644 (file)
@@ -74,8 +74,6 @@ public class StructureSelectionManager
 
   private boolean addTempFacAnnot = false;
 
-  private SiftsClient siftsClient = null;
-
   /*
    * Set of any registered mappings between (dataset) sequences.
    */
@@ -328,22 +326,20 @@ public class StructureSelectionManager
   }
 
   /**
-   * create sequence structure mappings between each sequence and the given
-   * pdbFile (retrieved via the given protocol).
+   * Import a single structure file and register sequence structure mappings for
+   * broadcasting colouring, mouseovers and selection events (convenience
+   * wrapper).
    * 
    * @param forStructureView
    *          when true, record the mapping for use in mouseOvers
-   * 
-   * @param sequenceArray
+   * @param sequence
    *          - one or more sequences to be mapped to pdbFile
-   * @param targetChainIds
+   * @param targetChains
    *          - optional chain specification for mapping each sequence to pdb
-   *          (may be nill, individual elements may be nill) - JBPNote: JAL-2693
-   *          - this should be List<List<String>>, empty lists indicate no
-   *          predefined mappings
+   *          (may be nill, individual elements may be nill)
    * @param pdbFile
    *          - structure data resource
-   * @param sourceType
+   * @param protocol
    *          - how to resolve data from resource
    * @return null or the structure data parsed as a pdb file
    */
@@ -355,46 +351,51 @@ public class StructureSelectionManager
             pdbFile, sourceType, null);
   }
 
+  /**
+   * create sequence structure mappings between each sequence and the given
+   * pdbFile (retrieved via the given protocol). Either constructs a mapping
+   * using NW alignment or derives one from any available SIFTS mapping data.
+   * 
+   * @param forStructureView
+   *          when true, record the mapping for use in mouseOvers
+   * 
+   * @param sequenceArray
+   *          - 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) - JBPNote: JAL-2693
+   *          - this should be List<List<String>>, empty lists indicate no
+   *          predefined mappings
+   * @param pdbFile
+   *          - structure data resource
+   * @param sourceType
+   *          - how to resolve data from resource
+   * @param IProgressIndicator
+   *          reference to UI component that maintains a progress bar for the
+   *          mapping operation
+   * @return null or the structure data parsed as a pdb file
+   */
   synchronized public StructureFile computeMapping(
           boolean forStructureView, SequenceI[] sequenceArray,
           String[] targetChainIds, String pdbFile, DataSourceType sourceType,
           IProgressIndicator progress)
   {
     long progressSessionId = System.currentTimeMillis() * 3;
-    /*
-     * There will be better ways of doing this in the future, for now we'll use
-     * the tried and tested MCview pdb mapping
+
+    /**
+     * do we extract and transfer annotation from 3D data ?
      */
-    boolean parseSecStr = processSecondaryStructure;
-    if (isPDBFileRegistered(pdbFile))
-    {
-      for (SequenceI sq : sequenceArray)
-      {
-        SequenceI ds = sq;
-        while (ds.getDatasetSequence() != null)
-        {
-          ds = ds.getDatasetSequence();
-        }
-        ;
-        if (ds.getAnnotation() != null)
-        {
-          for (AlignmentAnnotation ala : ds.getAnnotation())
-          {
-            // false if any annotation present from this structure
-            // JBPNote this fails for jmol/chimera view because the *file* is
-            // passed, not the structure data ID -
-            if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
-            {
-              parseSecStr = false;
-            }
-          }
-        }
-      }
-    }
+    // FIXME: possibly should just delete
+
+    boolean parseSecStr = processSecondaryStructure
+            ? isStructureFileProcessed(pdbFile, sequenceArray)
+            : false;
+
     StructureFile pdb = null;
     boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
     try
     {
+      // FIXME if sourceType is not null, we've lost data here
       sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
       pdb = new JmolParser(pdbFile, sourceType);
 
@@ -411,7 +412,10 @@ public class StructureSelectionManager
       ex.printStackTrace();
       return null;
     }
-
+    /*
+     * sifts client - non null if SIFTS mappings are to be used 
+     */
+    SiftsClient siftsClient = null;
     try
     {
       if (isMapUsingSIFTs)
@@ -422,6 +426,7 @@ public class StructureSelectionManager
     {
       isMapUsingSIFTs = false;
       e.printStackTrace();
+      siftsClient = null;
     }
 
     String targetChainId;
@@ -524,12 +529,12 @@ public class StructureSelectionManager
           try
           {
             siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
-                    pdb, maxChain, sqmpping, maxAlignseq);
+                    pdb, maxChain, sqmpping, maxAlignseq, siftsClient);
             seqToStrucMapping.add(siftsMapping);
-            maxChain.makeExactMapping(maxAlignseq, seq);
-            maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
+            maxChain.makeExactMapping(siftsMapping, seq);
+            maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
                                                        // "IEA:SIFTS" ?
-            maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
+            maxChain.transferResidueAnnotation(siftsMapping, null);
             ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
 
           } catch (SiftsException e)
@@ -540,7 +545,8 @@ public class StructureSelectionManager
                     targetChainId, maxChain, pdb, maxAlignseq);
             seqToStrucMapping.add(nwMapping);
             maxChain.makeExactMapping(maxAlignseq, seq);
-            maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
+            maxChain.transferRESNUMFeatures(seq, "IEA:Jalview"); // FIXME: is
+                                                                 // this
                                                         // "IEA:Jalview" ?
             maxChain.transferResidueAnnotation(nwMapping, sqmpping);
             ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
@@ -551,11 +557,17 @@ public class StructureSelectionManager
           List<StructureMapping> foundSiftsMappings = new ArrayList<>();
           for (PDBChain chain : pdb.getChains())
           {
+            StructureMapping siftsMapping = null;
             try
             {
-              StructureMapping siftsMapping = getStructureMapping(seq,
-                      pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
+              siftsMapping = getStructureMapping(seq,
+                      pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq,
+                      siftsClient);
               foundSiftsMappings.add(siftsMapping);
+              chain.makeExactMapping(siftsMapping, seq);
+              chain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
+              // "IEA:SIFTS" ?
+              chain.transferResidueAnnotation(siftsMapping, null);
             } catch (SiftsException e)
             {
               System.err.println(e.getMessage());
@@ -564,11 +576,6 @@ public class StructureSelectionManager
           if (!foundSiftsMappings.isEmpty())
           {
             seqToStrucMapping.addAll(foundSiftsMappings);
-            maxChain.makeExactMapping(maxAlignseq, seq);
-            maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
-                                                       // "IEA:SIFTS" ?
-            maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
-                    sqmpping);
             ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
           }
           else
@@ -608,6 +615,46 @@ public class StructureSelectionManager
     return pdb;
   }
 
+  /**
+   * check if we need to extract secondary structure from given pdbFile and
+   * transfer to sequences
+   * 
+   * @param pdbFile
+   * @param sequenceArray
+   * @return
+   */
+  private boolean isStructureFileProcessed(String pdbFile,
+          SequenceI[] sequenceArray)
+  {
+    boolean parseSecStr = true;
+    if (isPDBFileRegistered(pdbFile))
+    {
+      for (SequenceI sq : sequenceArray)
+      {
+        SequenceI ds = sq;
+        while (ds.getDatasetSequence() != null)
+        {
+          ds = ds.getDatasetSequence();
+        }
+        ;
+        if (ds.getAnnotation() != null)
+        {
+          for (AlignmentAnnotation ala : ds.getAnnotation())
+          {
+            // false if any annotation present from this structure
+            // JBPNote this fails for jmol/chimera view because the *file* is
+            // passed, not the structure data ID -
+            if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
+            {
+              parseSecStr = false;
+            }
+          }
+        }
+      }
+    }
+    return parseSecStr;
+  }
+
   public void addStructureMapping(StructureMapping sm)
   {
     mappings.add(sm);
@@ -624,13 +671,15 @@ public class StructureSelectionManager
    * @param maxChain
    * @param sqmpping
    * @param maxAlignseq
+   * @param siftsClient
+   *          client for retrieval of SIFTS mappings for this structure
    * @return
    * @throws SiftsException
    */
   private StructureMapping getStructureMapping(SequenceI seq,
           String pdbFile, String targetChainId, StructureFile pdb,
           PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
-          AlignSeq maxAlignseq) throws SiftsException
+          AlignSeq maxAlignseq, SiftsClient siftsClient) throws SiftsException
   {
     StructureMapping curChainMapping = siftsClient
             .getSiftsStructureMapping(seq, pdbFile, targetChainId);
@@ -639,7 +688,7 @@ public class StructureSelectionManager
       PDBChain chain = pdb.findChain(targetChainId);
       if (chain != null)
       {
-        chain.transferResidueAnnotation(curChainMapping, sqmpping);
+        chain.transferResidueAnnotation(curChainMapping, null);
       }
     } catch (Exception e)
     {
index 01ec8b1..1366ada 100644 (file)
@@ -2786,7 +2786,7 @@ public abstract class AlignmentViewport
     int lastSeq = alignment.getHeight() - 1;
     List<AlignedCodonFrame> seqMappings = null;
     for (int seqNo = ranges
-            .getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
+            .getStartSeq(); seqNo <= lastSeq; seqNo++, seqOffset++)
     {
       sequence = getAlignment().getSequenceAt(seqNo);
       if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
index 170f4e9..0235081 100644 (file)
@@ -58,6 +58,10 @@ public abstract class OverviewDimensions
 
   protected int alheight;
 
+  protected float widthRatio;
+
+  protected float heightRatio;
+
   /**
    * Create an OverviewDimensions object
    * 
@@ -157,23 +161,25 @@ public abstract class OverviewDimensions
   public float getPixelsPerCol()
   {
     resetAlignmentDims();
-    return (float) width / alwidth;
+    return 1 / widthRatio;
   }
 
   public float getPixelsPerSeq()
   {
     resetAlignmentDims();
-    return (float) sequencesHeight / alheight;
+    return 1 / heightRatio;
   }
 
   public void setWidth(int w)
   {
     width = w;
+    widthRatio = (float) alwidth / width;
   }
 
   public void setHeight(int h)
   {
     sequencesHeight = h - graphHeight;
+    heightRatio = (float) alheight / sequencesHeight;
   }
 
   /**
@@ -273,14 +279,14 @@ public abstract class OverviewDimensions
 
     // boxX, boxY is the x,y location equivalent to startRes, startSeq
     int xPos = Math.min(startRes, alwidth - vpwidth + 1);
-    boxX = Math.round((float) xPos * width / alwidth);
-    boxY = Math.round((float) startSeq * sequencesHeight / alheight);
+    boxX = Math.round(xPos / widthRatio);
+    boxY = Math.round(startSeq / heightRatio);
 
     // boxWidth is the width in residues translated to pixels
-    boxWidth = Math.round((float) vpwidth * width / alwidth);
+    boxWidth = Math.round(vpwidth / widthRatio);
 
     // boxHeight is the height in sequences translated to pixels
-    boxHeight = Math.round((float) vpheight * sequencesHeight / alheight);
+    boxHeight = Math.round(vpheight / heightRatio);
   }
 
   /**
index 0ca1cc3..de90a21 100644 (file)
@@ -50,6 +50,8 @@ public class OverviewDimensionsHideHidden extends OverviewDimensions
   public void updateViewportFromMouse(int mousex, int mousey,
           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
   {
+    resetAlignmentDims();
+
     int xAsRes = getLeftXFromCentreX(mousex, hiddenCols);
     int yAsSeq = getTopYFromCentreY(mousey, hiddenSeqs);
 
@@ -61,24 +63,29 @@ public class OverviewDimensionsHideHidden extends OverviewDimensions
   public void adjustViewportFromMouse(int mousex, int mousey,
           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
   {
+    resetAlignmentDims();
+
     // calculate translation in pixel terms:
     // get mouse location in viewport coords, add translation in viewport
     // coords, and update viewport as usual
-    int vpx = Math.round((float) mousex * alwidth / width);
-    int vpy = Math.round((float) mousey * alheight / sequencesHeight);
+    int vpx = Math.round(mousex * widthRatio);
+    int vpy = Math.round(mousey * heightRatio);
 
     updateViewportFromTopLeft(vpx + xdiff, vpy + ydiff, hiddenSeqs,
             hiddenCols);
 
   }
 
+  /**
+   * {@inheritDoc} Callers should have already called resetAlignmentDims to
+   * refresh alwidth, alheight and width/height ratios
+   */
   @Override
   protected void updateViewportFromTopLeft(int leftx, int topy,
           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
   {
     int xAsRes = leftx;
     int yAsSeq = topy;
-    resetAlignmentDims();
 
     if (xAsRes < 0)
     {
@@ -162,19 +169,30 @@ public class OverviewDimensionsHideHidden extends OverviewDimensions
   {
     alwidth = ranges.getVisibleAlignmentWidth();
     alheight = ranges.getVisibleAlignmentHeight();
+
+    widthRatio = (float) alwidth / width;
+    heightRatio = (float) alheight / sequencesHeight;
   }
 
+  /**
+   * {@inheritDoc} Callers should have already called resetAlignmentDims to
+   * refresh widthRatio
+   */
   @Override
   protected int getLeftXFromCentreX(int mousex, HiddenColumns hidden)
   {
-    int vpx = Math.round((float) mousex * alwidth / width);
+    int vpx = Math.round(mousex * widthRatio);
     return vpx - ranges.getViewportWidth() / 2;
   }
 
+  /**
+   * {@inheritDoc} Callers should have already called resetAlignmentDims to
+   * refresh heightRatio
+   */
   @Override
   protected int getTopYFromCentreY(int mousey, HiddenSequences hidden)
   {
-    int vpy = Math.round((float) mousey * alheight / sequencesHeight);
+    int vpy = Math.round(mousey * heightRatio);
     return vpy - ranges.getViewportHeight() / 2;
   }
 
@@ -182,10 +200,12 @@ public class OverviewDimensionsHideHidden extends OverviewDimensions
   public void setDragPoint(int x, int y, HiddenSequences hiddenSeqs,
           HiddenColumns hiddenCols)
   {
+    resetAlignmentDims();
+
     // get alignment position of x and box (can get directly from vpranges) and
     // calculate difference between the positions
-    int vpx = Math.round((float) x * alwidth / width);
-    int vpy = Math.round((float) y * alheight / sequencesHeight);
+    int vpx = Math.round(x * widthRatio);
+    int vpy = Math.round(y * heightRatio);
 
     xdiff = ranges.getStartRes() - vpx;
     ydiff = ranges.getStartSeq() - vpy;
index 79e1c47..3aa6e1b 100644 (file)
@@ -72,6 +72,8 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
   public void updateViewportFromMouse(int mousex, int mousey,
           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
   {
+    resetAlignmentDims();
+
     // convert mousex and mousey to alignment units as well as
     // translating to top left corner of viewport - this is an absolute position
     int xAsRes = getLeftXFromCentreX(mousex, hiddenCols);
@@ -93,6 +95,8 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
   public void adjustViewportFromMouse(int mousex, int mousey,
           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
   {
+    resetAlignmentDims();
+
     // calculate translation in pixel terms:
     // get mouse location in viewport coords, add translation in viewport
     // coords,
@@ -100,20 +104,23 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
     int vpx = Math.round((float) mousex * alwidth / width);
     int visXAsRes = hiddenCols.absoluteToVisibleColumn(vpx) + xdiff;
 
-    int vpy = Math.round((float) mousey * alheight / sequencesHeight);
+    int vpy = Math.round(mousey * heightRatio);
     int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(vpy) + ydiff;
 
     // update viewport accordingly
     updateViewportFromTopLeft(visXAsRes, visYAsRes, hiddenSeqs, hiddenCols);
   }
 
+  /**
+   * {@inheritDoc} Callers should have already called resetAlignmentDims to
+   * refresh alwidth, alheight and width/height ratios
+   */
   @Override
   protected void updateViewportFromTopLeft(int leftx, int topy,
           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
   {
     int visXAsRes = leftx;
     int visYAsSeq = topy;
-    resetAlignmentDims();
 
     if (visXAsRes < 0)
     {
@@ -225,8 +232,16 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
   {
     alwidth = ranges.getAbsoluteAlignmentWidth();
     alheight = ranges.getAbsoluteAlignmentHeight();
+
+    widthRatio = (float) alwidth / width;
+    heightRatio = (float) alheight / sequencesHeight;
   }
 
+
+  /**
+   * {@inheritDoc} Callers should have already called resetAlignmentDims to
+   * refresh widthRatio
+   */
   @Override
   protected int getLeftXFromCentreX(int mousex, HiddenColumns hidden)
   {
@@ -235,10 +250,14 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
             vpx);
   }
 
+  /**
+   * {@inheritDoc} Callers should have already called resetAlignmentDims to
+   * refresh heightRatio
+   */
   @Override
   protected int getTopYFromCentreY(int mousey, HiddenSequences hidden)
   {
-    int vpy = Math.round((float) mousey * alheight / sequencesHeight);
+    int vpy = Math.round(mousey * heightRatio);
     return hidden.subtractVisibleRows(ranges.getViewportHeight() / 2, vpy);
   }
 
@@ -246,10 +265,12 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
   public void setDragPoint(int x, int y, HiddenSequences hiddenSeqs,
           HiddenColumns hiddenCols)
   {
+    resetAlignmentDims();
+
     // get alignment position of x and box (can get directly from vpranges) and
     // calculate difference between the positions
-    int vpx = Math.round((float) x * alwidth / width);
-    int vpy = Math.round((float) y * alheight / sequencesHeight);
+    int vpx = Math.round(x * widthRatio);
+    int vpy = Math.round(y * heightRatio);
 
     xdiff = ranges.getStartRes() - hiddenCols.absoluteToVisibleColumn(vpx);
     ydiff = ranges.getStartSeq()
index fb8864d..1677eca 100644 (file)
@@ -61,6 +61,8 @@ public class DBRefFetcher implements Runnable
 {
   private static final String NEWLINE = System.lineSeparator();
 
+  public static final String TRIM_RETRIEVED_SEQUENCES = "TRIM_FETCHED_DATASET_SEQS";
+
   public interface FetchFinishedListenerI
   {
     void finished();
@@ -139,7 +141,7 @@ public class DBRefFetcher implements Runnable
             .getSequenceFetcherSingleton(progressIndicatorFrame);
     // set default behaviour for transferring excess sequence data to the
     // dataset
-    trimDsSeqs = Cache.getDefault("TRIM_FETCHED_DATASET_SEQS", true);
+    trimDsSeqs = Cache.getDefault(TRIM_RETRIEVED_SEQUENCES, true);
     if (sources == null)
     {
       setDatabaseSources(featureSettings, isNucleotide);
index 0227e35..62e59c9 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.ws.dbsources;
 
+import jalview.bin.Cache;
 import jalview.datamodel.DBRefSource;
 
 import com.stevesoft.pat.Regex;
@@ -34,6 +35,9 @@ import com.stevesoft.pat.Regex;
  */
 abstract public class Pfam extends Xfam
 {
+  private static final String PFAM_BASEURL_KEY = "PFAM_BASEURL";
+
+  private static final String DEFAULT_PFAM_BASEURL = "https://pfam.xfam.org";
 
   public Pfam()
   {
@@ -48,7 +52,6 @@ abstract public class Pfam extends Xfam
   @Override
   public String getAccessionSeparator()
   {
-    // TODO Auto-generated method stub
     return null;
   }
 
@@ -60,7 +63,6 @@ abstract public class Pfam extends Xfam
   @Override
   public Regex getAccessionValidator()
   {
-    // TODO Auto-generated method stub
     return null;
   }
 
@@ -91,17 +93,14 @@ abstract public class Pfam extends Xfam
   @Override
   public String getDbVersion()
   {
-    // TODO Auto-generated method stub
     return null;
   }
 
-  /**
-   * Returns base URL for selected Pfam alignment type
-   * 
-   * @return PFAM URL stub for this DbSource
-   */
   @Override
-  protected abstract String getXFAMURL();
+  protected String getURLPrefix()
+  {
+    return Cache.getDefault(PFAM_BASEURL_KEY, DEFAULT_PFAM_BASEURL);
+  }
 
   /*
    * (non-Javadoc)
index ec9fcbb..0600427 100644 (file)
@@ -31,20 +31,8 @@ public class PfamFull extends Pfam
     super();
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.ws.dbsources.Pfam#getPFAMURL()
-   */
-  @Override
-  protected String getXFAMURL()
-  {
-    return "http://pfam.xfam.org/family/";
-
-  }
-
   @Override
-  public String getXFAMURLSUFFIX()
+  public String getURLSuffix()
   {
     return "/alignment/full";
   }
index 33c39b1..dff8a17 100644 (file)
@@ -33,19 +33,8 @@ public class PfamSeed extends Pfam
     super();
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.ws.dbsources.Pfam#getPFAMURL()
-   */
-  @Override
-  protected String getXFAMURL()
-  {
-    return "http://pfam.xfam.org/family/";
-  }
-
   @Override
-  public String getXFAMURLSUFFIX()
+  public String getURLSuffix()
   {
     return "/alignment/seed";
   }
index 97f73d0..51edb05 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.ws.dbsources;
 
+import jalview.bin.Cache;
 import jalview.datamodel.DBRefSource;
 
 import com.stevesoft.pat.Regex;
@@ -31,6 +32,15 @@ import com.stevesoft.pat.Regex;
  */
 abstract public class Rfam extends Xfam
 {
+  private static final String RFAM_BASEURL_KEY = "RFAM_BASEURL";
+
+  private static final String DEFAULT_RFAM_BASEURL = "https://rfam.xfam.org";
+
+  @Override
+  protected String getURLPrefix()
+  {
+    return Cache.getDefault(RFAM_BASEURL_KEY, DEFAULT_RFAM_BASEURL);
+  }
 
   public Rfam()
   {
@@ -46,7 +56,6 @@ abstract public class Rfam extends Xfam
   @Override
   public String getAccessionSeparator()
   {
-    // TODO Auto-generated method stub
     return null;
   }
 
@@ -58,7 +67,6 @@ abstract public class Rfam extends Xfam
   @Override
   public Regex getAccessionValidator()
   {
-    // TODO Auto-generated method stub
     return null;
   }
 
@@ -82,18 +90,9 @@ abstract public class Rfam extends Xfam
   @Override
   public String getDbVersion()
   {
-    // TODO Auto-generated method stub
     return null;
   }
 
-  /**
-   * Returns base URL for selected Rfam alignment type
-   * 
-   * @return RFAM URL stub for this DbSource
-   */
-  @Override
-  protected abstract String getXFAMURL();
-
   /*
    * (non-Javadoc)
    * 
index b2ca31a..d815336 100644 (file)
@@ -33,20 +33,8 @@ public class RfamFull extends Rfam
     super();
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.ws.dbsources.Rfam#getXFAMURL()
-   */
-  @Override
-  protected String getXFAMURL()
-  {
-    return "http://rfam.xfam.org/family/";
-
-  }
-
   @Override
-  public String getXFAMURLSUFFIX()
+  public String getURLSuffix()
   {
     return "/alignment/full";
   }
index f714547..a74e829 100644 (file)
@@ -33,19 +33,8 @@ public class RfamSeed extends Rfam
     super();
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.ws.dbsources.Rfam#getRFAMURL()
-   */
-  @Override
-  protected String getXFAMURL()
-  {
-    return "http://rfam.xfam.org/family/";
-  }
-
   @Override
-  public String getXFAMURLSUFFIX()
+  public String getURLSuffix()
   {
     // to download gzipped file add '?gzip=1'
     return "/alignment/stockholm";
index 73775cf..6b09eb6 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.ws.dbsources;
 
+import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
@@ -52,6 +53,8 @@ import com.stevesoft.pat.Regex;
  */
 public class Uniprot extends DbSourceProxyImpl
 {
+  private static final String DEFAULT_UNIPROT_DOMAIN = "https://www.uniprot.org";
+
   private static final String BAR_DELIMITER = "|";
 
   /*
@@ -67,6 +70,11 @@ public class Uniprot extends DbSourceProxyImpl
     super();
   }
 
+  private String getDomain()
+  {
+    return Cache.getDefault("UNIPROT_DOMAIN", DEFAULT_UNIPROT_DOMAIN);
+  }
+
   /*
    * (non-Javadoc)
    * 
@@ -163,7 +171,7 @@ public class Uniprot extends DbSourceProxyImpl
               "(UNIPROT\\|?|UNIPROT_|UNIREF\\d+_|UNIREF\\d+\\|?)", "");
       AlignmentI al = null;
 
-      String downloadstring = "http://www.uniprot.org/uniprot/" + queries
+      String downloadstring = getDomain() + "/uniprot/" + queries
               + ".xml";
       URL url = null;
       URLConnection urlconn = null;
index 26291eb..b83f558 100644 (file)
@@ -42,7 +42,12 @@ public abstract class Xfam extends DbSourceProxyImpl
     super();
   }
 
-  protected abstract String getXFAMURL();
+  /**
+   * the base URL for this Xfam-like service
+   * 
+   * @return
+   */
+  protected abstract String getURLPrefix();
 
   @Override
   public abstract String getDbVersion();
@@ -57,8 +62,7 @@ public abstract class Xfam extends DbSourceProxyImpl
     // retrieved.
     startQuery();
     // TODO: trap HTTP 404 exceptions and return null
-    String xfamUrl = getXFAMURL() + queries.trim().toUpperCase()
-            + getXFAMURLSUFFIX();
+    String xfamUrl = getURL(queries);
 
     if (Cache.log != null)
     {
@@ -83,6 +87,12 @@ public abstract class Xfam extends DbSourceProxyImpl
     return rcds;
   }
 
+  String getURL(String queries)
+  {
+    return getURLPrefix() + "/family/" + queries.trim().toUpperCase()
+            + getURLSuffix();
+  }
+
   /**
    * Pfam and Rfam provide alignments
    */
@@ -97,7 +107,7 @@ public abstract class Xfam extends DbSourceProxyImpl
    * 
    * @return "" for most Xfam sources
    */
-  public String getXFAMURLSUFFIX()
+  public String getURLSuffix()
   {
     return "";
   }
index 68af7c3..b5f9653 100644 (file)
@@ -92,14 +92,24 @@ public class SiftsClient implements SiftsClientI
 
   private CoordinateSys seqCoordSys = CoordinateSys.UNIPROT;
 
+  /**
+   * PDB sequence position to sequence coordinate mapping as derived from SIFTS
+   * record for the identified SeqCoordSys Used for lift-over from sequence
+   * derived from PDB (with first extracted PDBRESNUM as 'start' to the sequence
+   * being annotated with PDB data
+   */
+  private jalview.datamodel.Mapping seqFromPdbMapping;
+
   private static final int BUFFER_SIZE = 4096;
 
-  public static final int UNASSIGNED = -1;
+  public static final int UNASSIGNED = Integer.MIN_VALUE;
 
   private static final int PDB_RES_POS = 0;
 
   private static final int PDB_ATOM_POS = 1;
 
+  private static final int PDBE_POS = 2;
+
   private static final String NOT_OBSERVED = "Not_Observed";
 
   private static final String SIFTS_FTP_BASE_URL = "http://ftp.ebi.ac.uk/pub/databases/msd/sifts/xml/";
@@ -413,6 +423,11 @@ public class SiftsClient implements SiftsClientI
   public StructureMapping getSiftsStructureMapping(SequenceI seq,
           String pdbFile, String chain) throws SiftsException
   {
+    SequenceI aseq = seq;
+    while (seq.getDatasetSequence() != null)
+    {
+      seq = seq.getDatasetSequence();
+    }
     structId = (chain == null) ? pdbId : pdbId + "|" + chain;
     System.out.println("Getting SIFTS mapping for " + structId + ": seq "
             + seq.getName());
@@ -435,8 +450,9 @@ public class SiftsClient implements SiftsClientI
     HashMap<Integer, int[]> mapping = getGreedyMapping(chain, seq, ps);
 
     String mappingOutput = mappingDetails.toString();
-    StructureMapping siftsMapping = new StructureMapping(seq, pdbFile,
-            pdbId, chain, mapping, mappingOutput);
+    StructureMapping siftsMapping = new StructureMapping(aseq, pdbFile,
+            pdbId, chain, mapping, mappingOutput, seqFromPdbMapping);
+
     return siftsMapping;
   }
 
@@ -444,8 +460,8 @@ public class SiftsClient implements SiftsClientI
   public HashMap<Integer, int[]> getGreedyMapping(String entityId,
           SequenceI seq, java.io.PrintStream os) throws SiftsException
   {
-    List<Integer> omitNonObserved = new ArrayList<Integer>();
-    int nonObservedShiftIndex = 0;
+    List<Integer> omitNonObserved = new ArrayList<>();
+    int nonObservedShiftIndex = 0,pdbeNonObserved=0;
     // System.out.println("Generating mappings for : " + entityId);
     Entity entity = null;
     entity = getEntityById(entityId);
@@ -476,7 +492,7 @@ public class SiftsClient implements SiftsClientI
     TreeMap<Integer, String> resNumMap = new TreeMap<Integer, String>();
     List<Segment> segments = entity.getSegment();
     SegmentHelperPojo shp = new SegmentHelperPojo(seq, mapping, resNumMap,
-            omitNonObserved, nonObservedShiftIndex);
+            omitNonObserved, nonObservedShiftIndex,pdbeNonObserved);
     processSegments(segments, shp);
     try
     {
@@ -498,15 +514,61 @@ public class SiftsClient implements SiftsClientI
     {
       throw new SiftsException("SIFTS mapping failed");
     }
+    // also construct a mapping object between the seq-coord sys and the PDB seq's coord sys
 
     Integer[] keys = mapping.keySet().toArray(new Integer[0]);
     Arrays.sort(keys);
     seqStart = keys[0];
     seqEnd = keys[keys.length - 1];
-
+    List<int[]> from=new ArrayList<>(),to=new ArrayList<>();
+    int[]_cfrom=null,_cto=null;
     String matchedSeq = originalSeq;
-    if (seqStart != UNASSIGNED)
+    if (seqStart != UNASSIGNED) // fixme! seqStart can map to -1 for a pdb sequence that starts <-1
     {
+      for (int seqps:keys)
+      {
+        int pdbpos = mapping.get(seqps)[PDBE_POS];
+        if (pdbpos == UNASSIGNED)
+        {
+          // not correct - pdbpos might be -1, but leave it for now
+          continue;
+        }
+        if (_cfrom==null || seqps!=_cfrom[1]+1)
+        {
+          _cfrom = new int[] { seqps,seqps};
+          from.add(_cfrom);
+          _cto = null; // discontinuity
+        } else {
+          _cfrom[1]= seqps;
+        }
+        if (_cto==null || pdbpos!=1+_cto[1])
+        {
+          _cto = new int[] { pdbpos,pdbpos};
+          to.add(_cto);
+        } else {
+          _cto[1] = pdbpos;
+        }
+      }
+      _cfrom = new int[from.size() * 2];
+      _cto = new int[to.size() * 2];
+      int p = 0;
+      for (int[] range : from)
+      {
+        _cfrom[p++] = range[0];
+        _cfrom[p++] = range[1];
+      }
+      ;
+      p = 0;
+      for (int[] range : to)
+      {
+        _cto[p++] = range[0];
+        _cto[p++] = range[1];
+      }
+      ;
+
+      seqFromPdbMapping = new jalview.datamodel.Mapping(null, _cto, _cfrom,
+              1,
+              1);
       pdbStart = mapping.get(seqStart)[PDB_RES_POS];
       pdbEnd = mapping.get(seqEnd)[PDB_RES_POS];
       int orignalSeqStart = seq.getStart();
@@ -559,6 +621,8 @@ public class SiftsClient implements SiftsClientI
     TreeMap<Integer, String> resNumMap = shp.getResNumMap();
     List<Integer> omitNonObserved = shp.getOmitNonObserved();
     int nonObservedShiftIndex = shp.getNonObservedShiftIndex();
+    int pdbeNonObservedCount = shp.getPdbeNonObserved();
+    int firstPDBResNum = UNASSIGNED;
     for (Segment segment : segments)
     {
       // System.out.println("Mapping segments : " + segment.getSegId() + "\\"s
@@ -566,6 +630,9 @@ public class SiftsClient implements SiftsClientI
       List<Residue> residues = segment.getListResidue().getResidue();
       for (Residue residue : residues)
       {
+        boolean isObserved = isResidueObserved(residue);
+        int pdbeIndex = getLeadingIntegerValue(residue.getDbResNum(),
+                UNASSIGNED);
         int currSeqIndex = UNASSIGNED;
         List<CrossRefDb> cRefDbs = residue.getCrossRefDb();
         CrossRefDb pdbRefDb = null;
@@ -574,6 +641,19 @@ public class SiftsClient implements SiftsClientI
           if (cRefDb.getDbSource().equalsIgnoreCase(DBRefSource.PDB))
           {
             pdbRefDb = cRefDb;
+            if (firstPDBResNum == UNASSIGNED)
+            {
+              firstPDBResNum = getLeadingIntegerValue(cRefDb.getDbResNum(),
+                      UNASSIGNED);
+            }
+            else
+            {
+              if (isObserved)
+              {
+                // after we find the first observed residue we just increment
+                firstPDBResNum++;
+              }
+            }
           }
           if (cRefDb.getDbCoordSys().equalsIgnoreCase(seqCoordSys.getName())
                   && isAccessionMatched(cRefDb.getDbAccessionId()))
@@ -586,11 +666,45 @@ public class SiftsClient implements SiftsClientI
             }
           }
         }
+        if (!isObserved)
+        {
+          ++pdbeNonObservedCount;
+        }
+        if (seqCoordSys == seqCoordSys.PDB) // FIXME: is seqCoordSys ever PDBe
+                                            // ???
+        {
+          // if the sequence has a primary reference to the PDB, then we are
+          // dealing with a sequence extracted directly from the PDB. In that
+          // case, numbering is PDBe - non-observed residues
+          currSeqIndex = seq.getStart() - 1 + pdbeIndex;
+        }
+        if (!isObserved)
+        {
+          if (seqCoordSys != CoordinateSys.UNIPROT) // FIXME: PDB or PDBe only
+                                                    // here
+          {
+            // mapping to PDB or PDBe so we need to bookkeep for the
+            // non-observed
+            // SEQRES positions
+            omitNonObserved.add(currSeqIndex);
+            ++nonObservedShiftIndex;
+          }
+        }
         if (currSeqIndex == UNASSIGNED)
         {
+          // change in logic - unobserved residues with no currSeqIndex
+          // corresponding are still counted in both nonObservedShiftIndex and
+          // pdbeIndex...
           continue;
         }
-        if (currSeqIndex >= seq.getStart() && currSeqIndex <= seq.getEnd())
+        // if (currSeqIndex >= seq.getStart() && currSeqIndex <= seqlength) //
+        // true
+                                                                         // numbering
+                                                                         // is
+                                                                         // not
+                                                                         // up
+                                                                         // to
+                                                                         // seq.getEnd()
         {
 
           int resNum = (pdbRefDb == null)
@@ -599,22 +713,18 @@ public class SiftsClient implements SiftsClientI
                   : getLeadingIntegerValue(pdbRefDb.getDbResNum(),
                           UNASSIGNED);
 
-          if (isResidueObserved(residue)
-                  || seqCoordSys == CoordinateSys.UNIPROT)
+          if (isObserved)
           {
             char resCharCode = ResidueProperties
                     .getSingleCharacterCode(ResidueProperties
                             .getCanonicalAminoAcid(residue.getDbResName()));
             resNumMap.put(currSeqIndex, String.valueOf(resCharCode));
+
+            int[] mappingcols = new int[] { Integer.valueOf(resNum),
+                UNASSIGNED, isObserved ? firstPDBResNum : UNASSIGNED };
+
+            mapping.put(currSeqIndex - nonObservedShiftIndex, mappingcols);
           }
-          else
-          {
-            omitNonObserved.add(currSeqIndex);
-            ++nonObservedShiftIndex;
-          }
-          mapping.put(currSeqIndex - nonObservedShiftIndex,
-                  new int[]
-                  { Integer.valueOf(resNum), UNASSIGNED });
         }
       }
     }
@@ -904,17 +1014,36 @@ public class SiftsClient implements SiftsClientI
 
     private int nonObservedShiftIndex;
 
+    /**
+     * count of number of 'not observed' positions in the PDB record's SEQRES
+     * (total number of residues with coordinates == length(SEQRES) -
+     * pdbeNonObserved
+     */
+    private int pdbeNonObserved;
+
     public SegmentHelperPojo(SequenceI seq, HashMap<Integer, int[]> mapping,
             TreeMap<Integer, String> resNumMap,
-            List<Integer> omitNonObserved, int nonObservedShiftIndex)
+            List<Integer> omitNonObserved, int nonObservedShiftIndex,
+            int pdbeNonObserved)
     {
       setSeq(seq);
       setMapping(mapping);
       setResNumMap(resNumMap);
       setOmitNonObserved(omitNonObserved);
       setNonObservedShiftIndex(nonObservedShiftIndex);
+      setPdbeNonObserved(pdbeNonObserved);
+
     }
 
+    public void setPdbeNonObserved(int pdbeNonObserved2)
+    {
+      this.pdbeNonObserved = pdbeNonObserved2;
+    }
+
+    public int getPdbeNonObserved()
+    {
+      return pdbeNonObserved;
+    }
     public SequenceI getSeq()
     {
       return seq;
@@ -964,6 +1093,7 @@ public class SiftsClient implements SiftsClientI
     {
       this.nonObservedShiftIndex = nonObservedShiftIndex;
     }
+
   }
 
   @Override
index 06b51e6..35196fa 100644 (file)
@@ -47,6 +47,7 @@ import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
 import jalview.io.FormatAdapter;
+import jalview.io.gff.SequenceOntologyI;
 import jalview.util.MapList;
 import jalview.util.MappingUtils;
 
@@ -263,14 +264,14 @@ public class AlignmentUtilsTests
   @Test(groups = { "Functional" })
   public void testMapProteinAlignmentToCdna_noXrefs() throws IOException
   {
-    List<SequenceI> protseqs = new ArrayList<SequenceI>();
+    List<SequenceI> protseqs = new ArrayList<>();
     protseqs.add(new Sequence("UNIPROT|V12345", "EIQ"));
     protseqs.add(new Sequence("UNIPROT|V12346", "EIQ"));
     protseqs.add(new Sequence("UNIPROT|V12347", "SAR"));
     AlignmentI protein = new Alignment(protseqs.toArray(new SequenceI[3]));
     protein.setDataset(null);
 
-    List<SequenceI> dnaseqs = new ArrayList<SequenceI>();
+    List<SequenceI> dnaseqs = new ArrayList<>();
     dnaseqs.add(new Sequence("EMBL|A11111", "TCAGCACGC")); // = SAR
     dnaseqs.add(new Sequence("EMBL|A22222", "GAGATACAA")); // = EIQ
     dnaseqs.add(new Sequence("EMBL|A33333", "GAAATCCAG")); // = EIQ
@@ -507,7 +508,7 @@ public class AlignmentUtilsTests
     acf.addMap(dna1.getDatasetSequence(), prot1.getDatasetSequence(), map);
     acf.addMap(dna2.getDatasetSequence(), prot2.getDatasetSequence(), map);
     acf.addMap(dna3.getDatasetSequence(), prot3.getDatasetSequence(), map);
-    ArrayList<AlignedCodonFrame> acfs = new ArrayList<AlignedCodonFrame>();
+    ArrayList<AlignedCodonFrame> acfs = new ArrayList<>();
     acfs.add(acf);
     protein.setCodonFrames(acfs);
 
@@ -605,14 +606,14 @@ public class AlignmentUtilsTests
   public void testMapProteinAlignmentToCdna_withStartAndStopCodons()
           throws IOException
   {
-    List<SequenceI> protseqs = new ArrayList<SequenceI>();
+    List<SequenceI> protseqs = new ArrayList<>();
     protseqs.add(new Sequence("UNIPROT|V12345", "EIQ"));
     protseqs.add(new Sequence("UNIPROT|V12346", "EIQ"));
     protseqs.add(new Sequence("UNIPROT|V12347", "SAR"));
     AlignmentI protein = new Alignment(protseqs.toArray(new SequenceI[3]));
     protein.setDataset(null);
 
-    List<SequenceI> dnaseqs = new ArrayList<SequenceI>();
+    List<SequenceI> dnaseqs = new ArrayList<>();
     // start + SAR:
     dnaseqs.add(new Sequence("EMBL|A11111", "ATGTCAGCACGC"));
     // = EIQ + stop
@@ -697,14 +698,14 @@ public class AlignmentUtilsTests
   @Test(groups = { "Functional" })
   public void testMapProteinAlignmentToCdna_withXrefs() throws IOException
   {
-    List<SequenceI> protseqs = new ArrayList<SequenceI>();
+    List<SequenceI> protseqs = new ArrayList<>();
     protseqs.add(new Sequence("UNIPROT|V12345", "EIQ"));
     protseqs.add(new Sequence("UNIPROT|V12346", "EIQ"));
     protseqs.add(new Sequence("UNIPROT|V12347", "SAR"));
     AlignmentI protein = new Alignment(protseqs.toArray(new SequenceI[3]));
     protein.setDataset(null);
 
-    List<SequenceI> dnaseqs = new ArrayList<SequenceI>();
+    List<SequenceI> dnaseqs = new ArrayList<>();
     dnaseqs.add(new Sequence("EMBL|A11111", "TCAGCACGC")); // = SAR
     dnaseqs.add(new Sequence("EMBL|A22222", "ATGGAGATACAA")); // = start + EIQ
     dnaseqs.add(new Sequence("EMBL|A33333", "GAAATCCAG")); // = EIQ
@@ -774,14 +775,14 @@ public class AlignmentUtilsTests
   public void testMapProteinAlignmentToCdna_prioritiseXrefs()
           throws IOException
   {
-    List<SequenceI> protseqs = new ArrayList<SequenceI>();
+    List<SequenceI> protseqs = new ArrayList<>();
     protseqs.add(new Sequence("UNIPROT|V12345", "EIQ"));
     protseqs.add(new Sequence("UNIPROT|V12346", "EIQ"));
     AlignmentI protein = new Alignment(
             protseqs.toArray(new SequenceI[protseqs.size()]));
     protein.setDataset(null);
 
-    List<SequenceI> dnaseqs = new ArrayList<SequenceI>();
+    List<SequenceI> dnaseqs = new ArrayList<>();
     dnaseqs.add(new Sequence("EMBL|A11111", "GAAATCCAG")); // = EIQ
     dnaseqs.add(new Sequence("EMBL|A22222", "GAAATTCAG")); // = EIQ
     AlignmentI cdna = new Alignment(dnaseqs.toArray(new SequenceI[dnaseqs
@@ -848,8 +849,8 @@ public class AlignmentUtilsTests
     al.addAnnotation(ann4); // Temp for seq1
     al.addAnnotation(ann5); // Temp for seq2
     al.addAnnotation(ann6); // Temp for no sequence
-    List<String> types = new ArrayList<String>();
-    List<SequenceI> scope = new ArrayList<SequenceI>();
+    List<String> types = new ArrayList<>();
+    List<SequenceI> scope = new ArrayList<>();
 
     /*
      * Set all sequence related Structure to hidden (ann1, ann2)
@@ -1747,7 +1748,7 @@ public class AlignmentUtilsTests
     map = new MapList(new int[] { 9, 11 }, new int[] { 2, 2 }, 3, 1);
     acf.addMap(dna3.getDatasetSequence(), prot3.getDatasetSequence(), map);
 
-    ArrayList<AlignedCodonFrame> acfs = new ArrayList<AlignedCodonFrame>();
+    ArrayList<AlignedCodonFrame> acfs = new ArrayList<>();
     acfs.add(acf);
     protein.setCodonFrames(acfs);
 
@@ -2030,9 +2031,9 @@ public class AlignmentUtilsTests
     sf6.setValue("ID", "var6");
     sf6.setValue("clinical_significance", "Good");
 
-    List<DnaVariant> codon1Variants = new ArrayList<DnaVariant>();
-    List<DnaVariant> codon2Variants = new ArrayList<DnaVariant>();
-    List<DnaVariant> codon3Variants = new ArrayList<DnaVariant>();
+    List<DnaVariant> codon1Variants = new ArrayList<>();
+    List<DnaVariant> codon2Variants = new ArrayList<>();
+    List<DnaVariant> codon3Variants = new ArrayList<>();
     List<DnaVariant> codonVariants[] = new ArrayList[3];
     codonVariants[0] = codon1Variants;
     codonVariants[1] = codon2Variants;
@@ -2272,7 +2273,7 @@ public class AlignmentUtilsTests
     seq1.createDatasetSequence();
     Mapping mapping = new Mapping(seq1, new MapList(
             new int[] { 3, 6, 9, 10 }, new int[] { 1, 6 }, 1, 1));
-    Map<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
+    Map<Integer, Map<SequenceI, Character>> map = new TreeMap<>();
     AlignmentUtils.addMappedPositions(seq1, from, mapping, map);
 
     /*
@@ -2304,7 +2305,7 @@ public class AlignmentUtilsTests
     seq1.createDatasetSequence();
     Mapping mapping = new Mapping(seq1, new MapList(
             new int[] { 3, 6, 9, 10 }, new int[] { 1, 6 }, 1, 1));
-    Map<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
+    Map<Integer, Map<SequenceI, Character>> map = new TreeMap<>();
     AlignmentUtils.addMappedPositions(seq1, from, mapping, map);
 
     /*
@@ -2561,7 +2562,7 @@ public class AlignmentUtilsTests
      * Case 2: CDS 3 times length of peptide + stop codon
      * (note code does not currently check trailing codon is a stop codon)
      */
-    dna = new Sequence("dna", "AACGacgtCTCCTTGA");
+    dna = new Sequence("dna", "AACGacgtCTCCTCCC");
     dna.createDatasetSequence();
     dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
     dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 16, null));
@@ -2574,17 +2575,42 @@ public class AlignmentUtilsTests
             Arrays.deepToString(ml.getFromRanges().toArray()));
 
     /*
-     * Case 3: CDS not 3 times length of peptide - no mapping is made
+     * Case 3: CDS longer than 3 * peptide + stop codon - no mapping is made
+     */
+    dna = new Sequence("dna", "AACGacgtCTCCTTGATCA");
+    dna.createDatasetSequence();
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 19, null));
+    ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+    assertNull(ml);
+
+    /*
+     * Case 4: CDS shorter than 3 * peptide - no mapping is made
+     */
+    dna = new Sequence("dna", "AACGacgtCTCC");
+    dna.createDatasetSequence();
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+    dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 12, null));
+    ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+    assertNull(ml);
+
+    /*
+     * Case 5: CDS 3 times length of peptide + part codon - mapping is truncated
      */
     dna = new Sequence("dna", "AACGacgtCTCCTTG");
     dna.createDatasetSequence();
     dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
     dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 15, null));
     ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
-    assertNull(ml);
+    assertEquals(3, ml.getFromRatio());
+    assertEquals(1, ml.getToRatio());
+    assertEquals("[[1, 3]]",
+            Arrays.deepToString(ml.getToRanges().toArray()));
+    assertEquals("[[1, 4], [9, 13]]",
+            Arrays.deepToString(ml.getFromRanges().toArray()));
 
     /*
-     * Case 4: incomplete start codon corresponding to X in peptide
+     * Case 6: incomplete start codon corresponding to X in peptide
      */
     dna = new Sequence("dna", "ACGacgtCTCCTTGG");
     dna.createDatasetSequence();
@@ -2600,4 +2626,151 @@ public class AlignmentUtilsTests
             Arrays.deepToString(ml.getFromRanges().toArray()));
   }
 
+  /**
+   * Tests for the method that locates the CDS sequence that has a mapping to
+   * the given protein. That is, given a transcript-to-peptide mapping, find the
+   * cds-to-peptide mapping that relates to both, and return the CDS sequence.
+   */
+  @Test
+  public void testFindCdsForProtein()
+  {
+    List<AlignedCodonFrame> mappings = new ArrayList<>();
+    AlignedCodonFrame acf1 = new AlignedCodonFrame();
+    mappings.add(acf1);
+
+    SequenceI dna1 = new Sequence("dna1", "cgatATcgGCTATCTATGacg");
+    dna1.createDatasetSequence();
+
+    // NB we currently exclude STOP codon from CDS sequences
+    // the test would need to change if this changes in future
+    SequenceI cds1 = new Sequence("cds1", "ATGCTATCT");
+    cds1.createDatasetSequence();
+
+    SequenceI pep1 = new Sequence("pep1", "MLS");
+    pep1.createDatasetSequence();
+    List<AlignedCodonFrame> seqMappings = new ArrayList<>();
+    MapList mapList = new MapList(
+            new int[]
+            { 5, 6, 9, 15 }, new int[] { 1, 3 }, 3, 1);
+    Mapping dnaToPeptide = new Mapping(pep1.getDatasetSequence(), mapList);
+    
+    // add dna to peptide mapping
+    seqMappings.add(acf1);
+    acf1.addMap(dna1.getDatasetSequence(), pep1.getDatasetSequence(),
+            mapList);
+
+    /*
+     * first case - no dna-to-CDS mapping exists - search fails
+     */
+    SequenceI seq = AlignmentUtils.findCdsForProtein(mappings, dna1,
+            seqMappings, dnaToPeptide);
+    assertNull(seq);
+
+    /*
+     * second case - CDS-to-peptide mapping exists but no dna-to-CDS
+     * - search fails
+     */
+    // todo this test fails if the mapping is added to acf1, not acf2
+    // need to tidy up use of lists of mappings in AlignedCodonFrame
+    AlignedCodonFrame acf2 = new AlignedCodonFrame();
+    mappings.add(acf2);
+    MapList cdsToPeptideMapping = new MapList(new int[]
+    { 1, 9 }, new int[] { 1, 3 }, 3, 1);
+    acf2.addMap(cds1.getDatasetSequence(), pep1.getDatasetSequence(),
+            cdsToPeptideMapping);
+    assertNull(AlignmentUtils.findCdsForProtein(mappings, dna1, seqMappings,
+            dnaToPeptide));
+
+    /*
+     * third case - add dna-to-CDS mapping - CDS is now found!
+     */
+    MapList dnaToCdsMapping = new MapList(new int[] { 5, 6, 9, 15 },
+            new int[]
+            { 1, 9 }, 1, 1);
+    acf1.addMap(dna1.getDatasetSequence(), cds1.getDatasetSequence(),
+            dnaToCdsMapping);
+    seq = AlignmentUtils.findCdsForProtein(mappings, dna1, seqMappings,
+            dnaToPeptide);
+    assertSame(seq, cds1.getDatasetSequence());
+  }
+
+  /**
+   * Tests for the method that locates the CDS sequence that has a mapping to
+   * the given protein. That is, given a transcript-to-peptide mapping, find the
+   * cds-to-peptide mapping that relates to both, and return the CDS sequence.
+   * This test is for the case where transcript and CDS are the same length.
+   */
+  @Test
+  public void testFindCdsForProtein_noUTR()
+  {
+    List<AlignedCodonFrame> mappings = new ArrayList<>();
+    AlignedCodonFrame acf1 = new AlignedCodonFrame();
+    mappings.add(acf1);
+  
+    SequenceI dna1 = new Sequence("dna1", "ATGCTATCTTAA");
+    dna1.createDatasetSequence();
+  
+    // NB we currently exclude STOP codon from CDS sequences
+    // the test would need to change if this changes in future
+    SequenceI cds1 = new Sequence("cds1", "ATGCTATCT");
+    cds1.createDatasetSequence();
+  
+    SequenceI pep1 = new Sequence("pep1", "MLS");
+    pep1.createDatasetSequence();
+    List<AlignedCodonFrame> seqMappings = new ArrayList<>();
+    MapList mapList = new MapList(
+            new int[]
+            { 1, 9 }, new int[] { 1, 3 }, 3, 1);
+    Mapping dnaToPeptide = new Mapping(pep1.getDatasetSequence(), mapList);
+    
+    // add dna to peptide mapping
+    seqMappings.add(acf1);
+    acf1.addMap(dna1.getDatasetSequence(), pep1.getDatasetSequence(),
+            mapList);
+  
+    /*
+     * first case - transcript lacks CDS features - it appears to be
+     * the CDS sequence and is returned
+     */
+    SequenceI seq = AlignmentUtils.findCdsForProtein(mappings, dna1,
+            seqMappings, dnaToPeptide);
+    assertSame(seq, dna1.getDatasetSequence());
+  
+    /*
+     * second case - transcript has CDS feature - this means it is
+     * not returned as a match for CDS (CDS sequences don't have CDS features)
+     */
+    dna1.addSequenceFeature(
+            new SequenceFeature(SequenceOntologyI.CDS, "cds", 1, 12, null));
+    seq = AlignmentUtils.findCdsForProtein(mappings, dna1, seqMappings,
+            dnaToPeptide);
+    assertNull(seq);
+
+    /*
+     * third case - CDS-to-peptide mapping exists but no dna-to-CDS
+     * - search fails
+     */
+    // todo this test fails if the mapping is added to acf1, not acf2
+    // need to tidy up use of lists of mappings in AlignedCodonFrame
+    AlignedCodonFrame acf2 = new AlignedCodonFrame();
+    mappings.add(acf2);
+    MapList cdsToPeptideMapping = new MapList(new int[]
+    { 1, 9 }, new int[] { 1, 3 }, 3, 1);
+    acf2.addMap(cds1.getDatasetSequence(), pep1.getDatasetSequence(),
+            cdsToPeptideMapping);
+    assertNull(AlignmentUtils.findCdsForProtein(mappings, dna1, seqMappings,
+            dnaToPeptide));
+  
+    /*
+     * fourth case - add dna-to-CDS mapping - CDS is now found!
+     */
+    MapList dnaToCdsMapping = new MapList(new int[] { 1, 9 },
+            new int[]
+            { 1, 9 }, 1, 1);
+    acf1.addMap(dna1.getDatasetSequence(), cds1.getDatasetSequence(),
+            dnaToCdsMapping);
+    seq = AlignmentUtils.findCdsForProtein(mappings, dna1, seqMappings,
+            dnaToPeptide);
+    assertSame(seq, cds1.getDatasetSequence());
+  }
 }
index ddba949..266b90a 100644 (file)
@@ -669,6 +669,17 @@ public class AlignmentTest
     // third found.. so
     assertFalse(iter.hasNext());
 
+    // search for annotation on one sequence with a particular label - expect
+    // one
+    SequenceI sqfound;
+    anns = al.findAnnotations(sqfound = al.getSequenceAt(1), null,
+            "Secondary Structure");
+    iter = anns.iterator();
+    assertTrue(iter.hasNext());
+    // expect reference to sequence 1 in the alignment
+    assertTrue(sqfound == iter.next().sequenceRef);
+    assertFalse(iter.hasNext());
+
     // null on all parameters == find all annotations
     anns = al.findAnnotations(null, null, null);
     iter = anns.iterator();
@@ -1323,6 +1334,24 @@ public class AlignmentTest
     // hidden sequences, properties
   }
 
+  /**
+   * test that calcId == null on findOrCreate doesn't raise an NPE, and yields
+   * an annotation with a null calcId
+   * 
+   */
+  @Test(groups = "Functional")
+  public void testFindOrCreateForNullCalcId()
+  {
+    SequenceI seq = new Sequence("seq1", "FRMLPSRT-A--L-");
+    AlignmentI alignment = new Alignment(new SequenceI[] { seq });
+
+    AlignmentAnnotation ala = alignment.findOrCreateAnnotation(
+            "Temperature Factor", null, false, seq, null);
+    assertNotNull(ala);
+    assertEquals(seq, ala.sequenceRef);
+    assertEquals("", ala.calcId);
+  }
+
   @Test(groups = "Functional")
   public void testPropagateInsertions()
   {
index 1b1a2b4..217742d 100644 (file)
@@ -25,6 +25,7 @@ import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.api.FeatureSettingsModelI;
+import jalview.bin.Cache;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -53,6 +54,7 @@ public class EnsemblGeneTest
   @BeforeClass(alwaysRun = true)
   public void setUp()
   {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
     SequenceOntologyFactory.setInstance(new SequenceOntologyLite());
   }
 
index 3309adf..e42b54f 100644 (file)
@@ -115,7 +115,7 @@ public class JmolCommandsTest
     String chainACommand = commands[0].commands[0];
     // M colour is #82827d == (130, 130, 125) (see strand.html help page)
     assertTrue(chainACommand
-            .contains(";select 21:A/1.1;color[130,130,125]"));
+            .contains("select 21:A/1.1;color[130,130,125]")); // first one
     // H colour is #60609f == (96, 96, 159)
     assertTrue(chainACommand.contains(";select 22:A/1.1;color[96,96,159]"));
     // hidden columns are Gray (128, 128, 128)
@@ -128,7 +128,7 @@ public class JmolCommandsTest
     String chainBCommand = commands[1].commands[0];
     // M colour is #82827d == (130, 130, 125)
     assertTrue(chainBCommand
-            .contains(";select 21:B/2.1;color[130,130,125]"));
+            .contains("select 21:B/2.1;color[130,130,125]"));
     // V colour is #ffff00 == (255, 255, 0)
     assertTrue(chainBCommand
 .contains(";select 22:B/2.1;color[255,255,0]"));
index e14a478..c0038a1 100644 (file)
@@ -39,6 +39,7 @@ import jalview.structure.StructureImportSettings.StructureParser;
 import java.io.File;
 import java.util.List;
 
+import org.junit.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
@@ -101,18 +102,19 @@ public class AnnotatedPDBFileInputTest
     }
   }
 
-  @Test(groups = { "Functional" })
+  @Test(groups = { "Functional" }, enabled = false)
   public void checkPDBannotationSource()
   {
-
+    Assert.fail(
+            "This test is incorrect - does not verify that JmolParser's annotation rows can be recognised as generated by the Jmol parser.");
     for (SequenceI asq : al.getSequences())
     {
       for (AlignmentAnnotation aa : asq.getAnnotation())
       {
 
         System.out.println("CalcId: " + aa.getCalcId());
-        if (StructureImportSettings.getDefaultPDBFileParser().equals(
-                StructureParser.JALVIEW_PARSER))
+        if (StructureImportSettings.getDefaultPDBFileParser()
+                .equals(StructureParser.JALVIEW_PARSER))
         {
           assertTrue(MCview.PDBfile.isCalcIdForFile(aa, pdbId));
         }
index 15e18e3..fbdd782 100644 (file)
@@ -76,7 +76,8 @@ public class Jalview2xmlBase
   @BeforeTest(alwaysRun = true)
   public static void clearDesktop()
   {
-    if (Desktop.instance != null && Desktop.getAlignFrames() != null)
+    if (Desktop.instance != null && Desktop.getFrames() != null
+            && Desktop.getFrames().length > 0)
     {
       Desktop.instance.closeAll_actionPerformed(null);
     }
index a59fbde..286be1b 100644 (file)
  */
 package jalview.structure;
 
+import static org.junit.Assert.assertArrayEquals;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.analysis.AlignmentUtils;
+import jalview.api.structures.JalviewStructureDisplayI;
+import jalview.bin.Cache;
 import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.ext.jmol.JmolCommands;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
+import jalview.gui.SequenceRenderer;
+import jalview.gui.StructureChooser;
 import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.io.Jalview2xmlBase;
 import jalview.io.StructureFile;
 import jalview.util.MapList;
+import jalview.ws.DBRefFetcher;
+import jalview.ws.sifts.SiftsSettings;
 
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
 
+import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
-public class StructureSelectionManagerTest
+@Test(singleThreaded = true)
+public class StructureSelectionManagerTest extends Jalview2xmlBase
 {
 
+  @Override
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
   {
@@ -160,4 +185,313 @@ public class StructureSelectionManagerTest
     assertEquals("1gaq", sf.getFeatureGroup());
     assertEquals("ALA:   1  1gaqB", sf.getDescription());
   }
+
+  /**
+   * Verify that RESNUM sequence features are present after creating a PDB
+   * mapping from a local file, then that everything stays in the same place
+   * when the file is viewed. The corner case is that 4IM2 is a fragment of a
+   * PDB file, which still includes the 'ID' field - a bug in Jalview 2.10.3
+   * causes features, annotation and positions to be remapped to the wrong place
+   * on viewing the structure
+   */
+  @Test(groups = { "Network" })
+  public void testMapping_EqualsFeatures()
+  {
+    // for some reason 'BeforeMethod' (which should be inherited from
+    // Jalview2XmlBase isn't always called)...
+    Desktop.instance.closeAll_actionPerformed(null);
+    try { 
+      Thread.sleep(200);
+    } catch (Exception foo) {}; 
+    SequenceI seq = new Sequence("4IM2|A",
+            "LDFCIRNIEKTVMGEISDIHTKLLRLSSSQGTIE");
+    String P4IM2_MISSING = "examples/testdata/4IM2_missing.pdb";
+    StructureSelectionManager sm = new StructureSelectionManager();
+    sm.setProcessSecondaryStructure(true);
+    sm.setAddTempFacAnnot(true);
+    StructureFile pmap = sm.setMapping(true, new SequenceI[] { seq },
+            new String[]
+            { null }, P4IM2_MISSING,
+            DataSourceType.FILE);
+    assertTrue(pmap != null);
+
+    assertEquals(1, pmap.getSeqs().size());
+    assertEquals("4IM2|A", pmap.getSeqs().get(0).getName());
+
+    List<int[]> structuremap1 = new ArrayList(
+            sm.getMapping(P4IM2_MISSING)[0]
+                    .getPDBResNumRanges(seq.getStart(), seq.getEnd()));
+
+    /*
+     * Verify a RESNUM sequence feature in the PDBfile sequence
+     * LEU468 - start+0 
+     * VAL479 - start+11
+     * MET486 - start+12
+     * GLY496 - start+13
+     * GLU516 - start+33 (last)
+     * 
+     * Expect features and mapping to resolve to same residues.
+     * Also try creating a view and test again
+     *   
+     */
+    String[] feats = new String[] { "LEU", "468", "VAL", "479", "MET",
+        "486", "GLY", "496", "GLU", "516" };
+    int[] offset = new int[] { 0, 11, 12, 13, 33 };
+
+    List<String> fdesc = new ArrayList<>();
+    for (int f = 0; f < feats.length; f += 2)
+    {
+      fdesc.add(feats[f] + ": " + feats[f + 1] + "  4im2A");
+    }
+    SequenceI pdbseq = pmap.getSeqs().get(0);
+    verifySeqFeats(pdbseq, offset, fdesc);
+
+    /// Now load as a view
+
+    AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded(
+            "examples/testdata/4IM2_missing.pdb", DataSourceType.FILE);
+    Desktop.addInternalFrame(alf, "examples/testdata/4IM2_missing.pdb", 800,
+            400);
+    AlignmentI pdbal = alf.getViewport().getAlignment();
+    SequenceI pdb_viewseq = pdbal.getSequenceAt(0);
+    assertEquals(pdb_viewseq.getSequenceAsString(),
+            seq.getSequenceAsString());
+    // verify the feature location on the sequence when pdb imported as an
+    // alignment
+    verifySeqFeats(pdb_viewseq, offset, fdesc);
+
+
+    JalviewStructureDisplayI viewr = openStructureViaChooser(alf,
+            pdb_viewseq, "4IM2");
+
+    // and check all is good with feature location still
+    verifySeqFeats(pdb_viewseq, offset, fdesc);
+
+    // finally check positional mapping for sequence and structure
+    PDBEntry pdbe = seq.getPDBEntry("4IM2");
+    StructureSelectionManager apssm = alf.alignPanel
+            .getStructureSelectionManager();
+    StructureMapping[] smap = apssm
+            .getMapping(pdbe.getFile());
+    assertNotNull(smap);
+    assertNotNull(smap[0]);
+    // find the last position in the alignment sequence - this is not
+    // 'SequenceI.getEnd()' - which gets the last PDBRESNUM rather than
+    // SequenceI.getStart() + number of residues in file...
+    int realSeqEnd = pdb_viewseq.findPosition(pdb_viewseq.getLength());
+    List<int[]> ranges = smap[0].getPDBResNumRanges(pdb_viewseq.getStart(),
+            realSeqEnd);
+    assertEquals(structuremap1.size(), ranges.size());
+    int tot_mapped = 0;
+    for (int p = 0; p < ranges.size(); p++)
+    {
+      assertArrayEquals(structuremap1.get(p), ranges.get(p));
+      tot_mapped += 1 + (structuremap1.get(p)[1] - structuremap1.get(p)[0]);
+    }
+
+    assertEquals(pdb_viewseq.getLength(), tot_mapped);
+
+    int lastmappedp = StructureMapping.UNASSIGNED_VALUE;
+    for (int rp = pdb_viewseq.getStart(), rpEnd = pdb_viewseq
+            .findPosition(pdb_viewseq.getLength() - 1); rp <= rpEnd; rp++)
+    {
+      int mappedp = smap[0].getPDBResNum(rp);
+      if (mappedp != StructureMapping.UNASSIGNED_VALUE)
+      {
+        tot_mapped--;
+        if (lastmappedp == mappedp)
+        {
+          Assert.fail("Duplicate mapped position at " + rp + " (dupe = "
+                  + mappedp + ")");
+        }
+      }
+    }
+
+    Assert.assertEquals(tot_mapped, 0,
+            "Different number of mapped residues compared to ranges of mapped residues");
+
+    // positional mapping to atoms for color by structure is still wrong, even
+    // though panel looks correct.
+
+    StructureMappingcommandSet smcr[] = JmolCommands
+            .getColourBySequenceCommand(apssm,
+            new String[]
+            { pdbe.getFile() },
+            new SequenceI[][]
+            { new SequenceI[] { pdb_viewseq } },
+                    new SequenceRenderer(alf.alignPanel.getAlignViewport()),
+                    alf.alignPanel);
+    // Expected - all residues are white
+    for (StructureMappingcommandSet smm : smcr)
+    {
+      for (String c : smm.commands)
+      {
+        System.out.println(c);
+      }
+    }
+  }
+
+  private void verifySeqFeats(SequenceI pdbseq, int[] offset,
+          List<String> fdesc)
+  {
+    for (int o = 0; o < offset.length; o++)
+    {
+      int res = pdbseq.findPosition(offset[o]);
+      List<SequenceFeature> sf = pdbseq.getFeatures().findFeatures(res, res,
+              "RESNUM");
+      assertEquals("Expected sequence feature at position " + res + "("
+              + offset[o] + ")", 1, sf.size());
+      assertEquals("Wrong description at " + res + "(" + offset[o] + ")",
+              fdesc.get(o), sf.get(0).getDescription());
+    }
+
+  }
+
+  @Test(groups = { "Network" })
+  public void testAssociatedMappingToSubSeq() throws Exception
+  {
+
+    // currently this test fails if trimming is enabled
+    Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
+            Boolean.FALSE.toString());
+    String TEMP_FACTOR_AA="Temperature Factor";
+    String PDBID = "4IM2";
+    String FullLengthSeq = ">TBK1_HUMAN Serine/threonine-protein kinase TBK1\n" + 
+            "MQSTSNHLWLLSDILGQGATANVFRGRHKKTGDLFAIKVFNNISFLRPVDVQMREFEVLKKLNHKNIVKLFA\n" + 
+            "IEEETTTRHKVLIMEFCPCGSLYTVLEEPSNAYGLPESEFLIVLRDVVGGMNHLRENGIVHRDIKPGNIMRV\n" + 
+            "IGEDGQSVYKLTDFGAARELEDDEQFVSLYGTEEYLHPDMYERAVLRKDHQKKYGATVDLWSIGVTFYHAAT\n" + 
+            "GSLPFRPFEGPRRNKEVMYKIITGKPSGAISGVQKAENGPIDWSGDMPVSCSLSRGLQVLLTPVLANILEAD\n" + 
+            "QEKCWGFDQFFAETSDILHRMVIHVFSLQQMTAHKIYIHSYNTATIFHELVYKQTKIISSNQELIYEGRRLV\n" + 
+            "LEPGRLAQHFPKTTEENPIFVVSREPLNTIGLIYEKISLPKVHPRYDLDGDASMAKAITGVVCYACRIASTL\n" + 
+            "LLYQELMRKGIRWLIELIKDDYNETVHKKTEVVITLDFCIRNIEKTVKVYEKLMKINLEAAELGEISDIHTK\n" + 
+            "LLRLSSSQGTIETSLQDIDSRLSPGGSLADAWAHQEGTHPKDRNVEKLQVLLNCMTEIYYQFKKDKAERRLA\n" + 
+            "YNEEQIHKFDKQKLYYHATKAMTHFTDECVKKYEAFLNKSEEWIRKMLHLRKQLLSLTNQCFDIEEEVSKYQ\n" + 
+            "EYTNELQETLPQKMFTASSGIKHTMTPIYPSSNTLVEMTLGMKKLKEEMEGVVKELAENNHILERFGSLTMD\n" + 
+            "GGLRNVDCL";
+    /*
+     * annotation exported after importing full length sequence to desktop, opening 4IM2 and selecting 'Add Reference Annotation'.
+     * 
+     * Note - tabs must be replaced with \t - Eclipse expands them to spaces otherwise.
+     */
+    String FullLengthAnnot = "JALVIEW_ANNOTATION\n" + 
+            "# Created: Mon Feb 05 15:30:20 GMT 2018\n" + 
+            "# Updated: Fri Feb 09 17:05:17 GMT 2018\n" + 
+            "\n" + 
+            "\n" + 
+            "SEQUENCE_REF\tTBK1_HUMAN\n"
+            + "LINE_GRAPH\tTemperature Factor\tTemperature Factor for 4im2A\t125.22|128.51|120.35|113.12|122.6|114.44|91.49|102.53|98.22|111.41|111.32|116.64|103.55|100.53|95.07|105.55|114.76|128.29|133.55|142.14|121.12|110.36|95.79|95.39|87.14|99.56|93.55|94.21|100.33|110.68|97.85|82.37|75.87|76.53|77.85|82.49|80.92|96.88|122.58|133.31|160.15|180.51|||||242.88|258.97|247.01|227.12|223.24|211.62|184.65|183.51|168.96|160.04|150.88|131.68|130.43|139.87|148.59|136.57|125.7|96.51|74.49|74.08|85.87|70.93|86.47|101.59|97.51|97.39|117.19|114.27|129.5|112.98|147.52|170.26|154.98|168.18|157.51|131.95|105.85|97.78|97.35|76.51|76.31|72.55|71.43|78.82|79.94|75.04|79.54|77.95|83.56|88.5|71.51|71.73|75.96|82.36|81.75|66.51|67.23|69.35|67.92|54.75|71.19|61.85|65.34|67.97|64.51|67.41|62.28|72.85|72.76|70.64|65.23|71.07|67.73|87.72|64.93|75.92|94.02|99.35|93.71|103.59|106.29|115.46|118.69|147.18|130.62|171.64|158.95|164.11||107.42|88.53|83.52|88.06|94.06|80.82|59.01|59.73|78.89|69.21|70.34|81.95|74.53|60.92|64.65|55.79|75.71|68.86|70.95|75.08|87.76|85.43|105.84|||||||||||||||||137.46|151.33|145.17|122.79|111.56|126.72|124.06|161.75|176.84|180.51|198.49|196.75|187.41||195.23|202.27|203.16|226.55|221.75|193.83||||||172.33|177.97|151.47|132.65|99.22|93.7|91.15|88.24|72.35|70.05|70.0|74.92|66.51|68.37|65.76|70.12|74.97|76.89|80.83|70.21|69.48|79.54|82.65|96.54|114.31|140.46|168.51|176.99|205.08|209.27|155.83|139.41|151.3|129.33|111.31|119.62|121.37|102.26|115.39|129.97|128.65|110.38|110.66|116.1|82.53|84.02|82.17|87.63|86.42|77.23|91.23|95.53|102.21|120.73|133.26|109.67|108.49|93.25|92.85|86.39|95.66|94.92|85.82|80.13|76.17|86.61|78.9|77.97|105.6|70.66|69.35|78.94|66.68|63.03|69.91|79.05|75.43|70.73|70.02|80.57|81.74|77.99|84.1|91.66|92.42|94.03|116.47|132.01|154.55|163.99|161.37|155.23|132.78|109.3|90.38|101.83|99.61|91.68|82.77|86.12|82.73|90.13|85.14|79.54|74.27|74.06|72.88|86.34|72.0|69.32|60.9|68.15|52.99|63.53|61.3|66.01|68.28|77.41|71.52|67.18|66.17|71.51|65.47|52.63|65.08|66.37|73.76|77.79|67.58|79.53|84.75|87.42|78.9|79.19|85.57|73.67|80.56|86.19|72.17|66.27|72.8|86.28|78.89|74.5|90.6|80.42|92.5|92.84|96.18|92.08|88.5|87.25|64.6|68.95|65.56|67.55|71.62|78.24|84.95|71.35|86.41|84.73|94.41|95.09|84.74|87.64|88.85|75.1|86.42|79.28|73.14|78.54|80.81|60.66|67.93|71.64|59.85|64.7|61.22|63.84|65.9|62.18|74.95|72.92|93.37|90.47|96.0|93.8|88.46|79.78|83.4|66.55|68.7|73.2|78.76|85.67|84.8|89.59|96.52|79.53|103.51|134.72|126.7|145.31|156.17|149.35|128.48|117.29|118.98|131.59|109.36|90.39|87.68|91.81|78.77|80.11|91.39|75.57|78.98|71.53|76.85|70.9|64.71|73.55|73.45|60.0|69.92|57.89|69.07|66.45|62.85|57.83|57.89|66.4|61.61|60.85|66.47|63.53|63.84|65.96|73.06|70.82|64.51|63.66|73.37|73.59|68.09|78.93|76.99|75.05|71.32|88.4|78.88|93.08|110.61|94.32|99.24|128.99|129.49|132.74|124.21|120.32|142.06|166.41|149.87|153.29|172.19|165.89|181.6|223.11|237.73|176.41|171.09|189.65|188.61|154.84|142.72|154.25|170.99|175.65|||||||110.61||||||||||158.07|170.73|167.93|198.47|212.36|181.71|157.69|163.31|138.96|120.29|131.63|152.26|125.06|136.66|148.97|129.68|120.52|135.31|136.05|119.39|124.18|128.94|123.02|103.37|128.44|134.12|118.88|120.94|130.38|124.67|112.21|113.69|123.65|132.06|114.97|110.75|92.38|101.2|103.25|94.84|85.3|82.19|89.81|98.81|83.03|68.91|65.24|70.31|63.49|86.38|71.07|62.65|63.95|66.98|58.06|68.28|62.11|63.86|67.4|68.69|69.57|68.03|74.23|75.66|70.67|81.08|81.31|82.49|88.15|95.99|92.97|100.01|113.18|122.37|110.99|122.19|159.27|147.74|133.96|111.2|115.64|126.55|107.15|102.85|117.06|116.56|109.55|96.82|98.92|96.53|86.0|88.11|92.76|85.77|79.41|93.06|86.96|76.35|72.37|74.19|68.6|67.46|74.47|76.25|66.73|73.18|75.2|88.21|84.93|75.04|71.09|82.6|80.03|76.22|75.76|83.72|75.85|79.36|90.35|86.9|78.24|95.64|97.38|86.41|85.02|91.87|87.36|77.56|81.25|91.66|83.65|77.67|85.07|89.21|92.66|92.46|89.0|100.83|96.71|94.81|101.37|111.28|124.48|119.73|127.81|134.41|132.4|140.32|140.86|166.52|160.16|168.39|176.74|174.63|172.86|168.55|155.9|132.71|113.44|113.49|123.9|151.11|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n"
+            + 
+            "\n" + 
+            "";
+    AlignFrame alf_full=new
+     FileLoader(false).LoadFileWaitTillLoaded(FullLengthSeq,DataSourceType.PASTE);
+    alf_full.loadJalviewDataFile(FullLengthAnnot, DataSourceType.PASTE, null, null);
+    AlignmentI al_full = alf_full.getViewport().getAlignment();
+    AlignmentAnnotation fullseq_tf = al_full.findAnnotations(al_full.getSequences().get(0), null, TEMP_FACTOR_AA).iterator()
+            .next();
+    assertNotNull(fullseq_tf);
+    
+    // getMappingFor
+    // AlignmentI al_full=alf_full.getViewport().getAlignment();
+    //
+    // // load 4IM2 (full length, SIFTS onto full alingnment)
+    // SiftsSettings.setMapWithSifts(true);
+    // StructureChooser schoose = new StructureChooser(selectedSeqs_full,
+    // seq_full,
+    // alf_full.getViewport().getAlignPanel());
+    // schoose.selectStructure(PDBID);
+    // schoose.ok_ActionPerformed();
+
+    AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded(
+            ">TBK1_HUMAN/470-502 Serine/threonine-protein kinase TBK1\nFCIRNIEKTVKVYEKLMKINLEAAELGEISDIH",
+            DataSourceType.PASTE);
+    Desktop.addInternalFrame(alf, "Foo", 800, 600);
+    ;
+    AlignmentI al = alf.getViewport().getAlignment();
+    SequenceI seq = al.getSequenceAt(0);
+    assertEquals(470, seq.getStart());
+    // load 4IM2 (full length, SIFTS)
+    SiftsSettings.setMapWithSifts(true);
+    StructureImportSettings.setProcessSecondaryStructure(true);
+    StructureImportSettings.setVisibleChainAnnotation(true);
+    JalviewStructureDisplayI sview = openStructureViaChooser(alf, seq,
+            PDBID);
+
+    AlignmentAnnotation subseq_tf=null;
+    assertTrue(seq.getDBRefs() != null && seq.getDBRefs().length > 0);
+    
+    if (!al.findAnnotations(seq, null, TEMP_FACTOR_AA).iterator().hasNext())
+    {
+      // FIXME JAL-2321 - don't see reference annotation on alignment the first
+      // time
+      // around
+      SortedMap<String, String> tipEntries = new TreeMap<>();
+      final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
+
+      AlignmentUtils.findAddableReferenceAnnotations(al.getSequences(),
+              tipEntries, candidates, al);
+      AlignmentUtils.addReferenceAnnotations(candidates, al, null);
+
+      if (!al.findAnnotations(seq, null, TEMP_FACTOR_AA).iterator()
+              .hasNext())
+      {
+        Assert.fail(
+                "JAL-2321 or worse has occured. No secondary structure added to alignment.");
+      }
+    }
+    subseq_tf = al.findAnnotations(seq, null, TEMP_FACTOR_AA).iterator()
+            .next();
+    // verify against annotation after loading 4IM2 to full length TBK1_HUMAN
+    // verify location of mapped residues
+    // verify location of secondary structure annotation
+    // Specific positions: LYS477 (h),THR478 (no helix), ... GLY496(no helix),
+    // GLU497 (helix),
+    
+    // check there is or is not a tempfactor for each mapped position, and that
+    // values are equal for those positions.
+    for (int p=seq.getStart();p<=seq.getEnd();p++)
+    {
+      Annotation orig,subseq;
+      orig = fullseq_tf.getAnnotationForPosition(p);
+      subseq = subseq_tf.getAnnotationForPosition(p);
+      if (orig == null)
+      {
+        Assert.assertNull(subseq,
+                "Expected no annotation transferred at position " + p);
+      }
+      ;
+      if (orig != null)
+      {
+        Assert.assertNotNull(subseq,
+                "Expected annotation transfer at position " + p);
+        assertEquals(orig.value, subseq.value);
+      }
+      ;
+
+    }
+  }
+
+  private JalviewStructureDisplayI openStructureViaChooser(AlignFrame alf,
+          SequenceI seq,
+          String pDBID)
+  {
+
+    SequenceI[] selectedSeqs = new SequenceI[] { seq };
+
+    StructureChooser schoose = new StructureChooser(selectedSeqs, seq,
+            alf.getViewport().getAlignPanel());
+
+    try
+    {
+      Thread.sleep(5000);
+    } catch (InterruptedException q)
+    {
+    }
+    ;
+    Assert.assertTrue(schoose.selectStructure(pDBID),
+            "Couldn't select structure via structure chooser: " + pDBID);
+    schoose.showStructures(true);
+    return schoose.getOpenedStructureViewer();
+  }
+
 }
index 95863e7..cc3dca8 100644 (file)
  */
 package jalview.ws;
 
+import static org.testng.Assert.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.bin.Cache;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
 import jalview.structure.StructureImportSettings;
 import jalview.structure.StructureImportSettings.StructureParser;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
+import java.util.Arrays;
 import java.util.List;
 
+import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -106,23 +110,76 @@ public class PDBSequenceFetcherTest
     testRetrieveProteinSeqFromPDB();
   }
 
+  private class TestRetrieveObject
+  {
+    String id;
+
+    int expectedHeight;
+
+    public TestRetrieveObject(String id, int expectedHeight)
+    {
+      super();
+      this.id = id;
+      this.expectedHeight = expectedHeight;
+    }
+
+  }
+
+  private List<TestRetrieveObject> toRetrieve = Arrays.asList(
+          new TestRetrieveObject("1QIP", 4),
+          new TestRetrieveObject("4IM2", 1));
+
   private void testRetrieveProteinSeqFromPDB() throws Exception
   {
     List<DbSourceProxy> sps = sf.getSourceProxy("PDB");
-    AlignmentI response = sps.get(0).getSequenceRecords("1QIP");
-    assertTrue(response != null);
-    assertTrue(response.getHeight() == 4);
-    for (SequenceI sq : response.getSequences())
+    StringBuilder errors = new StringBuilder();
+    for (TestRetrieveObject str : toRetrieve)
     {
-      assertTrue("No annotation transfered to sequence.",
-              sq.getAnnotation().length > 0);
-      assertTrue("No PDBEntry on sequence.",
-              sq.getAllPDBEntries().size() > 0);
-      org.testng.Assert
-              .assertEquals(sq.getEnd() - sq.getStart() + 1,
-                      sq.getLength(),
-                      "Sequence start/end doesn't match number of residues in sequence");
+      AlignmentI response = sps.get(0).getSequenceRecords(str.id);
+      assertTrue("No aligment for " + str.id, response != null);
+      assertEquals(response.getHeight(), str.expectedHeight,
+              "Number of chains for " + str.id);
+      for (SequenceI sq : response.getSequences())
+      {
+        assertTrue("No annotation transfered to sequence " + sq.getName(),
+                sq.getAnnotation().length > 0);
+        assertTrue("No PDBEntry on sequence " + sq.getName(),
+                sq.getAllPDBEntries().size() > 0);
+        // FIXME: should test that all residues extracted as sequences from
+        // chains in structure have a mapping to data in the structure
+        List<SequenceFeature> prev = null;
+        int lastp = -1;
+        for (int col = 1; col <= sq.getLength(); col++)
+        {
+          List<SequenceFeature> sf = sq.findFeatures(col, col, "RESNUM");
+          if (sf.size() != 1)
+          {
+            errors.append(
+                    str.id + ": " +
+                            "Expected one feature at column (position): "
+                            + (col - 1)
+                            + " (" + sq.findPosition(col - 1) + ")"
+                            + ": saw "
+                            + sf.size());
+            errors.append("\n");
+            if (prev != null)
+            {
+              errors.append("Last Feature was at position " + lastp + ": "
+                      + prev.get(0).toString());
+              errors.append("\n");
+            }
+          }
+          else
+          {
+            prev = sf;
+            lastp = sq.findPosition(col - 1);
+          }
+        }
+      }
+    }
+    if (errors.length() > 0)
+    {
+      Assert.fail(errors.toString());
     }
   }
-
 }
diff --git a/test/jalview/ws/dbsources/PfamFullTest.java b/test/jalview/ws/dbsources/PfamFullTest.java
new file mode 100644 (file)
index 0000000..d675fbe
--- /dev/null
@@ -0,0 +1,30 @@
+package jalview.ws.dbsources;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.bin.Cache;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class PfamFullTest
+{
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+  }
+
+  @Test(groups = "Functional")
+  public void testGetURL()
+  {
+    // with default value for domain
+    String url = new PfamFull().getURL(" abc ");
+    assertEquals(url, "http://pfam.xfam.org/family/ABC/alignment/full");
+
+    // with override in properties
+    Cache.setProperty("PFAM_DOMAIN", "https://pfam.xfam.org");
+    url = new PfamFull().getURL(" abc ");
+    assertEquals(url, "https://pfam.xfam.org/family/ABC/alignment/full");
+  }
+}
diff --git a/test/jalview/ws/dbsources/PfamSeedTest.java b/test/jalview/ws/dbsources/PfamSeedTest.java
new file mode 100644 (file)
index 0000000..537c97e
--- /dev/null
@@ -0,0 +1,30 @@
+package jalview.ws.dbsources;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.bin.Cache;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class PfamSeedTest
+{
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+  }
+
+  @Test(groups = "Functional")
+  public void testGetURL()
+  {
+    // with default value for domain
+    String url = new PfamSeed().getURL(" abc ");
+    assertEquals(url, "http://pfam.xfam.org/family/ABC/alignment/seed");
+
+    // with override in properties
+    Cache.setProperty("PFAM_DOMAIN", "https://pfam.xfam.org");
+    url = new PfamSeed().getURL(" abc ");
+    assertEquals(url, "https://pfam.xfam.org/family/ABC/alignment/seed");
+  }
+}
diff --git a/test/jalview/ws/dbsources/RfamFullTest.java b/test/jalview/ws/dbsources/RfamFullTest.java
new file mode 100644 (file)
index 0000000..344aee6
--- /dev/null
@@ -0,0 +1,30 @@
+package jalview.ws.dbsources;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.bin.Cache;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class RfamFullTest
+{
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+  }
+
+  @Test(groups = "Functional")
+  public void testGetURL()
+  {
+    // with default value for domain
+    String url = new RfamFull().getURL(" abc ");
+    assertEquals(url, "http://rfam.xfam.org/family/ABC/alignment/full");
+
+    // with override in properties
+    Cache.setProperty("RFAM_DOMAIN", "https://rfam.xfam.org");
+    url = new RfamFull().getURL(" abc ");
+    assertEquals(url, "https://rfam.xfam.org/family/ABC/alignment/full");
+  }
+}
diff --git a/test/jalview/ws/dbsources/RfamSeedTest.java b/test/jalview/ws/dbsources/RfamSeedTest.java
new file mode 100644 (file)
index 0000000..e45fff1
--- /dev/null
@@ -0,0 +1,32 @@
+package jalview.ws.dbsources;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.bin.Cache;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class RfamSeedTest
+{
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+  }
+
+  @Test(groups = "Functional")
+  public void testGetURL()
+  {
+    // with default value for domain
+    String url = new RfamSeed().getURL(" abc ");
+    assertEquals(url,
+            "http://rfam.xfam.org/family/ABC/alignment/stockholm");
+
+    // with override in properties
+    Cache.setProperty("RFAM_DOMAIN", "https://rfam.xfam.org");
+    url = new RfamSeed().getURL(" abc ");
+    assertEquals(url,
+            "https://rfam.xfam.org/family/ABC/alignment/stockholm");
+  }
+}
index 573022d..51cff6e 100644 (file)
@@ -58,7 +58,7 @@ public class XfamFetcherTest
   @Test(groups = { "External" })
   public void testPfamFullAndSeed() throws Exception
   {
-    PfamFull pff = new PfamFull();
+    Pfam pff = new PfamFull();
     PfamSeed pfseed = new PfamSeed();
 
     AlignmentI fullpf = pff.getSequenceRecords(pff.getTestQuery());
index b92766e..75c1413 100644 (file)
@@ -83,103 +83,103 @@ public class SiftsClientTest
   @BeforeTest(alwaysRun = true)
   public void populateExpectedMapping() throws SiftsException
   {
-    expectedMapping.put(51, new int[] { 1, 2 });
-    expectedMapping.put(52, new int[] { 2, 7 });
-    expectedMapping.put(53, new int[] { 3, 12 });
-    expectedMapping.put(54, new int[] { 4, 24 });
-    expectedMapping.put(55, new int[] { 5, 33 });
-    expectedMapping.put(56, new int[] { 6, 40 });
-    expectedMapping.put(57, new int[] { 7, 47 });
-    expectedMapping.put(58, new int[] { 8, 55 });
-    expectedMapping.put(59, new int[] { 9, 62 });
-    expectedMapping.put(60, new int[] { 10, 69 });
-    expectedMapping.put(61, new int[] { 11, 76 });
-    expectedMapping.put(62, new int[] { 12, 83 });
-    expectedMapping.put(63, new int[] { 13, 87 });
-    expectedMapping.put(64, new int[] { 14, 95 });
-    expectedMapping.put(65, new int[] { 15, 102 });
-    expectedMapping.put(66, new int[] { 16, 111 });
-    expectedMapping.put(67, new int[] { 17, 122 });
-    expectedMapping.put(68, new int[] { 18, 131 });
-    expectedMapping.put(69, new int[] { 19, 137 });
-    expectedMapping.put(70, new int[] { 20, 144 });
-    expectedMapping.put(71, new int[] { 21, 152 });
-    expectedMapping.put(72, new int[] { 22, 160 });
-    expectedMapping.put(73, new int[] { 23, 167 });
-    expectedMapping.put(74, new int[] { 24, 179 });
-    expectedMapping.put(75, new int[] { 25, 187 });
-    expectedMapping.put(76, new int[] { 26, 195 });
-    expectedMapping.put(77, new int[] { 27, 203 });
-    expectedMapping.put(78, new int[] { 28, 208 });
-    expectedMapping.put(79, new int[] { 29, 213 });
-    expectedMapping.put(80, new int[] { 30, 222 });
-    expectedMapping.put(81, new int[] { 31, 231 });
-    expectedMapping.put(82, new int[] { 32, 240 });
-    expectedMapping.put(83, new int[] { 33, 244 });
-    expectedMapping.put(84, new int[] { 34, 252 });
-    expectedMapping.put(85, new int[] { 35, 260 });
-    expectedMapping.put(86, new int[] { 36, 268 });
-    expectedMapping.put(87, new int[] { 37, 275 });
-    expectedMapping.put(88, new int[] { 38, 287 });
-    expectedMapping.put(89, new int[] { 39, 293 });
-    expectedMapping.put(90, new int[] { 40, 299 });
-    expectedMapping.put(91, new int[] { 41, 310 });
-    expectedMapping.put(92, new int[] { 42, 315 });
-    expectedMapping.put(93, new int[] { 43, 319 });
-    expectedMapping.put(94, new int[] { 44, 325 });
-    expectedMapping.put(95, new int[] { 45, 331 });
-    expectedMapping.put(96, new int[] { 46, 337 });
-    expectedMapping.put(97, new int[] { 47, 343 });
-    expectedMapping.put(98, new int[] { 48, 349 });
-    expectedMapping.put(99, new int[] { 49, 354 });
-    expectedMapping.put(100, new int[] { 50, 358 });
-    expectedMapping.put(101, new int[] { 51, 367 });
-    expectedMapping.put(102, new int[] { 52, 375 });
-    expectedMapping.put(103, new int[] { 53, 384 });
-    expectedMapping.put(104, new int[] { 54, 391 });
-    expectedMapping.put(105, new int[] { 55, 395 });
-    expectedMapping.put(106, new int[] { 56, 401 });
-    expectedMapping.put(107, new int[] { 57, 409 });
-    expectedMapping.put(108, new int[] { 58, 417 });
-    expectedMapping.put(109, new int[] { 59, 426 });
-    expectedMapping.put(110, new int[] { 60, 434 });
-    expectedMapping.put(111, new int[] { 61, 442 });
-    expectedMapping.put(112, new int[] { 62, 451 });
-    expectedMapping.put(113, new int[] { 63, 457 });
-    expectedMapping.put(114, new int[] { 64, 468 });
-    expectedMapping.put(115, new int[] { 65, 476 });
-    expectedMapping.put(116, new int[] { 66, 484 });
-    expectedMapping.put(117, new int[] { 67, 492 });
-    expectedMapping.put(118, new int[] { 68, 500 });
-    expectedMapping.put(119, new int[] { 69, 509 });
-    expectedMapping.put(120, new int[] { 70, 517 });
-    expectedMapping.put(121, new int[] { 71, 525 });
-    expectedMapping.put(122, new int[] { 72, 534 });
-    expectedMapping.put(123, new int[] { 73, 538 });
-    expectedMapping.put(124, new int[] { 74, 552 });
-    expectedMapping.put(125, new int[] { 75, 559 });
-    expectedMapping.put(126, new int[] { 76, 567 });
-    expectedMapping.put(127, new int[] { 77, 574 });
-    expectedMapping.put(128, new int[] { 78, 580 });
-    expectedMapping.put(129, new int[] { 79, 585 });
-    expectedMapping.put(130, new int[] { 80, 590 });
-    expectedMapping.put(131, new int[] { 81, 602 });
-    expectedMapping.put(132, new int[] { 82, 609 });
-    expectedMapping.put(133, new int[] { 83, 616 });
-    expectedMapping.put(134, new int[] { 84, 622 });
-    expectedMapping.put(135, new int[] { 85, 630 });
-    expectedMapping.put(136, new int[] { 86, 637 });
-    expectedMapping.put(137, new int[] { 87, 644 });
-    expectedMapping.put(138, new int[] { 88, 652 });
-    expectedMapping.put(139, new int[] { 89, 661 });
-    expectedMapping.put(140, new int[] { 90, 668 });
-    expectedMapping.put(141, new int[] { 91, 678 });
-    expectedMapping.put(142, new int[] { 92, 687 });
-    expectedMapping.put(143, new int[] { 93, 696 });
-    expectedMapping.put(144, new int[] { 94, 705 });
-    expectedMapping.put(145, new int[] { 95, 714 });
-    expectedMapping.put(146, new int[] { 96, 722 });
-    expectedMapping.put(147, new int[] { 97, 729 });
+    expectedMapping.put(51, new int[] { 1, 2, 1 });
+    expectedMapping.put(52, new int[] { 2, 7, 2 });
+    expectedMapping.put(53, new int[] { 3, 12, 3 });
+    expectedMapping.put(54, new int[] { 4, 24, 4 });
+    expectedMapping.put(55, new int[] { 5, 33, 5 });
+    expectedMapping.put(56, new int[] { 6, 40, 6 });
+    expectedMapping.put(57, new int[] { 7, 47, 7 });
+    expectedMapping.put(58, new int[] { 8, 55, 8 });
+    expectedMapping.put(59, new int[] { 9, 62, 9 });
+    expectedMapping.put(60, new int[] { 10, 69, 10 });
+    expectedMapping.put(61, new int[] { 11, 76, 11 });
+    expectedMapping.put(62, new int[] { 12, 83, 12 });
+    expectedMapping.put(63, new int[] { 13, 87, 13 });
+    expectedMapping.put(64, new int[] { 14, 95, 14 });
+    expectedMapping.put(65, new int[] { 15, 102, 15 });
+    expectedMapping.put(66, new int[] { 16, 111, 16 });
+    expectedMapping.put(67, new int[] { 17, 122, 17 });
+    expectedMapping.put(68, new int[] { 18, 131, 18 });
+    expectedMapping.put(69, new int[] { 19, 137, 19 });
+    expectedMapping.put(70, new int[] { 20, 144, 20 });
+    expectedMapping.put(71, new int[] { 21, 152, 21 });
+    expectedMapping.put(72, new int[] { 22, 160, 22 });
+    expectedMapping.put(73, new int[] { 23, 167, 23 });
+    expectedMapping.put(74, new int[] { 24, 179, 24 });
+    expectedMapping.put(75, new int[] { 25, 187, 25 });
+    expectedMapping.put(76, new int[] { 26, 195, 26 });
+    expectedMapping.put(77, new int[] { 27, 203, 27 });
+    expectedMapping.put(78, new int[] { 28, 208, 28 });
+    expectedMapping.put(79, new int[] { 29, 213, 29 });
+    expectedMapping.put(80, new int[] { 30, 222, 30 });
+    expectedMapping.put(81, new int[] { 31, 231, 31 });
+    expectedMapping.put(82, new int[] { 32, 240, 32 });
+    expectedMapping.put(83, new int[] { 33, 244, 33 });
+    expectedMapping.put(84, new int[] { 34, 252, 34 });
+    expectedMapping.put(85, new int[] { 35, 260, 35 });
+    expectedMapping.put(86, new int[] { 36, 268, 36 });
+    expectedMapping.put(87, new int[] { 37, 275, 37 });
+    expectedMapping.put(88, new int[] { 38, 287, 38 });
+    expectedMapping.put(89, new int[] { 39, 293, 39 });
+    expectedMapping.put(90, new int[] { 40, 299, 40 });
+    expectedMapping.put(91, new int[] { 41, 310, 41 });
+    expectedMapping.put(92, new int[] { 42, 315, 42 });
+    expectedMapping.put(93, new int[] { 43, 319, 43 });
+    expectedMapping.put(94, new int[] { 44, 325, 44 });
+    expectedMapping.put(95, new int[] { 45, 331, 45 });
+    expectedMapping.put(96, new int[] { 46, 337, 46 });
+    expectedMapping.put(97, new int[] { 47, 343, 47 });
+    expectedMapping.put(98, new int[] { 48, 349, 48 });
+    expectedMapping.put(99, new int[] { 49, 354, 49 });
+    expectedMapping.put(100, new int[] { 50, 358, 50 });
+    expectedMapping.put(101, new int[] { 51, 367, 51 });
+    expectedMapping.put(102, new int[] { 52, 375, 52 });
+    expectedMapping.put(103, new int[] { 53, 384, 53 });
+    expectedMapping.put(104, new int[] { 54, 391, 54 });
+    expectedMapping.put(105, new int[] { 55, 395, 55 });
+    expectedMapping.put(106, new int[] { 56, 401, 56 });
+    expectedMapping.put(107, new int[] { 57, 409, 57 });
+    expectedMapping.put(108, new int[] { 58, 417, 58 });
+    expectedMapping.put(109, new int[] { 59, 426, 59 });
+    expectedMapping.put(110, new int[] { 60, 434, 60 });
+    expectedMapping.put(111, new int[] { 61, 442, 61 });
+    expectedMapping.put(112, new int[] { 62, 451, 62 });
+    expectedMapping.put(113, new int[] { 63, 457, 63 });
+    expectedMapping.put(114, new int[] { 64, 468, 64 });
+    expectedMapping.put(115, new int[] { 65, 476, 65 });
+    expectedMapping.put(116, new int[] { 66, 484, 66 });
+    expectedMapping.put(117, new int[] { 67, 492, 67 });
+    expectedMapping.put(118, new int[] { 68, 500, 68 });
+    expectedMapping.put(119, new int[] { 69, 509, 69 });
+    expectedMapping.put(120, new int[] { 70, 517, 70 });
+    expectedMapping.put(121, new int[] { 71, 525, 71 });
+    expectedMapping.put(122, new int[] { 72, 534, 72 });
+    expectedMapping.put(123, new int[] { 73, 538, 73 });
+    expectedMapping.put(124, new int[] { 74, 552, 74 });
+    expectedMapping.put(125, new int[] { 75, 559, 75 });
+    expectedMapping.put(126, new int[] { 76, 567, 76 });
+    expectedMapping.put(127, new int[] { 77, 574, 77 });
+    expectedMapping.put(128, new int[] { 78, 580, 78 });
+    expectedMapping.put(129, new int[] { 79, 585, 79 });
+    expectedMapping.put(130, new int[] { 80, 590, 80 });
+    expectedMapping.put(131, new int[] { 81, 602, 81 });
+    expectedMapping.put(132, new int[] { 82, 609, 82 });
+    expectedMapping.put(133, new int[] { 83, 616, 83 });
+    expectedMapping.put(134, new int[] { 84, 622, 84 });
+    expectedMapping.put(135, new int[] { 85, 630, 85 });
+    expectedMapping.put(136, new int[] { 86, 637, 86 });
+    expectedMapping.put(137, new int[] { 87, 644, 87 });
+    expectedMapping.put(138, new int[] { 88, 652, 88 });
+    expectedMapping.put(139, new int[] { 89, 661, 89 });
+    expectedMapping.put(140, new int[] { 90, 668, 90 });
+    expectedMapping.put(141, new int[] { 91, 678, 91 });
+    expectedMapping.put(142, new int[] { 92, 687, 92 });
+    expectedMapping.put(143, new int[] { 93, 696, 93 });
+    expectedMapping.put(144, new int[] { 94, 705, 94 });
+    expectedMapping.put(145, new int[] { 95, 714, 95 });
+    expectedMapping.put(146, new int[] { 96, 722, 96 });
+    expectedMapping.put(147, new int[] { 97, 729, 97 });
   }
 
   @BeforeTest(alwaysRun = true)
@@ -311,7 +311,7 @@ public class SiftsClientTest
     atom.atomIndex = 7;
     atoms.add(atom);
     int actualAtomIndex = siftsClient.getAtomIndex(1, atoms);
-    Assert.assertEquals(actualAtomIndex, -1);
+    Assert.assertEquals(actualAtomIndex, siftsClient.UNASSIGNED);
     actualAtomIndex = siftsClient.getAtomIndex(43, atoms);
     Assert.assertEquals(actualAtomIndex, 7);
   }